Modern CSS
HTML and CSS now cover much of the JS work UI libraries did: "popover, anchor, dialog, view transitions, scroll driven animation and custom select" (nerdy.dev: Headless, boneless, skinless & lifeless UI, 2024-10-16, crediting Nils), and models are "barely aware" of it (nerdy.dev: Why AI Sucks At Front End, 2026-04-12). This skill holds that CSS. Every fact comes from Adam Argyle's blog nerdy.dev, tagged with the post and its date, except FONTS-AND-TEXT-DETAILS.md and the few sections tagged with another source ([Craft], [Emil Kowalski, ...], [Jakub Krehel, ...], [corner-smoothing], [css-modern-features], [responsive-craft], [flornkm, ...], [Libraries.dev]), STICKY.md, and the owner's responsive policy and source comparisons in RESPONSIVE.md and RESPONSIVE-FORKS.md, and every feature carries its current status from MDN (Baseline widely, Baseline newly with its date, or Limited availability with the engines), checked October 2026, stated once in the file that introduces it. Where a post's code or support claim has gone stale, the files give the current form and say what the post said; experimental features stay in, marked. Durations, curves, springs (including linear() springs) and staggers for interface motion are in ui-animation SKILL.md; SVG markup, filters and SMIL are in svg SKILL.md; the owner's signed-in app builds its controls, menus and dialogs on headless primitives in app-ui SKILL.md, and where that differs from the native route here, the topic file says so; keeping an interface from looking template-built is anti-slop-ui SKILL.md.
Apply only the routes and checks for the selected job. Read a linked skill's named file from its installed folder when available, or from the linked source. Report an unavailable required reference instead of inventing it. [skill-authoring, DISTRIBUTION.md#composing-skills]
| The job | Read |
|---|---|
Modal <dialog> and shown [popover] in the top layer and their support, invoker commands (commandfor, command), closedby light dismiss and its fallback limitation, a component that puts itself in the top layer, popover="hint" with interestfor, interactivity: inert, CloseWatcher, transition starter kits for dialogs and popovers, dialog patterns |
POPOVER-AND-DIALOG.md |
Enter and exit with @starting-style, transition-behavior: allow-discrete, display and overlay, why top-layer elements are hard to animate, [hidden] exits for any element, removing a node after getAnimations() finish, opting in to motion, <details> with ::details-content, the exclusive accordion, interpolate-size and calc-size(), sibling-index() staggers |
TRANSITIONS-AND-STARTING-STYLE.md |
anchor-name, position-anchor, anchor(), anchor-size(), position-area, position-try-fallbacks, position-try-order and why fallbacks fail in small spaces, anchor-interpolated morphing (AIM), carousel buttons that move inside or outside, other uses |
ANCHOR-POSITIONING.md |
Customizable <select> (appearance: base-select, ::picker(select), <selectedcontent>, :open, ::checkmark, ::picker-icon) and its transitions, the "nice select" build part by part, field-sizing, :user-valid reveals, form state and values into CSS, range progress fills, radio and checkbox groups, accent-color, the on-screen keyboard (inputmode, autocapitalize, autocorrect, enterkeyhint) |
SELECT-AND-FORMS.md |
Scroller structure and essentials (overscroll, scroll-axis-lock), snapping, pull to refresh, scrollend and snap events, scroll-state() queries, CSS carousels, touch-action axes |
SCROLL.md |
| Scroll-driven animation and named timelines, edge-aware scroll fades, scroll-triggered animation, range and shorthand qualifications | SCROLL-ANIMATIONS.md |
Sticky that does nothing (align-self: start, overflow and overflow: clip, insets), offsets shared by several sticky bars, anchor links under a sticky header (scroll-padding, scroll-margin), detecting the stuck state with an IntersectionObserver sentinel, a table with a sticky header row and first column |
STICKY.md |
Scrollbar color and width, the ::-webkit-scrollbar fallback, hover and focus hints |
SCROLLBARS.md |
startViewTransition(), cross-document @view-transition, names, classes and types, text replace transitions, composer and other morphs, 3D perspective, the swoop, freezing a transition to inspect it, where view transitions fall short |
VIEW-TRANSITIONS.md |
| Units, fluid scales, container-query migration, right-to-left layout, touch and mobile browser chrome, with the owner's policy and source differences | RESPONSIVE.md |
| Choose responsive alternatives for sidebars, tables, dashboards, heroes, sticky bars, navigation, forms and grids, with behavior specs and audit gates outside the owner's apps | RESPONSIVE-FORKS.md |
What a component can know, container size queries (the container shorthand, calc() and ch in the condition), container queries in Tailwind v4 (and the v3 plugin's different syntax), name-only container queries, style queries, media query range syntax, @custom-media and feature flags, reduced motion, transparency and data, color scheme and contrast, forced-colors, hover and pointer, orientation, color gamut, scripting: none, display-mode |
QUERIES-AND-PREFERENCES.md |
@layer (named, nested, anonymous, later overrides), @scope with donut scope and proximity, nesting and BEM, :has() and other selectors, focus by demotion, which custom names need dashes and the optional emoji convention, specificity, a study list, the headless, boneless, skinless and lifeless vocabulary |
CASCADE-AND-SCOPE.md |
The ten kinds of custom properties, typed @property and CSS.registerProperty(), rotating border beams, the custom property bomb, Open Props and Open Props UI tokens, Tailwind v4 @theme inline, live props from JS |
CUSTOM-PROPERTIES.md |
Mixins and @apply, @function and if(), typed attr(), sibling-index() and sibling-count(), trig and physics, stepped values, functions still coming |
CSS-FUNCTIONS.md |
LCH and OKLCH against HSL, OKLCH palettes from one hue, color-mix() and its space, relative color, alpha(), contrast-color(), light-dark() and color-scheme, page and component light and dark, system and accent colors, P3 with an sRGB fallback, APCA and L* contrast, forced colors |
COLOR.md |
calc(infinity), implementation-dependent numeric ceilings, responsive radius signs and percentage axes, NaN equality boundaries, boolean recipes and persistent state |
CSS-INFINITY.md |
lh and rlh, drop caps, cap and the root font units, text-wrap: balance and its limits, text-box trim, the GRAD axis for dark mode and contrast, text-grow (prototype), text-emphasis-style |
TYPOGRAPHY-AND-UNITS.md |
Not from nerdy.dev: typography review (scale, measure, tracking, source-qualified audit checks), properties over raw font-variation-settings and font-feature-settings, synthesis longhands, axes and OpenType features, optical sizes, small caps and font-variant-position, tabular against proportional figures, font smoothing, hanging-punctuation, underlines, ::selection, ::target-text, highlights and user-select, the caret, the iOS input zoom, decorative text, fallback-font metrics (font-size-adjust, @font-face size-adjust), hyphenate-limit-chars, ::marker and CSS counters, each with its support |
FONTS-AND-TEXT-DETAILS.md |
Stops, hints and hard lines, hue interpolation routes, conic charts and spinners, radial and repeating recipes, mesh and noise backgrounds, animated gradient text, borders, border-image scrims, shine borders and shadows, shape(), corner-shape and superellipse() and clipping, nested radii with overflow-clip-margin, paint-order on HTML text, shake, glitch and motion blur |
GRADIENTS-AND-EFFECTS.md |
Three unintuitive fixes (min-width: 0, flex-shrink: 0, auto-fill columns), grid and subgrid slots, cards aligned with subgrid, stacking in one cell, bento grids, a circle layout with trig and sibling-index(), layering without position: absolute, balanced wrapping, centering, aspect ratios that follow orientation, logical against physical properties |
LAYOUT.md |
The rules
Put floating layers in the top layer with modal
<dialog>and shown[popover]. "knowing your way around a<dialog>and a[popover]are table stakes. Otherwise, everyone else will be on top of you, and your wackz-indexattempts will be defeated with a puny value of1"; they come "with no JavaScript to download, and accessibility built in. Use em" (nerdy.dev: 6 CSS Snippets Every Front-End Developer Should Know In 2025, 2025-01-19). app-ui instead builds overlays on headless primitives: "Keep every overlay mounted and passopen" (app-ui OVERLAYS.md). See the modal/modeless distinction.Interruptible transitions over keyframe animations (nerdy.dev: Using @starting-style and transition-behavior for enter and exit stage effects, 2024-05-20). Enter from
@starting-style, leave withdisplay: nonedelayed bytransition-behavior: allow-discrete("you have to usedisplay: noneto kick something off stage"), "You may also need to transitionoverlaydepending on what you're after" for a dialog, and let exits run "slightly faster than entry animations" (the post: .5s in, .4s out).linear()springs run long, which makes them "a great fit for transitions and potentially troublesome as keyframes" (2025 snippets post; the springs are in ui-animation TIMING.md). The post eases entries in and exits out; ui-animation TIMING.md eases arrivals out and exits in. See TRANSITIONS-AND-STARTING-STYLE.md for which engines run the exit.Enhance, never depend. The site "tries to only use JavaScript to enhance the experience, not relying on it for the baseline behavior" (nerdy.dev: New Year, New Site, 2023-01-01). Adopt a newer feature with a cascade fallback that older browsers skip ("If it knows, it knows") or behind
@supports(2025 snippets post), and put motion inside@media (prefers-reduced-motion: no-preference)(nerdy.dev: Anchor Interpolated Morph (AIM), 2026-01-23). ui-animation SKILL.md asks for a deliberate reduced version of each animation rather than none.Put the essentials on every scroller: "use the
overflowshorthand and set both axes to prevent surprises;overscroll-behaviorshould always match the scrolling axis; padding andscroll-paddingshould always match; smoothscroll-behaviorif the use[r] is ok with motion" (nerdy.dev: Nintendo Switch Homescreen recreated with CSS and a li'l bit of JS, 2025-06-13). See SCROLL.md.Manipulate color in LCH-type spaces. HSL 50% lightness is not 50% as people see it, "and it will totally bite you when you go to measure color contrast"; "LCH type color spaces should be your colorspace for manipulation" (nerdy.dev: LCH Luminance vs HSL Lightness, 2022-12-02). ui-animation PATTERNS.md derives a chart palette in HSL and sets this post against it. See COLOR.md.
Know the three strategies for light and dark sections and components (nerdy.dev: Page and Component Adaptive Light/Dark, 2024-08-21):
color-schemepluslight-dark(), "only for color values" but "the HTML is clean and tidy";@scope, whose "primary use case" is "scoping light and dark contexts" (crediting Miriam Suzanne); and, "if you want to adapt more than just color", style queries on custom properties holding thecolor-schemevalue, with "each new context" wrapped in a.darkor.lightelement. The post filed the last two under Future. app-ui and landing-page-ui switch the whole page with a class (landing-page-ui also setsdata-theme) set by a head script instead (app-ui CHECKS.md, landing-page-ui SYSTEM.md). See COLOR.md.Type the custom properties a system depends on.
@property"formalizes CSS system interfaces", "protects CSS systems", "enables new animation powers" and "can perform better when usinginherits: false" (2025 snippets post). For invalid-value behavior, use the official correction; the post and old rule incorrectly said the last valid declaration survives.Dash your own names. "I think it's a good idea to
--all your custom names, just to make it really clear they aren't internal CSS keywords" (nerdy.dev: An Emoji Naming Convention, 2025-02-20). Both forms are valid where a feature accepts an undashed name, and the owner's app names its containers without dashes (@container mainin ../app-ui/reference/styles/layout/shell/page-layout.css). See CASCADE-AND-SCOPE.md.Give forced colors an affordance: where shadows and colors separate UI parts, add a transparent 1px border so
forced-colorsmode still draws an edge (nerdy.dev: New Year, New Site, 2023-01-01); "Transparent borders are your friend!" (Switch homescreen post, 2025-06-13). See QUERIES-AND-PREFERENCES.md.Enhance a
<select>only for fine pointers: the custom picker applies under@media (hover)and(pointer: fine), and "I keep mobile with the native select" (nerdy.dev: Nice Select, 2026-02-03). See SELECT-AND-FORMS.md.Know the yearly picks. For 2025: page transitions with
@view-transition { navigation: auto; }("the easiest snippet to add to your site, with no downsides"), transitions for<dialog>,[popover]and<details>, animated light and dark gradient text, typed custom properties andlinear()springs (2025 snippets post). For 2026:@container scroll-state(),text-boxtrim,sibling-index()staggers and typedattr()(nerdy.dev: 4 CSS Features Every Front-End Developer Should Know In 2026, 2026-01-07). Several of them still run in one or two engines (cross-document view transitions,interpolate-size,overlay, scroll-state queries, typedattr()), so check each in its topic file before relying on it.When a model writes the front end, ask for the environment and know its weak spots. For HTML and CSS "there is no pinning the browser type, browser window size, browser version, the users input type (keyboard, mouse, touch, voice), their user preferences"; the model "doesn't control these, so it ignores them until you make them relevant". "I prompt LLMs with logical properties" (nerdy.dev: Prompt In Logical Properties, 2026-01-27); even so, "when you ask for it, or provide documentation that spells it out, it's not guaranteed to work" (Why AI Sucks At Front End post). The post's weak spots: scroll-driven animations and micro-interactions ("it will invent a CSS syntax"), layout and spacing math, combined states, accessibility ("It throws
aria-hidden="true"at a wall"), performance ("the heaviest, jankiest solution unless you explicitly ask"), and tests (many, not good) (Why AI Sucks At Front End post, 2026-04-12). Verifying on a rendered surface is in anti-slop-ui SKILL.md.Check the browser targets before writing CSS [css-modern-features, SKILL.md]: read
"browserslist"inpackage.json, then.browserslistrc, then the framework's config (Vite and Astrobuild.target); "Usenpx browserslistin the project root to get the exact resolved list when uncertain." Then compare each feature's status in its topic file. The source's Next.js step ("checknext.config.*forbrowserslistortranspilePackages") is wrong: Next.js reads Browserslist frompackage.json, and with none it uses["chrome 111", "edge 111", "firefox 111", "safari 16.4"](Next.js: Supported Browsers), so in such an app anything newer needs rule 3's fallback. The source also maps targets onto five tiers and calls its Tier 2 (Chrome 111, Safari 16.4, Firefox 113) "Modern baseline - most features safe", yet that floor lacks:has()(Firefox 121),@starting-style(Safari 17.5, Firefox 129) and scroll-driven animation (no Firefox release), which its checklist rates Tier 2 (web-features). Use MDN's Baseline instead, which Browserslist takes as a query:baseline widely available,baseline newly available,baseline 2024(browserslist).
Prove it
Modal dialogs and shown popovers use the top layer without a z-index fight; modeless dialogs follow the separate behavior, and dismissal follows the chosen mode with a working close control; each enter and exit transition can be interrupted mid-way, and in a browser without overlay or interpolate-size the element still shows and hides, just without the motion; with reduced motion on, nothing moves that isn't essential; every scroller meets the four essentials; each feature used is in a browser the project's Browserslist targets ship it in, or sits behind @supports or a cascade fallback that leaves a working page; the page reads in light, dark and forced colors; on a touch phone the native select appears; any code a model wrote has been checked in the browser for the weak spots in rule 12; and every topic file's own Prove it checks pass for the parts you touched.