# Modern Css

> >

- **Type:** Skill
- **Install:** `agentstack add skill-caidanw-skills-modern-css`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [caidanw](https://agentstack.voostack.com/s/caidanw)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [caidanw](https://github.com/caidanw)
- **Source:** https://github.com/caidanw/skills/tree/main/modern-css

## Install

```sh
agentstack add skill-caidanw-skills-modern-css
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Modern CSS

The CSS spec has evolved dramatically. Many old hacks — absolute-position centering,
padding-top aspect ratios, JS scroll listeners, Sass color functions — now have clean,
native replacements. This skill ensures you always reach for the modern approach first.

**Reference:** [modern-css.com](https://modern-css.com/) — all techniques sourced from
this site. Visit individual pages for live demos and deeper explanations.

**Support data:** Browser support percentages represent global user coverage from
[caniuse.com](https://caniuse.com), last updated **February 2026**. These numbers shift as
browsers release updates — verify on caniuse if precision matters for a project.

## How to Use This Skill

When writing or reviewing CSS:

1. **Always use** techniques in the *Widely Available* tier (90%+ support) without asking.
   If you spot legacy patterns, refactor them to the modern equivalent.
2. **Suggest** techniques in the *Newly Available* tier (80–90% support). Mention they are
   newly available and let the user decide. Offer a fallback if relevant.
3. **Ask first** before using *Limited Availability* techniques ( * { margin-right: 16px; }
.grid > *:last-child { margin-right: 0; }

/* MODERN: gap on the container */
.grid {
  display: flex;
  gap: 16px;
}
```

[Reference →](https://modern-css.com/spacing-elements-without-margin-hacks/)

#### Aspect ratios — `aspect-ratio`

```css
/* OLD: padding-top percentage hack */
.wrapper { padding-top: 56.25%; position: relative; }
.inner { position: absolute; inset: 0; }

/* MODERN: aspect-ratio property */
.video-wrapper {
  aspect-ratio: 16 / 9;
}
```

[Reference →](https://modern-css.com/aspect-ratios-without-the-padding-hack/)

#### Positioning shorthand — `inset`

```css
/* OLD: four separate properties */
.overlay { top: 0; right: 0; bottom: 0; left: 0; }

/* MODERN: inset shorthand */
.overlay {
  position: absolute;
  inset: 0;
}
```

[Reference →](https://modern-css.com/positioning-shorthand-without-four-properties/)

#### Sticky headers — `position: sticky`

```css
/* OLD: JS scroll listener + getBoundingClientRect */
// add/remove .fixed class based on scroll position

/* MODERN: sticky positioning */
.header {
  position: sticky;
  top: 0;
}
```

[Reference →](https://modern-css.com/sticky-headers-without-javascript-scroll-listeners/)

#### Responsive images — `object-fit`

```css
/* OLD: background-image with background-size */
.card-image {
  background-image: url(...);
  background-size: cover;
  background-position: center;
}

/* MODERN: object-fit on an img element */
img {
  object-fit: cover;
  width: 100%;
  height: 200px;
}
```

[Reference →](https://modern-css.com/responsive-images-without-background-image-hack/)

#### Filling available space — `stretch`

```css
/* OLD: calc workaround */
.full { width: calc(100% - 40px); }

/* MODERN: stretch keyword */
.full { width: stretch; }
/* fills container, respects margins */
```

[Reference →](https://modern-css.com/filling-available-space-without-calc-workarounds/)

#### Preventing scroll chaining — `overscroll-behavior`

```css
/* OLD: JS wheel event preventDefault */
// modal.addEventListener('wheel', e => e.preventDefault(), { passive: false })

/* MODERN: overscroll-behavior */
.modal-content {
  overflow-y: auto;
  overscroll-behavior: contain;
}
```

[Reference →](https://modern-css.com/preventing-scroll-chaining-without-javascript/)

#### Preventing scrollbar layout shift — `scrollbar-gutter`

```css
/* OLD: force scrollbar or hardcode padding */
body { overflow-y: scroll; }

/* MODERN: reserve scrollbar space */
body { scrollbar-gutter: stable; }
```

[Reference →](https://modern-css.com/preventing-layout-shift-from-scrollbar/)

#### Grid template areas — named areas

```css
/* OLD: grid line numbers or floats */
.item { grid-column: 1 / 3; grid-row: 2; }

/* MODERN: named grid areas */
.layout {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}
.header { grid-area: header; }
```

[Reference →](https://modern-css.com/naming-grid-areas-without-line-numbers/)

#### Modal dialogs — `` element

```css
/* OLD: fixed overlay + JS open/close/ESC/focus-trap */
.overlay { position: fixed; z-index: 999; }

/* MODERN: native dialog with ::backdrop */
dialog { padding: 1rem; }
dialog::backdrop { background: rgb(0 0 0 / .5); }
/* JS: dialog.showModal() / dialog.close() */
```

[Reference →](https://modern-css.com/modal-dialogs-without-a-javascript-library/)

#### Direction-aware layouts — logical properties

```css
/* OLD: physical properties + RTL overrides */
margin-left: 1rem;
padding-right: 1rem;
[dir="rtl"] .box { margin-right: 1rem; }

/* MODERN: logical properties */
margin-inline-start: 1rem;
padding-inline-end: 1rem;
border-block-start: 1px solid;
```

[Reference →](https://modern-css.com/direction-aware-layouts-without-left-and-right/)

#### Responsive components — `@container`

```css
/* OLD: viewport-based media queries */
@media (min-width: 768px) {
  .card { grid-template-columns: auto 1fr; }
}

/* MODERN: container queries */
.wrapper { container-type: inline-size; }
@container (width > 400px) {
  .card { grid-template-columns: auto 1fr; }
}
```

[Reference →](https://modern-css.com/responsive-components-without-media-queries/)

#### Scroll snapping — `scroll-snap`

```css
/* OLD: Slick/Swiper carousel or touch handlers */
// $('.carousel').slick({ ... })

/* MODERN: CSS scroll snap */
.carousel {
  scroll-snap-type: x mandatory;
  overflow-x: auto;
}
.carousel > * { scroll-snap-align: start; }
```

[Reference →](https://modern-css.com/scroll-snapping-without-a-carousel-library/)

### Selectors

#### Parent selection — `:has()`

```css
/* OLD: JavaScript el.closest('.parent').classList.add(...) */

/* MODERN: :has() parent selector */
.card:has(img) {
  grid-template-rows: auto 1fr;
}
```

[Reference →](https://modern-css.com/selecting-parent-elements-without-javascript/)

#### Grouping selectors — `:is()`

```css
/* OLD: repeat the full selector for each match */
.card h1, .card h2, .card h3, .card h4 { margin-bottom: 0.5em; }

/* MODERN: :is() grouping */
.card :is(h1, h2, h3, h4) { margin-bottom: 0.5em; }
```

[Reference →](https://modern-css.com/grouping-selectors-without-repetition/)

#### Low-specificity resets — `:where()`

```css
/* OLD: class-based resets with specificity issues */
.reset ul, .reset ol { margin: 0; }

/* MODERN: :where() has zero specificity */
:where(ul, ol) {
  margin: 0;
  padding-inline-start: 1.5rem;
}
```

[Reference →](https://modern-css.com/low-specificity-resets-without-complicated-selectors/)

#### Keyboard-only focus — `:focus-visible`

```css
/* OLD: :focus fires on mouse click too, so people remove outlines (a11y fail) */
:focus { outline: 2px solid blue; }

/* MODERN: :focus-visible only shows for keyboard navigation */
:focus-visible {
  outline: 2px solid var(--focus-color);
}
```

[Reference →](https://modern-css.com/focus-styles-without-annoying-mouse-users/)

### Color

#### Styling form controls — `accent-color`

```css
/* OLD: appearance: none + rebuild the entire control */
input[type="checkbox"] { appearance: none; /* 20+ lines of custom styles */ }

/* MODERN: accent-color */
input[type="checkbox"],
input[type="radio"] {
  accent-color: #7c3aed;
}
```

[Reference →](https://modern-css.com/styling-form-controls-without-rebuilding-them/)

#### Perceptually uniform colors — `oklch()`

```css
/* OLD: hex/rgb with guess-and-check for each shade */
--brand: #4f46e5;
--brand-light: #818cf8;
--brand-dark: #3730a3;

/* MODERN: oklch — adjust lightness, keep perceived hue */
--brand: oklch(0.55 0.2 264);
--brand-light: oklch(0.75 0.2 264);
--brand-dark: oklch(0.35 0.2 264);
```

[Reference →](https://modern-css.com/perceptually-uniform-colors-with-oklch/)

#### Wide-gamut colors — `display-p3` / `oklch`

```css
/* OLD: sRGB only — washed out on P3 displays */
.hero { color: rgb(200, 80, 50); }

/* MODERN: oklch or display-p3 for vivid colors */
.hero { color: oklch(0.7 0.25 29); }
/* or: color(display-p3 1 0.2 0.1) */
```

[Reference →](https://modern-css.com/vivid-colors-beyond-srgb/)

#### Frosted glass — `backdrop-filter`

```css
/* OLD: pseudo-element with blurred background image */
.card::before { content: ''; background-image: url(bg.jpg); filter: blur(12px); z-index: -1; }

/* MODERN: backdrop-filter */
.glass {
  backdrop-filter: blur(12px);
  background: rgba(255, 255, 255, .1);
}
```

[Reference →](https://modern-css.com/frosted-glass-effect-without-opacity-hacks/)

### Typography

#### Fluid typography — `clamp()`

```css
/* OLD: multiple media queries for each breakpoint */
h1 { font-size: 1rem; }
@media (min-width: 600px) { h1 { font-size: 1.5rem; } }
@media (min-width: 900px) { h1 { font-size: 2rem; } }

/* MODERN: clamp for fluid scaling */
h1 { font-size: clamp(1rem, 2.5vw, 2rem); }
```

[Reference →](https://modern-css.com/fluid-typography-without-media-queries/)

#### Multiline text truncation — `line-clamp`

```css
/* OLD: JS to slice text by chars/words and add "..." */

/* MODERN: line-clamp */
.card-title {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}
```

[Reference →](https://modern-css.com/multiline-text-truncation-without-javascript/)

#### Drop caps — `initial-letter`

```css
/* OLD: float hack with manual line-height */
.drop-cap::first-letter { float: left; font-size: 3em; line-height: 1; }

/* MODERN: initial-letter */
.drop-cap::first-letter { initial-letter: 3; }
```

[Reference →](https://modern-css.com/drop-caps-without-float-hacks/)

#### Font loading — `font-display: swap`

```css
/* OLD: invisible text until font loads (FOIT) */
@font-face { font-family: "MyFont"; src: url(...); }

/* MODERN: font-display swap shows fallback immediately */
@font-face {
  font-family: "MyFont";
  src: url("MyFont.woff2");
  font-display: swap;
}
```

[Reference →](https://modern-css.com/font-loading-without-invisible-text/)

#### Variable fonts — single file, all weights

```css
/* OLD: separate @font-face for each weight */
@font-face { font-weight: 400; src: url("Regular.woff2"); }
@font-face { font-weight: 700; src: url("Bold.woff2"); }

/* MODERN: one variable font file */
@font-face {
  font-family: "MyVar";
  src: url("MyVar.woff2");
  font-weight: 100 900;
}
```

[Reference →](https://modern-css.com/multiple-font-weights-without-multiple-files/)

### Animation

#### Independent transforms

```css
/* OLD: rewrite entire transform shorthand to change one value */
.icon { transform: translateX(10px) rotate(45deg) scale(1.2); }

/* MODERN: individual transform properties */
.icon {
  translate: 10px 0;
  rotate: 45deg;
  scale: 1.2;
}
/* animate any one without touching the rest */
```

[Reference →](https://modern-css.com/independent-transforms-without-the-shorthand/)

#### Typed custom properties — `@property`

```css
/* OLD: custom properties are strings, can't animate */
:root { --hue: 0; }
.wheel { transition: --hue .3s; } /* ignored */

/* MODERN: @property makes them animatable */
@property --hue {
  syntax: "";
  inherits: false;
  initial-value: 0deg;
}
.wheel {
  background: hsl(var(--hue), 80%, 50%);
  transition: --hue .3s;
}
```

[Reference →](https://modern-css.com/typed-custom-properties-without-javascript/)

#### Responsive clip paths — `shape()`

```css
/* OLD: clip-path: path() uses fixed px coordinates */
.shape { clip-path: path('M0 200 L100 0...'); }

/* MODERN: shape() uses responsive units */
.shape { clip-path: shape(from 0% 100%, ...); }
```

[Reference →](https://modern-css.com/responsive-clip-paths-without-svg/)

### Workflow

#### CSS nesting — no preprocessor needed

```css
/* OLD: requires Sass/Less compiler */
// .nav { & a { color: #888; } }

/* MODERN: native CSS nesting */
.nav {
  & a { color: #888; }
}
/* plain .css file, no build step */
```

[Reference →](https://modern-css.com/nesting-selectors-without-sass-or-less/)

#### Cascade layers — `@layer`

```css
/* OLD: specificity wars and !important */
.page .card .title.special { color: red !important; }

/* MODERN: cascade layers control order */
@layer base, components, utilities;
@layer utilities {
  .mt-4 { margin-top: 1rem; }
}
```

[Reference →](https://modern-css.com/controlling-specificity-without-important/)

#### Theme variables — custom properties

```css
/* OLD: Sass variables compile to static values */
$primary: #7c3aed;
.btn { background: $primary; }

/* MODERN: CSS custom properties update at runtime */
:root { --primary: #7c3aed; }
.btn { background: var(--primary); }
```

[Reference →](https://modern-css.com/theme-variables-without-a-preprocessor/)

#### Dark mode defaults — `color-scheme`

```css
/* OLD: manually restyle every form control for dark mode */
@media (prefers-color-scheme: dark) { input, select, textarea { ... } }

/* MODERN: color-scheme tells the browser to handle it */
:root { color-scheme: light dark; }
```

[Reference →](https://modern-css.com/dark-mode-defaults-without-extra-css/)

#### Lazy rendering — `content-visibility`

```css
/* OLD: IntersectionObserver to defer rendering */
// new IntersectionObserver((entries) => { /* render */ }).observe(el)

/* MODERN: content-visibility auto */
.section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}
```

[Reference →](https://modern-css.com/lazy-rendering-without-intersection-observer/)

---

## Newly Available (80–90% support) — Suggest to User

These techniques are newly available across major browsers. Suggest them to the user,
mention the support level, and offer a fallback if needed.

### Layout

#### Dropdown menus — `[popover]` (86%)

```css
/* OLD: display:none + JS toggle + click-outside + ESC */
.menu { display: none; }
.menu.open { display: block; }

/* MODERN: popover attribute */
/* Toggle */
/* ... */
#menu[popover] { position: absolute; }
```

[Reference →](https://modern-css.com/dropdown-menus-without-javascript-toggles/)

#### Subgrid — align nested grids to parent tracks (88%)

```css
/* OLD: duplicate parent track definitions in child */
.child-grid { grid-template-columns: 1fr 1fr 1fr; }

/* MODERN: subgrid inherits parent tracks */
.child-grid {
  display: grid;
  grid-template-columns: subgrid;
}
```

[Reference →](https://modern-css.com/aligning-nested-grids-without-duplicating-tracks/)

#### Customizable selects — `appearance: base-select` (86%)

```css
/* OLD: Select2 or Choices.js replacing native select */

/* MODERN: base-select unlocks full styling */
select, select ::picker(select) {
  appearance: base-select;
}
```

Note: support is expanding rapidly — verify current status on
[caniuse](https://caniuse.com/css-appearance).
[Reference →](https://modern-css.com/customizable-selects-without-a-javascript-library/)

#### Hover tooltips — `popover=hint` + `interestfor` (86%)

```html

Hover me
Tooltip content
```

[Reference →](https://modern-css.com/hover-tooltips-without-javascript-events/)

### Animation

#### Entry animations — `@starting-style` (85%)

```css
/* OLD: requestAnimationFrame to add class after paint */
// requestAnimationFrame(() => el.classList.add('visible'))

/* MODERN: @starting-style defines entry state */
.card {
  transition: opacity .3s, transform .3s;
  @starting-style {
    opacity: 0;
    transform: translateY(10px);
  }
}
```

[Reference →](https://modern-css.com/entry-animations-without-javascript-timing/)

#### Animating `display: none` — `transition-behavior: allow-discrete` (85%)

```css
/* OLD: wait for transitionend, use visibility + opacity + pointer-events */

/* MODERN: allow-discrete enables display transitions */
.panel {
  transition: opacity .2s, display .2s;
  transition-behavior: allow-discrete;
}
.panel.hidden { opacity: 0; display: none; }
```

[Reference →](https://modern-css.com/animating-display-none-without-workarounds/)

#### Page transitions — View Transitions API (89%)

```css
/* OLD: Barba.js or React Transition Group */

/* MODERN: View Transitions API */
/*

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [caidanw](https://github.com/caidanw)
- **Source:** [caidanw/skills](https://github.com/caidanw/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-caidanw-skills-modern-css
- Seller: https://agentstack.voostack.com/s/caidanw
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
