Skip to main content

Keys

All 149 keys ss() accepts — base, breakpoints, max-width ranges, pseudo-classes, pseudo-elements, media queries, group-* and peer-* states.

The full list

ss accepts base plus Tailwind's own keys — 149 in total, and nothing else. That closed set is what makes autocomplete exhaustive and a mistyped variant a compile error rather than a class with no rule behind it.

All 149 keys ss accepts, grouped by kind.
GroupCountKeys
base1unprefixed classes
Breakpoints5sm md lg xl 2xl
Max-width ranges5max-sm max-md max-lg max-xl max-2xl
Pseudo-classes34hover focus focus-within focus-visible active visited target first last only odd even first-of-type last-of-type only-of-type empty disabled enabled checked indeterminate default optional required valid invalid user-valid user-invalid in-range out-of-range placeholder-shown autofill read-only open inert
Pseudo-elements10before after first-letter first-line marker selection file backdrop placeholder details-content
Media & feature queries17dark motion-safe motion-reduce contrast-more contrast-less forced-colors inverted-colors portrait landscape print noscript pointer-fine pointer-coarse pointer-none any-pointer-fine any-pointer-coarse any-pointer-none
Direction & transition3rtl ltr starting
Descendants2* (direct children) ** (all descendants)
group-*36parent state — group-hover group-focus group-checked group-open …
peer-*36sibling state — peer-hover peer-checked peer-invalid …

Nested groups

A bucket value can be another map, which stacks the prefixes. Every nested group takes the same 149 keys under the same rules, and that is how a compound variant is spelled — the ss page has the nesting rules in full.

Nested groups
ss({  base: "text-black p-4",  md: {    base: "p-6",       // → md:p-6    hover: "p-8",      // → md:hover:p-8    "max-lg": "grid",  // → md:max-lg:grid  },});

Keys containing a hyphen — max-lg, group-hover, motion-reduce — are quoted, as any JavaScript object key with a hyphen has to be.

Deliberately absent

Anything with a value of its own is absent by design: data-*, aria-*, supports-*, has-*, not-* and arbitrary queries such as min-[…]. A key that carries an open-ended value cannot be one entry in a finite list, so it cannot be completed or checked — those variants get their own helpers instead.

  • data and aria — attribute variants, for headless UI libraries.
  • withPrefix — the escape hatch for every other Tailwind variant.
withPrefix
withPrefix("supports-[display:grid]", "grid");  // → "supports-[display:grid]:grid"withPrefix("has-[:checked]", "bg-blue-50");     // → "has-[:checked]:bg-blue-50"withPrefix("group-[.open]", "rotate-90");       // → "group-[.open]:rotate-90"

Exported at runtime

The lists themselves are exported, so JavaScript can read the same values the classes use. screens maps a breakpoint to its width; stateKeys, screenKeys and maxScreenKeys are the key names.

Also exported
import { screens, screenKeys, maxScreenKeys, stateKeys } from "tailess"; window.matchMedia(`(min-width: ${screens.md})`).matches;  // "48rem"

Generated, then checked

stateKeys is regenerated and re-verified against the Tailwind compiler in CI, and the test suite asserts real generated rules for every one of the 149 keys on Tailwind 4.3.3.