State Selectors
Learn how to append selectors for hover, focus, attributes, descendants, pseudo-elements, and custom states.
Overview
<div class="fg:blue-60:hover"></div><input class="border:red:invalid" /><details class="bg:white[open]" open></details>State selectors let one declaration apply only when a selector matches. Append the selector after the declaration value:
property:value<selector>Common examples include interaction states such as :hover, validation states such as :invalid, and attributes such as [disabled] or [open].
<h2 class="font:lg font:2xl:hover font:3xl:active …">Selectors can be stacked when the CSS selector itself needs more detail.
<div class="bg:blue-20:hover:not(.active) …">If you also need a breakpoint, mode, or other condition, put the conditional query after the selector.
<button class="bg:blue-60:hover@md">Save</button>For readability, Master CSS includes built-in selector aliases for selectors that appear often.
<div class="mt:sm:first"><div class="mt:sm:first-child"><div class="mt:sm:odd"><div class="mt:sm:nth-child(2n)"><div class="mt:sm:rtl"><div class="mt:sm:dir(rtl)">Write longer project-specific selectors directly.
<div class="font:semibold_:is(h1,h2,h3,h4,h5,h6)">Basic selectors
Master CSS accepts native selector syntax. The selector is relative to the element that owns the class unless a combinator points to another element.
| Selector | Description | Preview CSS |
|---|---|---|
* | Universal selector | * { margin: 0; } |
element | Type selector | p { color: red; } |
.class | Class selector .box { padding: 1rem; } | |
#id | ID selector | #header { background: blue; } |
[attribute] | Attribute selector | [disabled] { opacity: 0.5; } |
:pseudo-class | Pseudo-class selector | a:hover { color: blue; } |
::pseudo-element | Pseudo-element selector | p::first-letter { font-size: 2em; } |
* — Universal
Use * as a wildcard. In >*, every direct child matches.
<div class="bg:blue-60>*"> <div>hit</div> <div>hit</div> ...</div>element
Use a type selector to target elements by tag name.
<div class="bg:blue-60>span"> <span>hit</span></div>If a raw type selector is hard to read or conflicts with nearby syntax, wrap it with :is() or :where().
<span class="bg:blue-60:is(span)"></span>.class
a application as class custom for selector state, such Use .active, .selected, or .expanded.
<div class="bg:blue-60.active active">...</div>#id
Use an ID selector when the state is tied to a unique element.
<nav id="nav" class="bg:blue-60#nav">...</nav>[attribute]
Use attribute selectors for DOM state that already lives in markup, such as [disabled], [open], aria-*, and data-*.
<button class="bg:blue-60[disabled]" disabled>Submit</button>:pseudo-class
Use pseudo-classes for browser-managed states.
<button class="bg:blue-60:hover">Submit</button>::pseudo-element
Use pseudo-elements such as ::before and ::after when the style should target generated content.
<div class="content:'“'::before">quotes</div>Combinators
Combinators target elements by their relationship to the element that owns the class. Use them when the declaration should style a child, sibling, or descendant instead of the element itself.
| Selector | Description | Preview CSS |
|---|---|---|
A B | Descendant selector (_) | nav a { color: white; } |
A > B | Child selector | ul > li { list-style: none; } |
A + B | Adjacent sibling selector | h1 + p { margin-top: 0; } |
A ~ B | General sibling selector | h1 ~ p { color: gray; } |
_ — Descendant
Use _ as the descendant combinator. It stands in for the CSS space, because spaces split class names in HTML.
<div class="bg:blue-60_div"> <div>hit</div> <div>hit <div>hit <div>hit</div> </div> </div></div>> — Child
Use > when only direct children should match.
<div class="bg:blue-60>div"> <div>hit</div></div>+ — Adjacent sibling
Use + to style the next sibling when it appears immediately after the current element.
<div class="bg:blue-60+div"></div><div>hit</div>~ — General sibling
Use ~ to style later siblings that share the same parent.
<div class="bg:blue-60~div"></div><div>hit</div><div>hit</div><div>hit</div>Selector groups
Use , when the same declaration should apply to several selectors.
<div class="content:'“'::before,::after">quotes</div>Generated CSS
@layer utilities { .content\:\'“\'\:\:before\,\:\:after::before, .content\:\'“\'\:\:before\,\:\:after::after { content: '“' }}Selector groups also work with combinators. In this example, the declaration applies to direct div and span children.
<div class="block>div,>span">hit</div>Generated CSS
@layer utilities { .block\>div\,\>span>div, .block\>div\,\>span>span { display: block }}Pseudo-classes
:hover, :active, :focus
Use interaction pseudo-classes to give controls feedback as people hover, press, focus, or navigate with a keyboard.
Try clicking the button to see states change
<button class="bg:blue-60 fg:white bg:blue-70:hover bg:blue-80:active">Submit</button>Use :focus-visible for keyboard focus rings when you want to avoid showing the focus style after every pointer click.
<button class="outline:2px|solid|blue:focus-visible">Submit</button>:first, :last, :odd, :even
Use structural shorthands such as :first, :last, :odd, and :even to style list items by position. Write native selectors such as :nth-child(N) directly when they are clearer.
Dressing TableA dress-up space.
Double BedA sweet moment for everyone.
SofaA place to be lazy all day.
CabinetSecrets are hidden here.
DeskA good partner in the office.
<ul class="…"> <li class="bg:gray-90:even@dark bg:slate-5:even@light …">…</li></ul>:valid, :invalid, :required
Use form validation pseudo-classes to reflect native validity without writing JavaScript state.
Try typing co as a valid email address
<input class="b:1px|solid b:green:valid b:red:invalid …" type="email" />:disabled
Use :disabled for controls that cannot be interacted with.
<button class="opacity:.5:disabled" disabled>Submit</button>:checked, :indeterminate
Use :checked and :indeterminate for checkboxes, radio buttons, switches, and custom controls backed by native inputs.
<input class="bg:blue-60:checked …" type="checkbox" checked />:rtl, :ltr
Use :rtl and :ltr to react to text direction. They map to :dir(rtl) and :dir(ltr).
<div class="mr:xs:rtl">...</div>:has()
Use :has() when the current element should change because it contains a matching child or descendant.
<div class="bg:blue-60:has(.active)"> <div>Item 1</div> <div class="active">Item 2</div> <div>Item 3</div></div>:not()
Use :not() to exclude a selector from the match.
<div class="fg:green-60:not(.active) active">...</div>:of()
:of() is the only proprietary selector introduced by Master CSS. It lets the current element respond to a parent, ancestor, or previous sibling. Use native selectors first when they can express the relationship; use :of() when you need to style the current element from outside-in context.
Style the element when an ancestor matches.
<div class="active"> <div> <div class="hidden:of(.active)">hidden</div> </div></div>Style the element when its parent matches.
<div class="active"> <div class="hidden:of(.active>)">hidden</div></div>Style the element when its previous adjacent sibling matches.
<div class="active"></div><div class="hidden:of(.active+)">hidden</div>Style the element when one of its preceding siblings matches.
<div class="active"></div><div></div><div class="hidden:of(.active~)">hidden</div>Do not put combinators or pseudo-elements before :of().
<div class="hidden_div::before:of(.active)">hidden</div>Pseudo-elements
::before, ::after
Use ::before and ::after to style generated content attached to the element.
Be the change you wish to see in the world.
<div class="content:close-quote::after content:open-quote::before …"> Be the change you wish to see in the world.</div>::scrollbar
Style common scrollbar surfaces with ::scrollbar, ::scrollbar-thumb, and ::scrollbar-track shorthands. Write native vendor selectors such as ::-webkit-scrollbar-corner directly for less common parts.
Try scrolling horizontally and interact with the scroll bar
<div class="overflow-x:auto size:0.375rem::scrollbar bg:neutral-50/.2::scrollbar-thumb …">Attribute selectors
[open]
Use [open] to style a <details> element while it is expanded.
<details class="bg:white[open]" open> <summary>Details</summary> <p>Details content goes here.</p></details>[aria-<key>=<value>]
Use ARIA attributes when accessible state is already present in the DOM.
<div class="bg:blue-60[aria-checked=true]" aria-checked="true">...</div>[data-<key>=<value>]
Use data-* attributes for component state that is not covered by native attributes or ARIA.
<div class="bg:blue-60[data-active]" data-active>...</div>[<attr>=<value>]
Match an exact attribute value.
<input class="b:blue[type=checkbox]" type="checkbox" />[<attr>^=<value>]
Match values that start with a specific string.
Links that start with http.
<a class="content:'↗'[href^=http]::after" href="https://…">External</a>[<attr>$=<value>]
Match values that end with a specific string.
<a class="content:'⬇'[href$='.pdf']::after" href="https://….pdf">PDF</a>[<attr>*=<value>]
Match values that contain a specific string.
<div class="bg:blue-60[title*=master]" title="mastercss">...</div>[<attr>|=<value>]
Match a value exactly or followed by a hyphen, which is common for language codes.
<div class="bg:blue-60[lang|=en]" lang="en-US">...</div>[<attr>~=<value>]
Match one word inside a whitespace-separated attribute value.
<div class="bg:blue-60[title~=css]" title="master css">...</div>Learn how Master CSS turns class names into CSS declarations, values, units, functions, variables, and shorthands.
Learn how to append condition suffixes for breakpoints, modes, media types, container queries, supports checks, and ranges.










