Compatibility
Learn browser support, native declaration fallback, vendor prefixes, modern CSS feature strategy, and how Master CSS coexists with third-party styles.
Overview
Master CSS is designed to work with modern browser features, existing CSS files, component libraries, and third-party stylesheets. Compatibility mostly depends on the CSS features your project uses and the way external styles enter the cascade.
Static extraction and server rendering generate regular CSS ahead of time. Runtime rendering uses the browser MutationObserver API to detect class changes and generate only the rules used by connected elements.
The default stylesheet uses native CSS cascade layers to keep theme, base, defaults, components, and utilities predictable:
@layer theme, base, defaults, components, utilities;That means Master CSS works best in projects that target browsers with cascade layer support. If your project must support older browsers, treat @layer support as the main compatibility boundary and test the generated CSS against your browser matrix.
Browser support
The Master CSS engine does not polyfill every CSS feature. It generates CSS from the classes you use, so browser support is usually determined by the final CSS property, value, selector, at-rule, or platform feature in that output.
For example, bg:red depends on normal background-color support, while backdrop-filter:blur(16px) depends on backdrop-filter support. Modern features should be checked in Can I use or MDN before relying on them in production.
Property-like classes can also fall back to native CSS declarations. In the browser runtime, Master CSS validates those declarations with CSS.supports(property, value). Static, server, extraction, compiler, validator, and linting workflows use a CSS syntax matcher so invalid declarations such as interpolate-size:banana do not emit CSS. High-frequency native properties such as spacing, sizing, radius, color, and timing still keep curated Master CSS token and unit behavior before this native validation step.
Use this rule of thumb:
- If the browser supports the generated CSS, Master CSS can use it.
- If the browser does not support the generated CSS, use a fallback, avoid that class for that target, or gate it behind a feature query when appropriate.
- If the class relies on a Master CSS runtime workflow, make sure the target browser supports the runtime APIs required by that workflow.
Vendor prefixes
Master CSS includes built-in vendor prefixes for common CSS properties and selectors, so you usually write the standard syntax and let the engine emit the compatibility form.
CSS properties
Write the unprefixed class:
<div class="backdrop-filter:blur(16px)">…</div>Generated CSS
@layer utilities { .backdrop-filter\:blur\(16px\) { -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px) }}CSS selectors
Use the Master CSS selector shorthand when one exists:
<div class="bg:#000::scrollbar">…</div>Generated CSS
@layer utilities { .bg\:\#000\:\:scrollbar::-webkit-scrollbar { background-color: #000 }}New CSS features
Master CSS does not need a built-in utility for every platform feature before you can try it. It recognizes many explicit CSS declarations directly, while still preserving Master CSS utilities, tokens, and shorthands when they exist.
Native declarations
Write a property-like class when the declaration is already valid CSS:
<article class="field-sizing:content interpolate-size:allow-keywords view-transition-name:card transition-behavior:allow-discrete">…</article>Generated CSS
@layer utilities { .field-sizing\:content { field-sizing: content } .interpolate-size\:allow-keywords { interpolate-size: allow-keywords } .transition-behavior\:allow-discrete { transition-behavior: allow-discrete } .view-transition-name\:card { view-transition-name: card }}Custom properties can use the same direct declaration form:
<section class="--card-gap:1rem">…</section>Generated CSS
@layer utilities { .--card-gap\:1rem { --card-gap: 1rem }}Master CSS syntax first
Native fallback is intentionally lower priority than Master CSS semantics. Curated aliases, token resolution, unit conversion, transform helpers, and shorthand utilities continue to use Master CSS semantics before a plain native declaration is considered.
<div class="mt:4x margin:1rem bg:red-60">…</div>Generated CSS
@layer theme { :root { --color-red-60: oklch(60.94% .2501 29.2) }}@layer utilities { .margin\:1rem { margin: 1rem } .bg\:red-60 { background-color: var(--color-red-60) } .mt\:4x { margin-top: 1rem }}This preserves the expected syntax model:
mt:4xuses a curated alias and emitsmargin-top:1rem.margin:1remwrites the native property value as-is and emitsmargin:1rem.bg:red-60resolves the theme token and emitsbackground-color:var(--color-red-60).- Rare native properties without Master CSS token behavior should use valid CSS values directly, such as
field-sizing:contentorinterpolate-size:allow-keywords. field-sizing:bananaandinterpolate-size:bananaare rejected instead of emitted as raw CSS.
Arbitrary properties
Arbitrary properties do not need {}. If the declaration is valid CSS, write it directly with property:value syntax:
<div class="interpolate-size:allow-keywords scroll-timeline-name:--cards paint-order:stroke|fill">…</div>Generated CSS
@layer utilities { .interpolate-size\:allow-keywords { interpolate-size: allow-keywords } .paint-order\:stroke\|fill { paint-order: stroke fill } .scroll-timeline-name\:--cards { scroll-timeline-name: --cards }}Use {...} only as an explicit raw escape hatch, or when several raw declarations should share one selector or query suffix. Static tooling may reject the newest CSS grammar until its syntax data catches up, while the browser runtime follows CSS.supports(property, value) for direct native declarations.
New selectors
Selector suffixes can use native CSS selector syntax as long as the browser supports the selector.
<form class="outline:2px|solid|red:has(:checked)">…</form>Generated CSS
@layer theme { :root { --color-red-60: oklch(60.94% .2501 29.2); --color-red-50: oklch(62.82% .25 28.6) } @media (prefers-color-scheme:light) { :root { --color-red: var(--color-red-60) } } @media (prefers-color-scheme:dark) { :root { --color-red: var(--color-red-50) } }}@layer utilities { .outline\:2px\|solid\|red\:has\(\:checked\):has(:checked) { outline: 2px solid var(--color-red) }}Third-party styles
Third-party libraries often ship CSS with their own selector strategy. Put vendor styles in a lower cascade layer when you want Master CSS components and utilities to override them without !important.
For example, import Swiper styles into the defaults layer:
@import 'swiper/css'; @import 'swiper/css/navigation'; @import 'swiper/css/pagination'; @import 'swiper/css' layer(defaults);@import 'swiper/css/navigation' layer(defaults);@import 'swiper/css/pagination' layer(defaults);Some bundlers may not support @import ... layer(...) for package CSS. Check your build tool before relying on layered package imports.
Master CSS is meant to sit in the CSS build workflow, so you usually do not need a separate preprocessor just to bundle imports, share variables, add prefixes, or generate utility classes. Prefer native CSS imports, cascade layers, CSS variables, and Master CSS tokens before reaching for Sass, Less, or Stylus.
If your project already uses a preprocessor, keep it at the edge of the workflow: compile it to regular CSS first, then make sure the resulting vendor rules enter the intended layer. Avoid making preprocessor-only features the recommended path for third-party compatibility.
Then define your application overrides in the components layer or use utilities in markup:
@components { swiper { @compose max-w:4xl; } swiper-wrapper { @compose bg:red-60; } swiper-slide { @compose bg:blue-60; }}<div class="swiper-slide bg:blue-60">Slide 1</div>This keeps vendor defaults below product components and utilities, reducing the need for forceful overrides.
Existing CSS workflows
Master CSS can coexist with native CSS, preprocessors, CSS modules, and framework <style> blocks. The most predictable setup is to keep one project CSS entry that imports @master/css, then let regular CSS files enter that graph through normal imports when they should share the same theme, layer order, extraction context, and native CSS pruning behavior.
Use native CSS variables from your theme when module-scoped or component-scoped CSS needs shared design values:
.button { background-color: var(--color-primary); border-radius: var(--radius-md);}Use Master CSS classes in markup for styling that should be generated, validated, ordered, and highlighted by Master CSS tooling:
<button class="bg:blue r:md px:md h:40px">Save</button>When a CSS file imports @master/css, it becomes a Master-managed stylesheet. Keep vendor, CMS, or externally injected classes outside managed roots unless the class usage is visible to extraction or protected with @preserve native.
Checklist
- Check browser support for the generated CSS feature, not just the Master CSS class.
- Treat native cascade layers as the main browser compatibility boundary for the default stylesheet.
- Write standard unprefixed properties and selectors when Master CSS already prefixes them.
- Use native declaration syntax for valid CSS declarations; reserve
{...}groups for explicit raw escape hatches or multi-declaration groups. - Keep curated Master CSS aliases, tokens, unit conversion, and shorthands ahead of native declaration fallback.
- Expect browser runtime validation and static validation to occasionally differ for the newest CSS grammar; test experimental declarations in the rendering mode you ship.
- Put third-party CSS in
defaultswhen you want components and utilities to override it. - Keep externally injected classes visible to extraction, outside managed roots, or protected from native CSS pruning.