Store a value once using --name and reuse it anywhere with var(). Unlike Sass variables, these work in the browser at runtime and can be changed with JavaScript.
Define animations that play through multiple steps using @keyframes, then attach them to elements with the animation property. No hover or trigger needed — they can loop on their own.
css
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.card {
animation: fadeInUp 0.4s ease-out forwards;
/* name | duration | easing | delay | iterations | direction | fill-mode */
animation: fadeInUp 0.4s ease-out 0.1s 1 normal forwards;
}
.loading {
animation: pulse 1.5s ease-in-out infinite;
}
/* Pause on hover */
.card:hover { animation-play-state: paused; }
/* Respect motion preference */
@media (prefers-reduced-motion: reduce) {
.card { animation: none; }
}
coreanimationskeyframesmotion
not reviewed
Pseudo-elements
::before and ::after let you insert decorative content without adding HTML. Other pseudo-elements like ::placeholder and ::selection style specific parts of existing elements.
css
/* ::before and ::after require content property */
Keep an element at a fixed width-to-height ratio (like 16:9 for video) without the old percentage-padding workaround.
css
/* Maintain 16:9 ratio */
.video-wrapper {
aspect-ratio: 16 / 9;
width: 100%;
}
/* Square thumbnail */
.thumbnail {
aspect-ratio: 1; /* shorthand for 1/1 */
width: 80px;
object-fit: cover; /* on img elements */
}
/* 4:3 card image */
.card-img {
aspect-ratio: 4 / 3;
width: 100%;
object-fit: cover;
}
/* Old padding hack (no longer needed) */
.old-way {
position: relative;
padding-top: 56.25%; /* 9/16 = 56.25% */
}
.old-way > * {
position: absolute;
inset: 0;
}
coreaspect-ratioresponsivelayout
not reviewed
clamp(), min(), max()
Math functions that let values scale smoothly with the viewport, staying between a minimum and maximum — no media query breakpoints needed.
css
/* clamp(MIN, PREFERRED, MAX) */
.heading {
/* Fluid type: 1.5rem at small viewport, up to 3rem */
font-size: clamp(1.5rem, 4vw, 3rem);
}
.container {
/* Fluid width that won't exceed 1200px or go below 300px */
width: clamp(300px, 90%, 1200px);
/* Equivalent to: */
width: min(max(300px, 90%), 1200px);
}
/* min() — pick the smallest */
.img {
width: min(500px, 100%); /* responsive: max 500px, never overflow */
}
/* max() — pick the largest */
.sidebar {
min-height: max(300px, 50vh); /* at least 300px, but 50vh if larger */
}
/* Fluid spacing */
.section {
padding: clamp(2rem, 5vw, 6rem);
}
advancedclampfluidresponsive
not reviewed
Modern Pseudo-classes
Modern selectors that let you match multiple targets at once (:is, :where), exclude elements (:not), or style a parent based on what it contains (:has).
css
/* :is() — match any in the list (takes highest specificity of its args) */
:is(h1, h2, h3, h4) { line-height: 1.2; }
:is(article, section, aside) p { margin-bottom: 1rem; }
/* :where() — same as :is() but ZERO specificity (easy to override) */
inset-inline-start: 0; /* left in LTR, right in RTL */
inset: 00 auto 0; /* top right bottom left shorthand */
}
advancedlogical-propertiesrtli18n
not reviewed
Container Queries
CSS Containment Level 3
Apply styles based on how wide the parent container is, not the full viewport. This makes components adapt correctly when placed in different parts of the page.
css
/* 1. Declare a containment context */
.card-wrapper {
container-type: inline-size;
container-name: card; /* optional name */
}
/* 2. Query the container, not the viewport */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 120px 1fr;
}
}
@container (min-width: 600px) {
.card-title {
font-size: 1.5rem;
}
}
/* Container query units */
.card-img {
width: 50cqi; /* 50% of container inline size */
}
advancedcontainer-queriesresponsivemodern-css
not reviewed
Cascade Layers (@layer)
CSS Cascade 5
Group styles into named priority layers so you can control which styles win without fighting over specificity scores.
css
/* Declare layer order — later layers win over earlier ones */
body { font-family: system-ui; line-height: 1.5; }
a { color: var(--link-color); }
}
@layer components {
.button {
padding: 0.5rem 1rem;
border-radius: 0.25rem;
}
}
@layer utilities {
.mt-4 { margin-top: 1rem; }
.hidden { display: none; }
}
/* Unlayered styles beat any layer */
.override { color: red; } /* always wins over all layers */
/* Import into a layer */
@import url("bootstrap.css") layer(third-party);
advancedcascade-layerslayerspecificity
not reviewed
CSS Subgrid
CSS Grid Level 2
Let a child grid item inherit its parent's row or column tracks so elements inside it can align to the outer grid — useful for lining up card sections across a row of cards.
css
/* Parent grid */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto; /* title / body / footer */
Declare a CSS custom property with a specific type (like a number or color). Once typed, the browser can animate it smoothly — something plain custom properties cannot do.