Skip to content

Style: Stop link colours repainting block button labels - #849

Open
softglazee wants to merge 1 commit into
WordPress:trunkfrom
softglazee:fix/8418-planet-button-contrast
Open

Style: Stop link colours repainting block button labels#849
softglazee wants to merge 1 commit into
WordPress:trunkfrom
softglazee:fix/8418-planet-button-contrast

Conversation

@softglazee

@softglazee softglazee commented Sep 1, 2026

Copy link
Copy Markdown

Trac ticket: https://meta.trac.wordpress.org/ticket/8418

The problem

Buttons on https://planet.wordpress.org/ render their label in the body link colour on top of the button's own background, so the label is close to invisible.

State Colours Ratio
rest #21759b on #3858e9 1.09:1
hover #d54e21 on #3858e9 1.32:1
visited #4ca6cf on #3858e9 2.05:1

Why it happens

The block theme emits its button colours through global styles:

:root :where( .wp-block-button .wp-block-button__link ) {
	background-color: var( --wp--custom--button--color--background );
	color: var( --wp--custom--button--color--text );
}

That selector is specificity (0,1,0):root is the only thing that counts, :where() adds nothing.

The link rules in wp4.css are (0,1,1):

a:link,
a { color: #21759b; }

a:visited { color: #4ca6cf; }

a:hover   { color: #d54e21; }

So the link colour wins on color while the button keeps its own background-color. The custom properties are fine, --wp--custom--button--color--text resolves to #ffffff; they are simply being overridden.

a:hover and a:visited have always been (0,1,1), so those two states have been wrong for a while. The rest state broke when a:link was added alongside a: a on its own is (0,0,1), which loses to the button rule. wp4-rtl.css has not been regenerated since that change, which is why it still has a bare a and why the rest state still looks correct in RTL.

The change

Guard the three link rules with :where( :not( .wp-element-button ) ). :where() contributes zero specificity, so (0,1,1) and (0,0,1) are unchanged and nothing else in the cascade shifts; only the match set narrows. This is the idiom core already uses on the same pages, for example :root :where( a:where( :not( .wp-element-button ) ):hover ).

Excluding buttons from a:hover also removes the only hover feedback Planet had, so this adds the hover, focus and active states from the button custom properties the wporg parent theme already defines. Pages that load the parent theme's button stylesheet are unaffected: those rules are [class*="wp-block"] .wp-block-button__link:hover at (0,2,0) and load after wp4.css.

The same change is applied to wp4-rtl.css, which is generated by grunt css. That file already looks out of date relative to wp4.css, so this PR makes the equivalent change rather than regenerating it, to keep the diff reviewable.

Testing

Measured on https://planet.wordpress.org/ with wp4.css swapped for the patched file at the same position in the cascade.

State Before After
rest #21759b on #3858e9, 1.09:1 #ffffff on #3858e9, 5.61:1
hover #d54e21 on #3858e9, 1.32:1 #ffffff on #213fd4, 7.70:1
active not styled #ffffff on #1e1e1e, 16.67:1

The hover result matches https://wordpress.org/download/, which does not load wp4.css and gets these states from the parent theme.

No regressions found on the Planet front page:

  • 1,335 non-button links keep #21759b. The full link colour census is identical before and after.
  • The search icon button is unchanged at rgb(30, 30, 30).
  • Buttons no longer match the link rules; ordinary links still do.

Steps to reproduce the original bug

  1. Visit https://planet.wordpress.org/
  2. Look at the "Read the Letter", "Download WordPress 7.1" and "Check out what's new in 7.1" buttons.
  3. The labels are the body link colour on the button background, and turn orange on hover.

Screenshots of the before and after states are on the Trac ticket.

Summary by CodeRabbit

  • Style
    • Improved button link styling for clearer hover, focus, and active states.
    • Prevented generic link colors from overriding block button appearance.
    • Added fallback colors to maintain consistent button styling across themes and configurations.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props softglaze, valani9099.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: b3e92c80-1ba9-4be0-8842-338ff6659aff

📥 Commits

Reviewing files that changed from the base of the PR and between ff6ffab and fa7d2e9.

📒 Files selected for processing (2)
  • wordpress.org/public_html/style/wp4-rtl.css
  • wordpress.org/public_html/style/wp4.css

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The LTR and RTL stylesheets exclude block button links from generic link colors. They add hover, focus, and active styles that use WordPress button custom properties with fallback colors.

Changes

Block button styling

Layer / File(s) Summary
Exclude block buttons from generic links
wordpress.org/public_html/style/wp4.css, wordpress.org/public_html/style/wp4-rtl.css
Generic, visited, and hover link selectors now exclude .wp-element-button links.
Define block button states
wordpress.org/public_html/style/wp4.css, wordpress.org/public_html/style/wp4-rtl.css
Hover, focus, and active rules set button text and background colors from WordPress button custom properties with fallback values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to fa7d2

This localized stylesheet change fixes button label contrast while preserving ordinary link styling and adding button interaction states. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing generic link colours from repainting block button labels.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

The link rules in wp4.css are more specific than the button colours the
block theme emits. Core emits

    :root :where( .wp-block-button .wp-block-button__link )

which is specificity (0,1,0), because :where() adds nothing. The link
rules `a:link`, `a:visited` and `a:hover` are (0,1,1), so they win and
repaint button labels with the body link colour while the button keeps
its own background.

On Planet that renders #21759b on #3858e9, a contrast ratio of 1.09:1,
and #d54e21 on #3858e9 on hover, 1.32:1.

Guard the three link rules with :where( :not( .wp-element-button ) ),
which leaves their specificity unchanged so nothing else in the cascade
moves, and is the same idiom core already uses for
:root :where( a:where( :not( .wp-element-button ) ):hover ).

Excluding buttons from a:hover also removes the only hover feedback
Planet had, so add the hover, focus and active states from the button
custom properties the wporg parent theme already defines. Pages that
load the parent theme's button stylesheet are unaffected: those rules
are (0,2,0) and load later.

Measured on planet.wordpress.org:

    rest    #ffffff on #3858e9   5.61:1  (was 1.09:1)
    hover   #ffffff on #213fd4   7.70:1  (was 1.32:1)
    active  #ffffff on #1e1e1e  16.67:1

The hover result matches wordpress.org/download/, which does not load
wp4.css and gets these states from the parent theme.

Ordinary links are untouched: 1,335 non-button links on the Planet front
page keep #21759b, and the search icon button is unchanged.

See https://meta.trac.wordpress.org/ticket/8418
@softglazee
softglazee force-pushed the fix/8418-planet-button-contrast branch from fa7d2e9 to cdae1af Compare September 1, 2026 03:24
@nikvalani96

Copy link
Copy Markdown

@softglazee Thanks for looking into this and creating the PR! The changes look good.

@nikvalani96

Copy link
Copy Markdown

Thanks again for preparing the fix. Since this PR addresses the issue I identified in Meta Trac #8418, could I please be included in the props when it is merged, if applicable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants