[wp-trac] [WordPress Trac] #64939: Add opt-out mechanism for global admin CSS on individual elements
WordPress Trac
noreply at wordpress.org
Tue Mar 24 13:54:09 UTC 2026
#64939: Add opt-out mechanism for global admin CSS on individual elements
-------------------------+-----------------------------
Reporter: 0mirka00 | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: General | Version:
Severity: normal | Keywords:
Focuses: |
-------------------------+-----------------------------
== Problem
WordPress admin stylesheets (`forms.css`, `common.css`) apply broad, bare-
element selectors that set visual properties on elements like `input`,
`textarea`, `button`, `a`, `div`, `p`, and headings. For example:
{{{#!css
/* forms.css */
input[type="text"] { border: 1px solid #949494; min-height: 40px; /* ...
*/ }
/* common.css */
a, div { outline: 0; }
p { font-size: 13px; line-height: 1.5; margin: 1em 0; }
}}}
These rules work well for traditional wp-admin screens, but they conflict
with component libraries that manage their own element styles —
particularly those using CSS cascade layers, where unlayered admin styles
unconditionally win regardless of specificity.
This has been causing inconveniences for years, but is now becoming a
blocker for adopting modern CSS architectures like `@layer`. We have an
[https://github.com/WordPress/gutenberg/pull/76783 interim workaround] in
place for the `@wordpress/ui` package, but a Core-level solution would
benefit the broader ecosystem: any plugin or component library using
layered CSS, or simply wanting a clean styling baseline for its UI, faces
the same problem.
== Proposal
Add a `data-wp-no-global-css` attribute that opts individual elements out
of admin global styles. Each bare element selector in `forms.css` and
`common.css` would be guarded with `:where(:not([data-wp-no-global-
css]))`:
{{{#!css
/* Before */
input,
select,
textarea,
button {
box-sizing: border-box;
font-family: inherit;
font-size: inherit;
font-weight: inherit;
}
/* After */
:is(input, select, textarea, button):where(:not([data-wp-no-global-css]))
{
box-sizing: border-box;
font-family: inherit;
font-size: inherit;
font-weight: inherit;
}
}}}
An element with the attribute is simply excluded from the rule. Elements
without it are unaffected.
=== Design goals
- **Specificity-neutral** — `:where()` adds zero specificity, so existing
overrides of admin styles continue to work.
- **Per-element** — the guard is on each element selector, not an ancestor
wrapper, so there's no gap where the wrapper itself still receives admin
styles.
- **Package-agnostic** — usable by `@wordpress/components`,
`@wordpress/ui`, or any third-party component library.
- **Not a styling hook** — the attribute name describes an opt-out
behavior, not a component identity, so it doesn't invite misuse as a
selector by consumers.
- **Backwards compatible** — the default behavior (no attribute) is
identical to today.
=== Scope
Only the bare/unscoped element selectors in `forms.css` and `common.css`
need the guard — roughly the first ~335 lines of `forms.css` and the
element resets in `common.css`. Class-scoped rules (`.wp-admin ...`,
`.form-table ...`, etc.) are already sufficiently scoped and don't need
changes.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/64939>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list