CSS
CSS is the UI runtime, not just styling. CSS replaces all front-end JavaScript except data delivery.
CSS owns
Every visible UI behavior. Layout, theme, color-scheme, visibility, transitions, loading indicators, navigation appearance, form validation display, scrollbar styling, animations, focus indication. CSS owns everything in the presentation layer except API CRUD data transport.
JavaScript is strictly forbidden for anything in the presentation latyer except for API CRUD data transport. All presentation layer behavior MUST be expressed in CSS, CSS expresses it. The single permitted JavaScript responsibility is data transport — see the javascript skill.
Universal CSS rules
The following apply across every CSS file in the project:
- Layers. All CSS belongs to a
@layer. The cascade order is declared once at the project root:@layer reset, fonts, layout, typography, themes, transitions, inputs, media, state, loading;. Skill features are layered into the appropriate name. Specificity wars are won by layer order, not by!importantor selector escalation. - No
!important. Ever. If a style needs to win, fix the layer order or the selector specificity by design, not by escalation. - No magic numbers. Every measurement is a named custom property, a
clamp()expression, a container query unit, a logical property, or derived viacalc()from another value. Sizing uses intrinsic and relative units only —min-content,max-content,fit-content,auto,1fr,clamp(), viewport units, container query units. - No size-based
@media. Responsive design uses@container(preferred) or media query range syntax (@media (600px <= width <= 1200px)) only. Static breakpoints withmin-width/max-widthare forbidden — they hardcode viewport assumptions. - No Flexbox. CSS Grid only. Justification: Grid is two-dimensional, declarative, and intrinsic-sizing-aware; Flexbox encourages wrapper nesting that violates the HTML "no layout wrappers" rule.
color-scheme: light darkis declared once at:root. Themes uselight-dark()for paired values, not duplicated@media (prefers-color-scheme: dark)blocks.oklchis the color model for any color the project defines.hsl,hex, andrgbare forbidden for project colors. (Browser-default values likeCanvasandcurrentColorare fine.)- Logical properties.
margin-inline,padding-block,inset-block-startetc. — noleft/right/top/bottomfor layout in the document flow. :where()for resets. Specificity-zero selectors so consumer rules always win.
Required modern features
The architecture mandates these specific modern CSS features for these specific tasks. Each rule is categorical (the rule plus its failure mode):
- CSS uses native accessibility-aware selectors (
:focus-visible,:user-invalid,:user-valid,:disabled,[aria-*]matchers, etc.) to bake accessibility into styling rather than relying on classes or scripted state. - Initial-load page content fades in via
@starting-style. JavaScript does not orchestrate entry animations. - Same-document (SPA tab) content transitions come from the universal
*transition +transition-behavior: allow-discrete;@view-transitionopts into transitions on cross-document navigations only. JavaScript does not animate tab changes — it only injects data, and CSS transitions it. (Same-document view transitions would require the JSdocument.startViewTransition()API, which is forbidden here.) - Hover and popover content uses CSS anchor positioning (
anchor-name/position-anchor) to keep content on-screen. Hand-rolled positioning math via JS or magic numbers is forbidden. - Cutting-edge experimental CSS is used without regard for browser support. Cross-browser compatibility is not a concern.
- Component-relative styling uses
@containerqueries. Components respond to their actual available space, not to viewport breakpoints. - Inline conditional values use
if()against custom properties / media features / container queries instead of toggling classes from JS. - Custom properties that need typing or animation are declared via
@propertyso the browser interpolates and validates them. - Reusable CSS calculations use
@function. Sass/Less mixins are not used. - Feature detection uses
@supports. JS-based feature detection (Modernizr, computed-style probing) is not used. - Lazy rendering / size containment uses
content-visibility+contain-intrinsic-size. JS-based IntersectionObserver visibility is not used.
CSS reads only the DOM and data attributes
CSS reads:
- The DOM tree shape
- Native attributes (
open,hidden,aria-*,checked,selected) - Data presence via
:empty,:not(:empty) - Relationships via
:has(),:not() - Custom properties on elements
- Container size and scroll-state via
@container
CSS does not read:
class(forbidden in HTML)id(forbidden in HTML)data-*(forbidden in HTML)
CSS targets elements by their semantic name and their native state.
Air-gap inside CSS
Each CSS feature is independent and copy-pastable. The transitions reference does not depend on themes. The state-machines reference does not depend on layout. Each feature stands alone and can be dropped into any project.
This rule is enforced by:
- One feature per reference file
- No cross-imports between feature references
- Custom properties used in a reference are declared inside that reference's example
- Each reference shows the feature in isolation, not in the context of the larger project
Feature references
Each feature has its own reference. Read only the reference for the feature you are working on. Do not load others.
| Feature | Reference |
|---|---|
| Reset | references/reset.md |
| Layers and cascade | references/layers.md |
| Layout (Holy Grail, auto-grid) | references/layout.md |
| Fonts (loading, variable fonts) | references/fonts.md |
| Typography (fluid sizing, balance, pretty) | references/typography.md |
| Inputs (form-field reset, validation display) | references/inputs.md |
| Media (img, picture, video reset) | references/media.md |
| State machines (label + checkbox/radio) | references/state-machines.md |
| Themes (color-scheme, oklch, light-dark) | references/themes.md |
| Transitions and view transitions | references/transitions.md |
| Loading indicator (CSS-only spinner) | references/loading.md |
| Containers (size and scroll-state queries) | references/containers.md |
| Radii (outer/inner radius math) | references/radii.md |
| Accessibility (focus-visible, accent-color, marker, selection) | references/a11y.md |
| Carousel (scroll-button, scroll-marker) | references/carousel.md |
| Menu (popover, popovertarget) | references/menu.md |
| Feature detection (@supports, @supports at-rule) | references/feature-detection.md |
| Starting style (@starting-style) | references/starting-style.md |
| Anchor positioning (anchor-name, position-anchor) | references/anchor-positioning.md |
| Scrollbars (scrollbar-color, scrollbar-width) | references/scrolling.md |
| Scroll affordances (scroll-state shadows) | references/scroll-affordances.md |
| Reactivity (data presence drives visibility) | references/reactivity.md |
Authoritative external references
- MDN CSS reference: https://developer.mozilla.org/en-US/docs/Web/CSS
- W3C CSS specifications: https://www.w3.org/Style/CSS/specs.en.html
- Modern CSS feature catalog: https://modern-css.com/
What CSS never does
- Never
!important - Never Flexbox (
display: flex,display: inline-flex,flex-direction,flex-wrap,flex-flow) - Never size-based
@media (min-width)/(max-width) - Never magic numbers
- Never
class,id, ordata-*selectors (those attributes don't exist in this architecture's HTML) - Never inline
<style>orstyle=attributes
Baseline & support
Checked against MDN as of 2026-07-16.
:has()— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/:has:focus-visible— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible@layer— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/@layer@container— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/@containeroklch()— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklchlight-dark()— Baseline 2024 Newly available — https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark@property— Baseline 2024 Newly available — https://developer.mozilla.org/en-US/docs/Web/CSS/@property@starting-style— Baseline 2024 Newly available — https://developer.mozilla.org/en-US/docs/Web/CSS/@starting-styletransition-behavior— Baseline 2024 Newly available — https://developer.mozilla.org/en-US/docs/Web/CSS/transition-behaviorcontent-visibility— Baseline 2024 Newly available — https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibilityanchor-name(anchor positioning) — Baseline 2026 Newly available — https://developer.mozilla.org/en-US/docs/Web/CSS/anchor-name@view-transition— Limited availability — https://developer.mozilla.org/en-US/docs/Web/CSS/@view-transitionif()— Limited availability — https://developer.mozilla.org/en-US/docs/Web/CSS/if@function— Limited availability — https://developer.mozilla.org/en-US/docs/Web/CSS/@function
Canonical rules: https://github.com/Autocss-com/ai/blob/main/AGENTS.md