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 can use selector variants to name 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)">You can also create project-specific selector variants for longer selectors.
<div class="font:semibold_:headings"><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
Use a class selector for custom application state, such as .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, :even, and :nth(N) to style list items by position.
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:slate-5:even@light bg:gray-90:even@dark …">…</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:red:invalid b:green:valid b:1px|solid …" 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:open-quote::before content:close-quote::after …"> Be the change you wish to see in the world.</div>::scrollbar
Style scrollbars with ::scrollbar, ::scrollbar-thumb, ::scrollbar-track, ::scrollbar-button, ::scrollbar-corner, and ::scrollbar-track-piece shorthands.
Try scrolling horizontally and interact with the scroll bar
<div class="size:0.375rem::scrollbar bg:neutral-50/.2::scrollbar-thumb overflow-x:auto …">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 at-rule conditions for breakpoints, modes, media types, container queries, supports checks, and ranges.










