Repository navigation
[WIP] Block Supports: Remove global border style fallbacks - #78818
Draft
aaronrobertshaw wants to merge 5 commits into
Draft
aaronrobertshaw wants to merge 5 commits into
aaronrobertshaw wants to merge 5 commits into
Conversation
3 of 6 tasks
28 of 77 tasks
aaronrobertshaw
force-pushed
the
try/border-style-editor-defaults
branch
from
October 16, 2026 12:05
c86ec85 to
0d15af0
Compare
🤖 PR meta 🤖📦 Bundle sizeSize Change: -1.87 kB (-0.02%) Total Size: 9.04 MB 📦 View Changed
⚡ PerformanceShow the resultsClient side metrics exclude the server response time. front-end-block-theme
front-end-classic-theme
media-processing
media-upload
post-editor
site-editor
🏁 Flaky testsSome tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information. Regression: updating a specific option will only change its value and will not corrupt others in
|
aaronrobertshaw
force-pushed
the
try/border-style-editor-defaults
branch
from
October 20, 2026 05:21
b1a6bae to
f52e9f8
Compare
…me defaults Replace the legacy :where([style*='border-...']) fallback in block-library/common.scss with a cascade-aware, three-layer mechanism: 1. Edit-time intelligent default in the block-instance BorderPanel: when a user sets border color or width and no explicit or inherited (block-type or active block-style variation) style exists, persist border.style = 'solid' so saved attributes are self-describing. 2. Editor render-time fallback in useBlockProps: legacy unmigrated content (attributes carry color/width but no style) renders with visible borders in the editor wrapper. 3. Front-end render-time fallback via a render_block filter using WP_HTML_Tag_Processor: covers static and dynamic blocks, mirrors the JS cascade resolution. The CSS fallback removal eliminates the entire false-positive class that PR #77476 was patching around (inline styles whose substring matches 'border-color' / 'border-width' incorrectly gaining a forced solid style — e.g. background-image URLs, --border-color custom properties). Inheritance lookup covers block-type (styles.blocks[name].border) and active block-style variation. Root styles.border is intentionally excluded because it compiles to a body selector and border-style is not a CSS-inherited property. Tests: - 32 JS unit tests (helpers + no-mutation). - 28 PHPUnit tests mirroring the JS matrix plus gutenberg_get_variation_name_from_class and the render_block filter integration. - 3 Playwright E2E specs covering the original #77476 regression cases and legacy-content render-time fallback.
…eedback
- Drop the `__experimentalBorder.style` support gate from the
render_block fallback filter. Opting out of `style` block-support
prevents users from picking a style via UI; it does not mean a
block whose attributes carry a color or width should be rendered
invisibly. The legacy CSS `:where()` rule this replaces did not
gate on `style` support either, so the previous gate was a
silent regression for blocks that opt into color/width only.
- Add a quick-exit in both the PHP render_block filter and the JS
`useBlockProps` path when the block has no border-related
attributes at all. Avoids registry / theme-json resolver work and
preset-color resolution for the common case of border-supporting
blocks without border data set.
- Move `@wordpress/i18n` import into the WordPress dependencies
section, restoring the conventional ordering that the strict
eslint config enforces.
- Add a PHPUnit test asserting the fallback fires for blocks
registered with `__experimentalBorder: { color: true, width: true }`
(no `style` sub-feature).
aaronrobertshaw
force-pushed
the
try/border-style-editor-defaults
branch
from
October 21, 2026 05:17
f7d3f7d to
43b506e
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
This approach is open for evaluation. It removes the global CSS fallback from every page render, but it is not yet clear that the JS/PHP replacement is objectively better than simply keeping the recently tightened CSS rule.
What?
Follow up to #77476.
Replaces the legacy
:where([style*="border-…"])CSS visibility fallback for the border block support with a cascade-aware, edit-time intelligent default plus a render-time fallback for legacy content.Why?
The legacy CSS rule in
packages/block-library/src/common.scssforcedborder-style: solidon any element whose inline style attribute contained the substringborder-color,border-width, etc. That substring match produced false positives:• Any element with a CSS custom property such as
--border-color: redwas matched.• Any element with a
background-image: url(...border-color...)URL was matched.• Any future inline-style declaration containing those substrings would be matched.
#77476 mitigated the symptom by tightening the selectors. This PR removes the root cause: the CSS fallback itself.
The CSS fallback has carried a
// TODOfor a long time noting it should be replaced with "intelligent defaults" once edit-time context made that possible. That context now exists (useBlockSettings, the resolved global-styles tree exposed viaglobalStylesDataKey, and block-style variation resolution helpers).How?
Three coordinated mechanisms replace the one CSS rule. All are cascade-aware.
packages/block-editor/src/hooks/border.jsthe block-instanceBorderPanel.onChangenow calls a new pure helperapplyBorderStyleDefaults. When the user sets a border color or width and:• there is no explicit border.style on the value being persisted, AND
• there is no inherited global border style for the affected scope (shorthand vs. per-side),
then
style: 'solid'is persisted into the block'sattributes.style.border. Saved HTML becomes self-describing: no runtime fallback is needed to render the border. The sharedStylesBorderPanelused by the Global Styles UI is intentionally untouched, its mergedinheritedValuealready handles inheritance, so no change is needed there.Inheritance is resolved across two cascade levels:
•
styles.blocks[ name ].border(block-type global styles)•
styles.blocks[ name ].variations[ active ].border(active block style variation, derived from the block'sclassNamevia the sharedgetVariationNameFromClasshelper)Root
styles.border.styleis intentionally excluded, theme.json compiles it to abodyselector andborder-styleis not a CSS-inherited property, so it does not cascade to inner blocks. Non-rendering values (none, hidden) are also excluded so that a theme setting border.style: 'none' does not silently suppress the fallback when a user adds a color.The same
useBlockPropshook gains a render-time fallback viagetBorderStyleFallbacksso that blocks with saved attributes carrying color/width but no style still render visibly in the editor wrapper. The fallback flows throughBlockListBlockwrapper props; it does not mutate saved HTML.lib/block-supports/border.php, newgutenberg_render_block_border_fallbackhooked into therender_blockfilter, usingWP_HTML_Tag_Processorto inject per-sideborder-{side}-style: solidinto the wrapper's style attribute. Hooked intorender_blockrather thanapply_block_supportsbecauseWP_Block_Supports::apply_block_supports()is only invoked viaget_block_wrapper_attributes()from inside a dynamic block'srender_callback, static blocks (Group, Paragraph, Heading, …) serialize their wrapper attributes at save time and never reach that path. Therender_blockfilter covers both static and dynamic blocks.The PHP path mirrors the JS algorithm exactly. Both files cross-reference each other in doc comments. The PHP helper has a quick-exit when the block has no border-related attribute and shares the same none/hidden non-rendering style handling.
Removed
packages/block-library/src/common.scss — the entire :where(.has-border-color, [style*="border-…"]) fallback block (lines 114-162) is removed.
Testing Instructions
style.border.color(nostyle.border.style) — easiest via the Code Editor. Publish and view on the front end. Confirm the border still renders as solid (backward compatibility).styles.blocks.core/group.border.style= 'dashed', edit a Group block, add aborder.colorfrom the UI. Confirm the editor shows the inherited dashed border (not forced solid), and that style: 'solid' is not persisted into the block's attributes (cascade-aware).◦ Insert an HTML block with
<div style="background-image: url('/wp-content/uploads/border-color-thing.png');">…</div>. Publish and inspect the rendered output: the element must haveborder-style: none(computed), not solid.◦ Same with
<div style="--border-color: red;">…</div>.◦
npm run test:unit -- packages/block-editor/src/hooks/test/border.js(32 tests).◦
npm run test:unit:php -- --filter WP_Block_Supports_Border_Test(29 tests).◦
npm run test:e2e -- test/e2e/specs/editor/blocks/border-block-support.spec.js(3 tests).Screenshots or screencast
TBA