- name
- modern-css
- description
- Teaches agents to write modern CSS using native features instead of legacy hacks, workarounds, and JavaScript. Covers layout, animation, color, typography, selectors, and workflow patterns with 64 old-vs-modern comparisons. The agent should always prefer modern CSS approaches, warn about browser compatibility for newer features, and ask the user before using techniques with limited browser availability (<80% support).
# 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 (<80% support). Warn about
browser support and suggest a progressive-enhancement approach or fallback.
4. **If the user has legacy browser requirements** (e.g. older Safari, corporate browsers),
ask before using any technique — even Widely Available ones — since support percentages
assume modern browser versions. Use `@supports` to provide fallbacks.
When you see old CSS patterns in existing code, point them out and suggest the modern
replacement with a brief explanation of why it's better.
---
## Widely Available (90%+ support) — Always Use
These techniques are well-established and work across all modern browsers. Use them
without hesitation.
### Layout
#### Centering elements — `place-items: center`
```css
/* OLD: absolute + transform hack (5 declarations, 2 selectors) */
.parent { position: relative; }
.child {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
/* MODERN: grid centering (2 declarations, 1 selector) */
.parent {
display: grid;
place-items: center;
}
```
[Reference →](https://modern-css.com/centering-elements-without-the-transform-hack/)
#### Spacing elements — `gap`
```css
/* OLD: margin hacks with :last-child override */
.grid > * { 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 — `<dialog>` 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);
}
```
Auf GitHub ansehen