Syntax & rules

Selectors

States, combinators, pseudo-elements and selector groups.

Overview

HTML
<button type="button" class="fg-blue-60:hover">Preview</button><label>Email <input type="email" class="b-red:invalid" /></label><details class="surface-raised[open]">  <summary>Release details</summary>  <p>Published today.</p></details>

State selectors let one declaration apply only when a selector matches. Append the selector after the declaration value:

TXT
property:value<selector>

Common examples include interaction states such as :hover, validation states such as :invalid, and attributes such as [disabled] or [open].

HTML
<h2 class="font-lg font-2xl:hover font-3xl:active">Release notes</h2>

Selectors can be stacked when the CSS selector itself needs more detail.

HTML
<div class="bg-blue-20:hover:not(.active)">Preview</div>

If you also need a breakpoint, mode, or other condition, put the conditional query after the selector.

HTML
<button type="button" class="bg-blue-60:hover@md">Save</button>

For readability, Master CSS includes built-in selector aliases for selectors that appear often.

HTML
<div class="mt-sm:first"></div><div class="mt-sm:first-child"></div><div class="mt-sm:odd"></div><div class="mt-sm:nth-child(odd)"></div><div class="mt-sm:rtl"></div><div class="mt-sm:dir(rtl)"></div>

Write longer project-specific selectors directly.

HTML
<div class="font-semibold_:is(h1,h2,h3,h4,h5,h6)"></div>

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.

SelectorDescription
*Universal selector
elementType selector
.classClass selector
#idID selector
[attribute]Attribute selector
:pseudo-classPseudo-class selector
::pseudo-elementPseudo-element selector
CSS
@layer theme {  :root,  :host {    --color-blue-60: oklch(51.83% .2687 266.1);    --color-red: var(--color-red-60);    --color-red-60: oklch(60.94% .2501 29.2);    --color-red-50: oklch(62.82% .25 28.6);    --color-surface-raised: oklch(100% 0 none);    --color-gray-90: oklch(23.5% 0 none)  }  @media (prefers-color-scheme:light) {    :root {      --color-red: var(--color-red-60);      --color-surface-raised: oklch(100% 0 none)    }  }  @media (prefers-color-scheme:light) {    :host {      --color-red: var(--color-red-60);      --color-surface-raised: oklch(100% 0 none)    }  }  @media (prefers-color-scheme:dark) {    :root {      --color-red: var(--color-red-50);      --color-surface-raised: var(--color-gray-90)    }  }  @media (prefers-color-scheme:dark) {    :host {      --color-red: var(--color-red-50);      --color-surface-raised: var(--color-gray-90)    }  }}@layer utilities {  .b-red\:invalid:invalid {    border-color: var(--color-red)  }  .surface-raised\[open\][open] {    background-color: var(--color-surface-raised)  }  .bg-blue-60\.active.active {    background-color: var(--color-blue-60)  }}

* — Universal

Use * as a wildcard. In >*, every direct child matches.

HTML
<div class="bg-blue-60>*">  <div>hit</div>  <div>hit</div></div>

element

Use a type selector to target elements by tag name.

HTML
<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().

HTML
<span class="bg-blue-60:is(span)"></span>

.class

Use an application class such as .active, .selected, or .expanded to represent state. The element must have both the utility class and the matching state class.

HTML
<div class="bg-blue-60.active active">...</div>

#id

Use an ID selector when the state is tied to a unique element.

HTML
<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-*.

HTML
<button type="button" class="bg-blue-60[disabled]" disabled>Submit</button>

:pseudo-class

Use pseudo-classes for browser-managed states.

HTML
<button type="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.

HTML
<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.

SelectorDescription
A BDescendant selector (_)
A > BChild selector
A + BAdjacent sibling selector
A ~ BGeneral sibling selector

_ — Descendant

Use _ as the descendant combinator. It stands in for the CSS space, because spaces split class names in HTML.

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.

HTML
<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.

HTML
<div class="bg-blue-60+div"></div><div>hit</div>

~ — General sibling

Use ~ to style later siblings that share the same parent.

HTML
<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.

HTML
<div class="content:'“'::before,::after">quotes</div>

Generated CSS

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.

HTML
<div class="block>div,>span">  <div>First child</div>  <span>Second child</span></div>

Generated CSS

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.

Hover or press the button to match the corresponding state. Include an explicit keyboard focus treatment.

HTML
<button type="button" class="bg-blue-60 fg-white bg-blue-70:hover outline:2px|solid|var(--color-blue):focus-visible bg-blue-80:active">Preview</button>

Use :focus-visible when the browser should decide whether to show a focus ring, including keyboard navigation. Keep focus visible instead of removing outlines without a replacement.

HTML
<button type="button" class="outline:2px|solid|var(--color-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.

HTML
<ul>  <li class="surface-muted:even">Draft</li>  <li class="surface-muted:even">In review</li>  <li class="surface-muted:even">Published</li></ul>

:odd maps to :nth-child(odd); :even maps to :nth-child(2n). Positions count all element siblings, not only siblings that carry the same class.

CSS
@layer theme {  :root,  :host {    --color-surface-muted: var(--color-neutral-5);    --color-neutral-5: oklch(96.8% .0048 253);    --color-gray-100: oklch(14.5% 0 none);    --spacing-sm: .75rem  }  @media (prefers-color-scheme:light) {    :root {      --color-surface-muted: var(--color-neutral-5)    }  }  @media (prefers-color-scheme:light) {    :host {      --color-surface-muted: var(--color-neutral-5)    }  }  @media (prefers-color-scheme:dark) {    :root {      --color-surface-muted: var(--color-gray-100)    }  }  @media (prefers-color-scheme:dark) {    :host {      --color-surface-muted: var(--color-gray-100)    }  }}@layer utilities {  .surface-muted\:even:nth-child(2n) {    background-color: var(--color-surface-muted)  }  .mt-sm\:odd:nth-child(odd) {    margin-top: var(--spacing-sm)  }}

:valid, :invalid, :required

Use form validation pseudo-classes to reflect native validity without writing JavaScript state.

The required field is invalid while empty or while its value fails native email validation. The visible label supplies its accessible name.

HTML
<label for="contact-email">Email</label><input id="contact-email" type="email" required  class="b:1px|solid b-green:valid b-red:invalid outline:2px|solid|var(--color-blue):focus-visible" />

Use :required to select required controls regardless of whether their current value is valid. Avoid communicating validation through color alone; production forms should also explain the error in text.

:disabled

Use :disabled for controls that cannot be interacted with.

HTML
<button type="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.

HTML
<label>  <input class="outline:2px|solid|var(--color-blue):checked" type="checkbox" checked />  Include archived items</label>

indeterminate is a DOM property, not an HTML attribute. Set it from JavaScript when a checkbox represents a partially selected group; style that state with :indeterminate. It does not change the checkbox's submitted checked value.

HTML
<label><input id="select-all" type="checkbox" class="outline:2px|solid|var(--color-blue):indeterminate" /> Select all</label>
JS
document.querySelector('#select-all').indeterminate = true

:rtl, :ltr

Use :rtl and :ltr to react to text direction. They map to :dir(rtl) and :dir(ltr).

HTML
<div dir="rtl" class="mr-xs:rtl">مرحبا</div>

:has()

Use :has() when the current element should change because it contains a matching child or descendant.

HTML
<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.

HTML
<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.

HTML
<div class="active">  <div>        <div class="hidden:of(.active)">hidden</div>  </div></div>

Style the element when its parent matches.

HTML
<div class="active">    <div class="hidden:of(.active>)">hidden</div></div>

Style the element when its previous adjacent sibling matches.

HTML
<div class="active"></div><div class="hidden:of(.active+)">hidden</div>

Style the element when one of its preceding siblings matches.

HTML
<div class="active"></div><div></div><div class="hidden:of(.active~)">hidden</div>

Do not put combinators or pseudo-elements before :of(). The following order is unsupported:

HTML
<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.

HTML
<span class="content:close-quote::after content:open-quote::before">  Keep the interface clear.</span>

::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.

These aliases generate ::-webkit-scrollbar* selectors. Their effect depends on browser support and the platform scrollbar settings; overlay scrollbars may remain hidden until scrolling.

HTML
<div tabindex="0" role="region" aria-label="Scrollable schedule"  class="overflow-x:auto max-w:100% width:0.375rem::scrollbar height:0.375rem::scrollbar bg-neutral-50/.2::scrollbar-thumb">  <p class="w-7xl">Monday · Tuesday · Wednesday · Thursday · Friday</p></div>

Attribute selectors

[open]

Use [open] to style a <details> element while it is expanded. The browser updates the attribute when the user toggles its summary.

HTML
<details class="surface-raised[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.

HTML
<button type="button" class="bg-blue-60[aria-pressed=true] fg-white[aria-pressed=true]" aria-pressed="true">Bold</button>

Choose an attribute that is valid for the control, and update it as part of the control behavior. A selector only reads state; it does not implement the interaction or make an arbitrary element accessible.

[data-<key>=<value>]

Use data-* attributes for component state that is not covered by native attributes or ARIA.

HTML
<div class="bg-blue-60[data-active]" data-active>...</div>

[<attr>=<value>]

Match an exact attribute value. Pseudo aliases only expand at actual pseudo selectors: [data-state=":first"]:first keeps the attribute value :first and expands the final :first to :first-child. Escaped identifier characters also remain literal.

HTML
<label><input class="accent-color-blue[type=checkbox]" type="checkbox" /> Enable alerts</label>

[<attr>^=<value>]

Match values that start with a specific string.

This matches links whose attribute starts with http; it does not distinguish same-origin from external links.

HTML
<a class="content:'↗'[href^=http]::after" href="https://example.com">External</a>

[<attr>$=<value>]

Match values that end with a specific string.

HTML
<a class="content:'⬇'[href$='.pdf']::after" href="https://example.com/report.pdf">PDF</a>

[<attr>*=<value>]

Match values that contain a specific string.

HTML
<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.

HTML
<div class="bg-blue-60[lang|=en]" lang="en-US">...</div>

[<attr>~=<value>]

Match one word inside a whitespace-separated attribute value.

HTML
<div class="bg-blue-60[title~=css]" title="master css">...</div>

© 2026 Aoyue Design LLC.MIT License
Trademark Policy