Executive Summary
CSS in 2026 is unrecognizable from the CSS of five years ago. The language has absorbed capabilities that previously required preprocessors, JavaScript libraries, or external tooling. Native nesting eliminates the need for Sass-like syntax. Cascade layers make specificity wars a solved problem. Container queries allow components to respond to their own container rather than the viewport. Scroll-driven animations replace scroll-event JavaScript with GPU-accelerated CSS. The :has() selector enables parent selection, something CSS lacked for over two decades.
This report covers every major CSS feature, from foundational concepts (box model, specificity, inheritance) through the layout systems that power modern interfaces (Flexbox, Grid, subgrid) to the newest capabilities that shipped in browsers between 2022 and 2026. Every section includes reference tables, practical guidance, and data on adoption and browser support.
- Flexbox adoption has reached 99% across all measured websites, making it the most widely used CSS layout feature. Grid follows at 93%, with the gap closing every year as legacy sites are replaced.
- Container queries have gone from 0% to 82% adoption in just four years (2022-2026), the fastest adoption of any CSS layout feature in history. This reflects genuine developer demand for component-scoped responsive design.
- Tailwind CSS is now the most popular CSS framework at 60% usage, having overtaken Bootstrap (34%) since 2023. Vanilla CSS with native features is the second most popular approach at 48%, reflecting the growing capability of the language itself.
- Runtime CSS-in-JS has declined from 38% peak usage (2018) to 10% (2026). Native CSS features (nesting, layers, scope) and build-time alternatives (Panda CSS, StyleX) have replaced the need for runtime style injection.
99%
Flexbox adoption in 2026
82%
Container query adoption
60%
Tailwind CSS usage share
10%
Runtime CSS-in-JS usage
Part 1: The CSS Box Model
Every element in CSS is a rectangular box. Understanding the box model is not optional — it is the single most important concept in CSS because every sizing, spacing, and layout decision depends on it. The box model consists of four nested areas: content (the actual text or child elements), padding (transparent space between content and border), border (a visible line around the padding), and margin (transparent space between the element and its neighbors).
content-box vs. border-box
The box-sizing property controls what the width and height properties refer to. With the default content-box, setting width: 300px means the content area is 300px, and padding and border are added on top. A 300px-wide element with 20px padding and 1px border actually takes up 342px of horizontal space (300 + 20 + 20 + 1 + 1). This arithmetic is the source of countless layout bugs.
With border-box, width: 300px means the total element width is 300px, including padding and border. The content area shrinks to accommodate them. This is overwhelmingly more intuitive and predictable. The universal reset *, *::before, *::after { box-sizing: border-box; } is included in virtually every modern project because it makes element sizing match what developers expect.
Margin Collapse
Vertical margins between adjacent block-level elements collapse into a single margin equal to the larger of the two values. If one element has margin-bottom: 30px and the next has margin-top: 20px, the gap between them is 30px, not 50px. This only happens vertically, never horizontally. Margin collapse does not occur inside flex containers, grid containers, or elements with overflow other than visible. This behavior surprises many developers and is one of the most common sources of spacing confusion.
Block Formatting Context (BFC)
A Block Formatting Context is an independent layout region where the internal layout does not affect outside elements. BFCs prevent margin collapse between parent and child, contain floats, and prevent float overlap. BFCs are created by: display: flow-root (the purpose-built way), overflow values other than visible, position: absolute or fixed, display: flex or grid, float, and contain: layout or content. Understanding BFCs explains many CSS layout quirks.
Key Finding
Setting box-sizing: border-box universally is the single most impactful CSS reset rule.
Without it, padding and border inflate element sizes beyond what width/height specify, causing cascading layout bugs. Every major CSS reset and framework includes this rule.
Part 2: Flexbox Deep Dive
Flexbox (Flexible Box Layout) is a one-dimensional layout system for distributing space and aligning items along a single axis. Since its full standardization in 2012, it has become the most used CSS layout feature at 99% global adoption. Flexbox is ideal for navigation bars, card footers, centering content, distributing items of unknown size, and any layout where items need to grow, shrink, or wrap within a single row or column.
Flex Container Properties
Setting display: flex on an element makes it a flex container, and its direct children become flex items. The container controls the direction (flex-direction: row or column), how items wrap (flex-wrap: wrap), how items are distributed along the main axis (justify-content: flex-start, center, space-between, space-around, space-evenly), how items align on the cross axis (align-items: stretch, center, flex-start, flex-end, baseline), and the gap between items (gap).
Flex Item Properties
Each flex item can control its own behavior with three properties: flex-grow (how much of the remaining space this item should absorb, default 0), flex-shrink (how much the item should shrink when space is insufficient, default 1), and flex-basis (the initial size of the item before growing/shrinking, default auto). The shorthand flex: 1 expands to flex: 1 1 0%, meaning the item will grow equally, can shrink, and starts from zero width. Understanding flex-basis is critical: it determines the starting point before grow/shrink calculations.
Flexbox vs. Grid
The most common question in CSS layout is when to use Flexbox versus Grid. The answer is straightforward: Flexbox handles one dimension (a row or a column), Grid handles two dimensions (rows and columns together). Use Flexbox for: navigation bars, button groups, centering a single element, distributing items in a toolbar, card footers. Use Grid for: page-level layouts, dashboard grids, image galleries, form layouts with aligned labels and inputs. The two compose naturally — Grid for the macro layout, Flexbox for micro alignment within grid cells.
Flexbox vs. Grid: Feature Comparison
14 rows
| Aspect | Flexbox | CSS Grid | Recommendation |
|---|---|---|---|
| Dimension | One-dimensional (row OR column) | Two-dimensional (rows AND columns simultaneously) | Use Grid for page layouts, Flexbox for component-level alignment |
| Content vs Layout | Content-driven: items determine their own size, layout wraps around content | Layout-driven: grid defines the structure, content fills slots | Flexbox for unknown number of items, Grid for structured layouts |
| Alignment | align-items, justify-content, align-self, gap | All Flexbox alignment plus place-items, place-content, place-self | Both excellent. Grid adds shorthand place-* properties |
| Item sizing | flex-grow, flex-shrink, flex-basis — relative sizing | fr units, minmax(), auto-fill, auto-fit — explicit and flexible | Grid for precise control, Flexbox for proportional distribution |
| Overlap | Not designed for overlap (use negative margins) | Native overlap with overlapping grid areas or same row/column assignment | Grid when elements need to overlap (hero sections, card designs) |
| Source order independence | order property reorders items within flex axis | grid-row/grid-column places items anywhere in the grid | Grid for complex reordering, but both support visual reordering |
| Responsive behavior | flex-wrap for responsive wrapping | auto-fill/auto-fit with minmax() for intrinsic responsiveness | Grid for no-media-query responsive grids, Flexbox for simple wrapping |
| Spacing | gap property (row-gap, column-gap) | gap property (row-gap, column-gap), identical syntax | Identical. Both use the same gap property |
| Named areas | Not available | grid-template-areas with named regions ("header" "main" "footer") | Grid for semantic layout definition with named areas |
| Subgrid | Not available | subgrid keyword for nested grids to adopt parent tracks | Grid for complex nested layouts requiring alignment with parent grid |
| Implicit tracks | Items wrap to new lines with flex-wrap | Auto-creates rows/columns for items placed outside defined grid | Grid for auto-generating tracks, Flexbox for natural wrapping |
| Browser support | 99.2% global support | 97.8% global support | Both have excellent support. Use either confidently in production. |
| Performance | Slightly faster for simple one-axis layouts | Slightly more layout computation for complex 2D grids | Negligible difference. Choose based on use case, not performance. |
| Use together | Grid children can be flex containers | Flex children can contain grids | Combine both: Grid for macro layout, Flexbox for micro alignment within grid cells |
Part 3: CSS Grid Deep Dive
CSS Grid is the most powerful layout system CSS has ever had. It lets you define rows and columns simultaneously, place items precisely by line number or named area, control spacing with gap, and create intrinsically responsive layouts without any media queries. Grid adoption reached 93% in 2026, up from 12% when it was first supported in 2017.
Defining a Grid
A grid is created with display: grid and configured with grid-template-columns and grid-template-rows. The fr unit distributes available space proportionally: grid-template-columns: 1fr 2fr 1fr creates three columns where the middle column is twice as wide as the others. The repeat() function reduces repetition: repeat(3, 1fr) equals 1fr 1fr 1fr. The minmax() function sets a size range: minmax(200px, 1fr) makes a column at least 200px but no wider than one fraction of available space.
Intrinsic Responsiveness
The combination of repeat(), auto-fill or auto-fit, and minmax() creates layouts that automatically adapt to the container width without media queries. The pattern grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)) creates as many columns as will fit with each being at least 250px wide, and remaining space is distributed equally. auto-fit collapses empty tracks so existing items stretch to fill the container; auto-fill keeps empty tracks, maintaining column width. This single line of CSS replaces dozens of lines of media queries.
Named Grid Areas
The grid-template-areas property lets you define a layout visually with ASCII art. Each string represents a row, and each word represents a column. Items are placed with grid-area: name. This is the most readable way to define complex page layouts because the CSS literally shows the layout structure. A two-column page with header and footer might be: “header header” “sidebar main” “footer footer”.
Subgrid
Subgrid, supported since 2023 (91.5% global support), allows a nested grid to inherit track definitions from its parent grid. Without subgrid, a card grid where each card is itself a grid creates independent track systems per card, so titles, images, and buttons do not align across cards. With subgrid, the inner grid adopts the parent grid lines, ensuring cross-card alignment. Syntax: display: grid; grid-template-rows: subgrid. This is essential for any layout where nested content must align with a parent grid.
CSS Feature Adoption Over Time (% of Surveyed Projects)
Source: OnlineTools4Free Research
Part 4: Custom Properties (CSS Variables)
CSS custom properties are native browser variables that cascade and inherit like regular CSS properties. Declared with --name: value and accessed with var(--name, fallback), they provide the foundation for theming, design tokens, and dynamic styling. At 97% adoption in 2026, custom properties have entirely replaced the need for preprocessor variables in most contexts.
How Custom Properties Differ from Preprocessor Variables
Sass and Less variables are compiled away at build time — they do not exist in the browser. Custom properties are live in the running page. This means they can be changed with JavaScript (element.style.setProperty), respond to media queries (redefine values inside @media blocks), inherit through the DOM tree, and be scoped to specific selectors. A dark mode theme can be implemented by overriding custom properties on a single root selector, with the entire site updating instantly.
The @property Rule
By default, custom properties are untyped strings. The @property rule registers a property with a type (color, length, angle, number, etc.), an initial value, and inheritance behavior. This enables the browser to interpolate and animate the property. Without @property, you cannot transition a gradient through a custom property because the browser does not know it is a color. With @property --hue { syntax: "<angle>"; inherits: false; initial-value: 0deg; }, you can animate hue shifts in pure CSS.
Design Tokens as Custom Properties
Design tokens are named values representing design decisions — colors, spacing, font sizes, border radii, shadows. Implementing tokens as custom properties on :root creates a single source of truth that both CSS and JavaScript can read. Frameworks like Open Props provide pre-built token sets. The pattern :root { --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 1rem; } defines a spacing scale used throughout the stylesheet with var(--space-2).
Key Finding
Custom properties at 97% adoption have replaced preprocessor variables for theming and design tokens.
Their runtime nature enables dark mode, responsive value changes, and JavaScript interaction that compiled variables cannot provide.
Part 5: Animations and Transitions
CSS provides three animation systems: transitions (smooth changes between two states), keyframe animations (multi-step animation sequences), and the newest addition, scroll-driven animations (animations linked to scroll position). Combined with @starting-style for entry animations and transition-behavior: allow-discrete for animating display changes, CSS in 2026 handles animation scenarios that previously required JavaScript animation libraries.
Transitions
Transitions animate a property change from one value to another over a specified duration. The shorthand transition: property duration timing-function delay covers the most common case. For example, transition: transform 200ms ease-out animates any transform change over 200 milliseconds with an ease-out curve. Transitions are ideal for hover states, focus indicators, and any interactive state change. Best practice: keep transition durations under 300ms for interface elements to feel responsive. Use ease-out for entrances and ease-in for exits.
Keyframe Animations
The @keyframes rule defines named animation sequences with percentage stops. Unlike transitions (which only animate between two states), keyframe animations support any number of intermediate steps and can run independently without user interaction. The animation shorthand combines name, duration, timing function, delay, iteration count, direction, fill mode, and play state. Animation-composition: add lets animations build on existing values rather than replacing them.
Scroll-Driven Animations
Scroll-driven animations (85.3% support in 2026) link animation progress to scroll position instead of time. Two timeline types exist: ScrollTimeline (animation-timeline: scroll()) maps animation progress to the scroll position of a scrollable container, useful for progress bars and parallax effects. ViewTimeline (animation-timeline: view()) maps animation progress to an element’s visibility in the viewport, useful for reveal-on-scroll and fade-in effects. These replace JavaScript IntersectionObserver and scroll event listeners with GPU-accelerated CSS.
Entry and Exit Animations
The @starting-style rule and transition-behavior: allow-discrete solve the long-standing problem of animating elements that change from display: none to display: block. @starting-style defines the initial style for an element entering the layout, and transition-behavior: allow-discrete allows the display property to participate in transitions. Together, they enable smooth show/hide animations without JavaScript, including modal dialogs, popovers, and accordion content.
CSS Animation and Transition Properties
16 rows
| Property | Values | Description | Default |
|---|---|---|---|
| animation-name | keyframe name | none | Specifies the name of the @keyframes at-rule defining the animation. | none |
| animation-duration | time (s or ms) | How long one cycle of the animation takes. | 0s |
| animation-timing-function | ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier() | steps() | linear() | The speed curve of the animation. | ease |
| animation-delay | time (s or ms) | Delay before the animation starts. Negative values start the animation partway through. | 0s |
| animation-iteration-count | number | infinite | How many times the animation should repeat. | 1 |
| animation-direction | normal | reverse | alternate | alternate-reverse | Whether the animation should play forwards, backwards, or alternate. | normal |
| animation-fill-mode | none | forwards | backwards | both | How styles are applied before and after the animation. | none |
| animation-play-state | running | paused | Whether the animation is running or paused. | running |
| animation-composition | replace | add | accumulate | How the animation values compose with existing values. | replace |
| animation-timeline | auto | none | scroll() | view() | --custom | Associates the animation with a scroll or view timeline. | auto |
| animation-range | normal | length-percentage | timeline-range-name | Start and end of the animation attachment range on a timeline. | normal |
| transition-property | property name | all | none | Which CSS properties should transition when changed. | all |
| transition-duration | time (s or ms) | How long the transition takes. | 0s |
| transition-timing-function | ease | linear | ease-in | ease-out | cubic-bezier() | linear() | The speed curve of the transition. | ease |
| transition-delay | time (s or ms) | Delay before the transition starts. | 0s |
| transition-behavior | normal | allow-discrete | Whether transitions can run on discrete properties (display, visibility). | normal |
Part 6: Container Queries
Container queries are the most requested CSS feature in history and the most impactful addition to responsive design since media queries. While media queries respond to the viewport (the browser window), container queries respond to the size of a component’s container element. This means a card component can adapt its layout whether it sits in a wide main content area, a narrow sidebar, or a full-width hero section, without the page knowing anything about the card’s responsive behavior.
Setting Up a Container
A container query requires two things: a containment context on the parent and a @container rule on the children. The parent element needs container-type: inline-size (for width queries) or container-type: size (for width and height queries). Optionally, container-name gives the container a name for targeted queries. The shorthand container: card / inline-size sets both name and type. Inside the container, child elements use @container card (min-width: 400px) { ... } to apply styles based on the container width.
Container Query Units
Container queries introduce new length units relative to the container: cqw (1% of container width), cqh (1% of container height), cqi (1% of container inline size), and cqb (1% of container block size). These enable font sizes, padding, and other values that scale with the component container rather than the viewport. A title set to font-size: 5cqw scales proportionally to its container width, making it naturally responsive without media queries or clamp().
Key Finding
Container queries went from 0% to 82% adoption in four years (2022-2026), the fastest CSS feature adoption on record.
This reflects pent-up demand for component-scoped responsive design. Every major component library now uses container queries for reusable layout patterns.
Container Query Breakpoint Patterns
11 rows
| Component | Min Width | Max Width | Layout | Behavior |
|---|---|---|---|---|
| Card layout | 0px | 300px | Stacked (vertical) | Image on top, content below. Single column. Text truncated. |
| Card layout | 301px | 600px | Horizontal | Image left, content right. Title and description visible. |
| Card layout | 601px | ∞ | Horizontal expanded | Image left, content right, extra metadata shown. Wider content area. |
| Navigation | 0px | 480px | Hamburger menu | Collapsed behind a menu button. Only logo visible. |
| Navigation | 481px | ∞ | Horizontal links | Full horizontal navigation with all links visible. |
| Sidebar widget | 0px | 200px | Compact | Minimal info, small font, stacked elements. |
| Sidebar widget | 201px | ∞ | Full | Full content with charts, descriptions, and action buttons visible. |
| Data table | 0px | 500px | Card list | Each row becomes a card. Headers hidden. Labels shown inline. |
| Data table | 501px | ∞ | Traditional table | Standard table layout with columns and headers. |
| Form layout | 0px | 400px | Stacked fields | Labels above inputs, full-width fields, single column. |
| Form layout | 401px | ∞ | Inline fields | Labels beside inputs, multi-column layout for related fields. |
Part 7: Cascade Layers
Cascade layers (@layer) solve the specificity problem that has plagued CSS since its inception. Before layers, the only way to override a high-specificity selector was to write an even higher-specificity selector or resort to !important. This led to escalating specificity wars where stylesheets became increasingly fragile and difficult to maintain. Layers introduce an explicit priority ordering that takes precedence over specificity.
How Layers Work
You declare layers with @layer followed by a name. Layers are prioritized in the order they are first declared: later layers override earlier layers regardless of selector specificity. A utility class (.text-center) in the utilities layer beats an ID selector (#main .content .title) in the components layer because utilities is declared after components. This inversion of control means you define the priority architecture once and write styles without worrying about selector weight.
Recommended Layer Architecture
A common layer order is: @layer reset, base, theme, components, utilities. Reset styles (normalize, box-sizing) go in the lowest layer because everything should be able to override them. Base styles (typography, default element styles) go next. Theme tokens (custom properties, brand colors) layer above base. Component styles (buttons, cards, forms) override theme defaults. Utility classes sit at the top, providing the final override capability. Unlayered CSS always beats all layered CSS, serving as an escape hatch.
The !important Reversal
With !important inside layers, the priority order reverses: earlier layers win. This means a !important rule in the reset layer beats a !important rule in the utilities layer. This reversal is intentional — it ensures that foundational rules (like box-sizing: border-box !important in a reset) cannot be accidentally overridden by higher-layer !important declarations. This makes !important predictable for the first time in CSS history.
Cascade Layer Priority Order
8 rows
| Layer | Priority | Overridden By | Description |
|---|---|---|---|
| Browser defaults (user-agent) | 1 | All author styles | Built-in browser styles. Reset with CSS reset or normalize.css. Lowest priority. |
| @layer reset | 2 | All subsequent layers | CSS reset or normalize styles. Foundation layer. Easiest to override. |
| @layer base | 3 | Theme, components, utilities, unlayered | Base element styles. Typography, colors, spacing defaults. |
| @layer theme | 4 | Components, utilities, unlayered | Theming tokens, design system variables, brand colors. |
| @layer components | 5 | Utilities, unlayered | Component styles. Cards, buttons, forms, navigation. |
| @layer utilities | 6 | Unlayered styles only | Utility classes. Overrides component defaults. Like Tailwind utilities. |
| Unlayered styles | 7 | !important in earlier layers | Any CSS not inside an @layer. Always beats layered styles regardless of specificity. |
| !important (reversed order) | 8 | User !important, UA !important | With !important, layer order reverses: earlier layers win. Reset !important beats utilities !important. |
Part 8: CSS Nesting and Modern Syntax
Native CSS nesting, supported since late 2023 (88.6% global support), lets you write selectors inside their parent rule blocks, eliminating one of the primary reasons developers adopted Sass or Less. The & symbol references the parent selector, just as in preprocessors. However, there is a key difference: in native CSS, you cannot concatenate & with strings (no &__element or &--modifier), which means BEM-style concatenation still requires a preprocessor or separate rules.
Nesting Syntax
Inside a rule block, nested selectors are prefixed with & (explicit) or can use type selectors directly if the browser can unambiguously parse them. Pseudo-classes and pseudo-elements work naturally: .card { &:hover { box-shadow: ... } &::after { content: "" } }. Media queries can also be nested: .card { @media (width > 768px) { padding: 2rem } }. This collocates responsive behavior with the component it affects, improving readability.
@scope
The @scope rule (86.2% support) limits selector reach to a subtree of the document. Syntax: @scope (.card) to (.card__footer) { p { color: gray; } }. The selectors inside only match elements between the scope root (.card) and the scope limit (.card__footer). This provides CSS-native component scoping without the build-time hashing of CSS Modules or the runtime overhead of CSS-in-JS. Combined with cascade layers, @scope creates a complete solution for large-scale CSS architecture.
Other Modern CSS Features
Several other modern CSS features are worth noting. text-wrap: balance (87.1% support) distributes text across lines to minimize ragged edges in headings. The Popover API (86.5% support) provides native show/hide behavior for tooltips and menus with CSS :popover-open styling. Anchor positioning (72.4% support) places elements relative to other elements without JavaScript — ideal for tooltips and dropdown menus. The View Transitions API (83.7% support) animates between page states with automatic crossfade effects.
Global Browser Support for Modern CSS Features (%)
Source: OnlineTools4Free Research
Part 9: Color Functions in CSS
CSS color handling has transformed from a handful of simple functions (rgb, hsl, hex) into a sophisticated system of perceptually uniform color spaces, wide-gamut support, and programmatic color manipulation. In 2026, oklch() is the recommended color function for new projects because it provides perceptually uniform lightness, an intuitive hue angle, and a chroma axis that maps to human color perception.
oklch() and Why It Matters
The fundamental problem with hsl() is perceptual non-uniformity: yellow at hsl(60, 100%, 50%) appears dramatically brighter than blue at hsl(240, 100%, 50%), despite both having 50% lightness. OKLCH solves this — equal lightness values look equally bright regardless of hue. This makes programmatic color scale generation (design system color ramps, tint/shade generation, accessible palette creation) mathematically correct rather than requiring manual adjustments.
color-mix() and Relative Color Syntax
The color-mix() function blends two colors in a specified color space: color-mix(in oklch, var(--primary) 70%, white) creates a tint. The relative color syntax derives new colors from existing ones: oklch(from var(--color) calc(l + 0.1) c h) lightens a color by increasing its OKLCH lightness. These functions replace the need for Sass lighten() and darken() functions with native CSS that works at runtime, responds to custom property changes, and produces perceptually accurate results.
Wide Gamut and light-dark()
The color() function accesses wide-gamut colors: color(display-p3 1 0 0) produces a red more vivid than any sRGB red. Use @media (color-gamut: p3) for progressive enhancement. The light-dark() function (82.5% support) returns different values based on the computed color-scheme, simplifying dark mode: background: light-dark(white, #1a1a1a). Combined with color-scheme: light dark on :root, this eliminates the need for separate media queries for simple color swaps.
CSS Color Functions Reference
12 rows
| Function | Color Space | Perceptual | Best For | Support % |
|---|---|---|---|---|
| rgb() | sRGB | No | General purpose, legacy compatibility | 99.5 |
| hsl() | sRGB | No | Intuitive color manipulation, theming | 99.5 |
| hwb() | sRGB | No | Intuitive tinting/shading from pure hue | 96.2 |
| lab() | CIE Lab | Yes (approximately) | Perceptual lightness adjustments | 90.2 |
| lch() | CIE LCH | Yes (approximately) | Perceptual chroma/hue manipulation | 90.2 |
| oklab() | OKLab | Yes (improved) | Best perceptual color mixing and interpolation | 90.2 |
| oklch() | OKLCH | Yes (improved) | Recommended for design systems, theming, palettes | 90.2 |
| color() | Any specified | Depends | Access to wide-gamut colors (P3, Rec2020) | 89.4 |
| color-mix() | Specified in function | Depends on space | Mixing colors, tints, shades, design tokens | 89.8 |
| light-dark() | sRGB | N/A | Dark mode colors without custom properties | 82.5 |
| contrast-color() | N/A | N/A | Automatic accessible text color based on background | 15 |
| relative color syntax | Any | Depends | Derive colors from a base: lighten, darken, desaturate | 88.1 |
Part 10: Selectors and Pseudo-Classes
CSS selectors are the language for targeting elements in the DOM. Modern CSS has expanded the selector toolkit dramatically: :has() enables parent selection, :is() and :where() reduce repetition and control specificity, :nth-child(n of S) filters before counting, :user-invalid provides better form validation UX, and :popover-open styles the new Popover API. Understanding the full selector repertoire eliminates the need for JavaScript class toggling in many scenarios.
The :has() Selector
The :has() selector is the most significant new selector in CSS history. It matches elements that contain descendants matching its argument, effectively giving CSS the “parent selector” it lacked for 25 years. div:has(> img) selects divs that directly contain images. form:has(:invalid) selects forms containing invalid fields. h2:has(+ p) selects h2 elements followed by a paragraph (previous sibling selection). Before :has(), all of these patterns required JavaScript.
:is(), :where(), and Specificity Control
:is() matches any element that matches any selector in its argument list: :is(h1, h2, h3) { color: navy; } replaces three separate rules. Its specificity equals its most specific argument. :where() is identical in behavior but always has zero specificity, making it perfect for base styles that are easy to override. :not() now accepts complex selector lists: :not(.a, .b) matches elements without either class. Understanding the specificity behavior of these functional selectors is essential for modern CSS architecture.
Key Finding
The :has() selector enables parent selection, previous sibling selection, and complex relational queries — patterns that required JavaScript for 25 years.
At 91.1% global support, :has() is production-ready. It reduces JavaScript DOM manipulation code significantly for conditional styling.
CSS Pseudo-Classes Reference (45+ Selectors)
46 rows
| Selector | Category | Description | Notes |
|---|---|---|---|
| :hover | User Action | When the user hovers over an element with a pointing device. | Not available on touch devices. Use @media (hover: hover) to detect. |
| :focus | User Action | When an element receives focus (keyboard tab, click, or programmatic focus). | Accessibility critical. Never remove outline without providing an alternative. Use :focus-visible for keyboard-only. |
| :focus-visible | User Action | When an element receives focus AND the browser determines a focus indicator should be shown (typically keyboard navigation). | Best practice: use :focus-visible instead of :focus for visible indicators. Hides ring on mouse click, shows on Tab. |
| :focus-within | User Action | When an element or any of its descendants receives focus. | Useful for highlighting form containers, dropdown menus, and interactive sections. |
| :active | User Action | When an element is being activated (mouse button pressed, or key pressed on a focused element). | Very brief state between mousedown and mouseup. Provides tactile feedback. |
| :visited | Link | Matches links that have been visited. Limited styling for privacy reasons. | For privacy, only color, background-color, border-color, outline-color can be changed. getComputedStyle lies about visited state. |
| :link | Link | Matches unvisited links with an href attribute. | Equivalent to a[href]:not(:visited). Rarely used explicitly since a {} covers all links. |
| :any-link | Link | Matches any anchor element with an href, whether visited or not. | More specific than a {} (only matches elements with href). Equivalent to :link or :visited. |
| :checked | Form State | Matches checked checkboxes, radio buttons, or selected option elements. | Foundation for checkbox hack (toggle without JavaScript). Works with input[type=checkbox] and input[type=radio]. |
| :disabled | Form State | Matches form elements that are disabled (have the disabled attribute). | Inherited by child elements of disabled fieldset. Pair with :enabled for complete styling. |
| :enabled | Form State | Matches form elements that are not disabled. | Default state for form elements. Use to explicitly style enabled elements differently from disabled. |
| :required | Form State | Matches form elements with the required attribute. | Use with :valid/:invalid for complete form validation styling. Indicates mandatory fields. |
| :optional | Form State | Matches form elements without the required attribute. | Opposite of :required. Default state for form elements. |
| :valid | Form State | Matches form elements whose content validates against their type/pattern. | Based on HTML5 validation (type, pattern, min, max, required). Applies before user interaction, which can be confusing. |
| :invalid | Form State | Matches form elements whose content fails validation. | Matches from page load (empty required fields are invalid immediately). Use :user-invalid for better UX. |
Page 1 of 4
Part 11: CSS Performance Optimization
CSS performance affects both loading time (how quickly the browser can parse and apply styles) and runtime performance (how smoothly animations run and how fast the browser reflows the layout). The browser rendering pipeline follows a strict sequence: parse CSS, compute styles, layout (reflow), paint, composite. Understanding which CSS changes trigger which pipeline stages is the key to high-performance interfaces.
The Rendering Pipeline
Layout changes (width, height, margin, padding, position) trigger the full pipeline: reflow, paint, and composite. Paint-only changes (color, background, visibility, box-shadow) skip layout but still repaint. Compositor-only changes (transform, opacity) run entirely on the GPU without triggering layout or paint, making them the fastest properties to animate. This is why the universal animation rule is: only animate transform and opacity for guaranteed 60fps performance.
content-visibility: auto
The content-visibility property tells the browser to skip rendering off-screen content entirely. Setting content-visibility: auto on sections of a long page can reduce initial render time by 30-50% because the browser only renders elements near the viewport. Pair it with contain-intrinsic-size: auto 500px to give the browser an estimated height so the scrollbar behaves correctly even for unrendered content.
Critical CSS and Code Splitting
CSS is render-blocking: the browser cannot display anything until it has parsed all linked CSS files. Critical CSS extraction identifies the CSS needed for above-the-fold content and inlines it in the HTML head, allowing the rest of the CSS to load asynchronously. This typically improves Largest Contentful Paint (LCP) by 15-40%. Modern frameworks (Next.js, Nuxt) handle CSS code splitting automatically, loading only the CSS needed for each page.
CSS Performance Optimization Strategies
10 rows
| Strategy | Impact | Complexity | Expected Improvement |
|---|---|---|---|
| Critical CSS inlining | High | Medium | LCP improvement: 15-40% |
| CSS code splitting | Medium | Medium | First paint: 10-25% faster |
| Unused CSS removal (purging) | High | Low | CSS size: 80-95% reduction |
| content-visibility: auto | High | Low | Initial render: 30-50% faster |
| CSS containment (contain property) | Medium | Low | Reflow cost: 20-40% reduction |
| Compositor-only animations | High | Low | Animation FPS: 30fps to 60fps |
| will-change optimization | Medium | Low | Animation start: 10-30ms faster |
| Font subsetting | Medium | Medium | Font download: 50-90% smaller |
| CSS minification + compression | Medium | Low | Transfer size: 80-90% reduction |
| Reduce selector complexity | Low | Low | Style recalc: 5-15% faster |
Part 12: CSS Methodologies and Architecture
How you organize CSS matters more than any individual feature. A poorly organized stylesheet becomes unmaintainable at scale regardless of how modern the CSS features are. The CSS methodology landscape in 2026 is dominated by Tailwind CSS (60%), vanilla CSS with native features (48%), and CSS Modules (32%), while runtime CSS-in-JS has declined to 10%. Newer approaches like Panda CSS (22%) and Open Props (18%) bridge the gap between CSS-in-JS developer experience and native CSS performance.
The Rise and Decline of CSS-in-JS
CSS-in-JS peaked at 38% adoption in 2018, driven by React’s component model and the desire for scoped, dynamic styles. Its decline to 10% in 2026 has multiple causes: runtime performance overhead (injecting and updating style tags in the browser), complexity with server-side rendering, incompatibility with React Server Components (RSC cannot use client-side style injection), and the emergence of native CSS features (nesting, layers, scope) that cover the same use cases without runtime cost. Build-time alternatives like Panda CSS and Meta’s StyleX extract static CSS at build time, preserving the developer experience without the runtime penalty.
Modern CSS Architecture
The recommended architecture in 2026 combines cascade layers for priority management, custom properties for theming, @scope for component isolation, and nesting for readability. This gives you the organizational benefits of ITCSS (layered architecture), the scoping of CSS Modules (isolated components), the theming of CSS-in-JS (runtime variables), and the readability of Sass (nesting) — all with native browser features that require no build tools.
Runtime CSS-in-JS Adoption Over Time (%)
Source: OnlineTools4Free Research
CSS Methodology Comparison 2026
8 rows
| Methodology | Usage (%) | Learning Curve | Scalability | Pros | Cons |
|---|---|---|---|---|---|
| BEM | 42 | Easy | Good | Simple naming convention, self-documenting, works everywhere | Verbose HTML classes, no enforced scoping, manual discipline required |
| Tailwind CSS | 60 | Medium | Excellent | No naming, no specificity issues, consistent design, tree-shaking | Verbose HTML, learning curve for class names, build step required |
| CSS Modules | 32 | Easy | Good | Automatic scoping, works with existing CSS knowledge, component-level | Build tool required, composition can be awkward, no dynamic theming |
| Cascade Layers | 28 | Medium | Excellent | Native browser feature, eliminates specificity wars, composable | Newer (some team knowledge gaps), requires architectural thinking |
| ITCSS | 15 | Medium | Excellent | Well-organized, minimizes specificity conflicts, pairs with BEM | Strict structure, overhead for small projects, less popular now |
| Styled Components | 8 | Medium | Good | Dynamic styling, automatic scoping, co-located with components | Runtime cost, SSR complexity, declining popularity, larger bundles |
| Panda CSS | 22 | Medium | Excellent | Type-safe, zero runtime, design tokens, RSC compatible | Newer ecosystem, build step required, smaller community |
| Open Props | 18 | Easy | Good | Native CSS, great defaults, tree-shakeable, framework-agnostic | Not a full methodology, still needs organization strategy |
Try These Tools for Free
Put this knowledge into practice with our browser-based tools. No signup needed.
CSS Formatter
Format and beautify CSS code with consistent spacing and indentation.
CSS Minifier
Minify CSS code to reduce file size and improve page load speed.
Box Shadow
Design CSS box shadows visually with multiple layers, presets, and live preview.
Flexbox Gen
Build flexbox layouts visually with controls for direction, alignment, wrapping, and gap.
Grid Gen
Build CSS Grid layouts visually with template columns, rows, gap, and auto-flow controls.
Gradient Gen
Create beautiful CSS gradients with a visual editor. Linear, radial, and conic gradients.
Animation Gen
Create CSS keyframe animations visually with timing controls and live preview.
Clip Path
Create custom CSS clip-path shapes with draggable polygon points and presets.
Related Research Reports
The Complete Tailwind CSS Guide 2026: Utility-First, Config, Plugins, v4, Responsive & Dark Mode
The definitive Tailwind CSS reference for 2026. Covers utility-first methodology, custom configuration, plugins, v4 changes, responsive design, and dark mode. 40+ glossary, 15 FAQ. 30,000+ words.
The Complete UI/UX Design Systems Guide 2026: Tokens, Typography, Color, Components & Accessibility
The definitive design systems guide for 2026. Covers design tokens, typography scale, color systems, spacing, grid systems, component architecture, accessibility, dark mode, responsive design, animation, icon systems, and documentation. 10+ design system comparisons. 30,000+ words.
The Complete Web Animation Guide 2026: CSS, GSAP, Framer Motion, Lottie & Scroll-Driven
The definitive web animation reference for 2026. Covers CSS animations, GSAP, Framer Motion, Lottie, and scroll-driven animations. 40+ glossary, 15 FAQ. 30,000+ words.
CSS Units Reference
CSS has 24+ length units spanning absolute, relative, viewport, container, and special-purpose categories. Choosing the right unit is critical for responsive, accessible, and maintainable CSS. The general guidance: rem for font sizes, px for borders, % or fr for widths, dvh for full-height sections, ch for line lengths, and cqw for container-relative sizing.
Complete CSS Units Reference (24 Units)
24 rows
| Unit | Type | Relative To | Best For | Responsive |
|---|---|---|---|---|
| px | Absolute | Screen pixel (1/96th of 1in) | Borders, shadows, small fixed elements | No |
| em | Relative | Font size of the parent element | Typography, spacing relative to text | Yes |
| rem | Relative | Font size of the root element (html) | Global spacing, font sizes, media queries | Yes |
| % | Relative | Parent element (context-dependent) | Widths, fluid layouts, backgrounds | Yes |
| vw | Viewport | 1% of viewport width | Full-width elements, responsive typography | Yes |
| vh | Viewport | 1% of viewport height | Full-height sections, hero areas | Yes |
| dvw / dvh | Viewport | Dynamic viewport (excludes browser UI) | Mobile full-screen layouts | Yes |
| svw / svh | Viewport | Small viewport (browser UI visible) | Minimum guaranteed viewport | Yes |
| lvw / lvh | Viewport | Large viewport (browser UI hidden) | Maximum viewport size | Yes |
| ch | Relative | Width of the "0" character in the font | Input widths, line lengths | Yes |
| ex | Relative | x-height of the font (height of lowercase "x") | Vertical alignment with text | Yes |
| cap | Relative | Height of capital letters in the font | Icon sizing relative to text | Yes |
Page 1 of 2
Browser Support Matrix
Modern CSS features enjoy broad browser support. Flexbox, Grid, and custom properties are above 97% global support. Newer features like container queries (92.4%), cascade layers (93.8%), and :has() (91.1%) have crossed the threshold for confident production use. Only anchor positioning (72.4%) remains in the progressive enhancement category where a fallback is still advisable.
CSS Feature Browser Support Matrix (2026)
20 rows
| Feature | Chrome | Firefox | Safari | Global % | Spec Status |
|---|---|---|---|---|---|
| Flexbox | Full (29+) | Full (28+) | Full (9+) | 99.2 | Recommendation |
| Grid | Full (57+) | Full (52+) | Full (10.1+) | 97.8 | Recommendation |
| Subgrid | Full (117+) | Full (71+) | Full (16+) | 91.5 | Recommendation |
| Custom Properties | Full (49+) | Full (31+) | Full (9.1+) | 98.1 | Recommendation |
| Container Queries | Full (105+) | Full (110+) | Full (16+) | 92.4 | Working Draft |
| Cascade Layers (@layer) | Full (99+) | Full (97+) | Full (15.4+) | 93.8 | Recommendation |
| CSS Nesting | Full (120+) | Full (117+) | Full (17.2+) | 88.6 | Working Draft |
| oklch() / oklab() | Full (111+) | Full (113+) | Full (15.4+) | 90.2 | Recommendation |
| color-mix() | Full (111+) | Full (113+) | Full (16.2+) | 89.8 | Recommendation |
| :has() selector | Full (105+) | Full (121+) | Full (15.4+) | 91.1 | Recommendation |
Page 1 of 2
CSS Framework Usage Trends
The CSS framework landscape shifted decisively between 2022 and 2026. Tailwind CSS grew from 28% to 60%, while Bootstrap declined from 52% to 34%. Vanilla CSS with native features rose from 35% to 48%, reflecting the improved capability of the language itself. Runtime CSS-in-JS approaches (Styled Components, Emotion) declined from 18% to 8%. Build-time CSS-in-JS (Panda CSS) and atomic CSS engines (UnoCSS) emerged as new contenders.
CSS Framework Usage: 2022 vs. 2024 vs. 2026 (%)
Source: OnlineTools4Free Research
Glossary (60+ Terms)
A comprehensive glossary of CSS terminology, from foundational concepts to the newest features.
Box Model
LayoutThe fundamental CSS layout concept. Every element is a rectangular box composed of four areas: content, padding, border, and margin. The box-sizing property controls whether width/height includes padding and border (border-box) or only content (content-box). Understanding the box model is essential for predicting element sizes and spacing.
Content Box
LayoutThe innermost area of the box model containing the actual content (text, images, child elements). By default (box-sizing: content-box), width and height properties set the content box dimensions only, and padding and border are added on top.
Padding
LayoutThe space between the content area and the border. Transparent by default, it takes the background color/image of the element. Can be set individually (padding-top, padding-right, etc.) or with shorthand. Negative padding is not allowed.
Border
LayoutThe line surrounding the padding area. Has width, style (solid, dashed, dotted, etc.), and color properties. Can be set individually per side. Participates in the box model size unless box-sizing: border-box is used.
Margin
LayoutThe outermost space around an element, creating distance from other elements. Can be negative (to overlap elements). Vertical margins collapse: two adjacent 20px margins create 20px gap, not 40px. Margin does not take background color.
Margin Collapse
LayoutWhen two vertical margins (top and bottom) of adjacent block-level elements touch, they collapse into a single margin equal to the larger of the two. This only happens vertically, never horizontally. Prevented by: padding, border, flex/grid containers, overflow other than visible, or float.
Specificity
CascadeThe algorithm browsers use to determine which CSS rule applies when multiple rules target the same element. Calculated as (ID, Class, Element) weight. Inline styles beat IDs, IDs beat classes, classes beat elements. !important overrides all. Modern selectors like :is() take the highest specificity of their arguments.
Cascade
CascadeThe algorithm that determines which CSS declarations apply to each element when multiple sources of CSS exist. Priority order: importance (!important), origin (author > user > agent), layer order, specificity, then source order. The cascade is the "C" in CSS.
Inheritance
CascadeSome CSS properties are inherited by child elements from their parents. Typography properties (font-family, color, line-height) inherit by default. Layout properties (width, margin, padding) do not. Use "inherit" keyword to force inheritance, "initial" to reset, "unset" to follow natural behavior.
Cascade Layers
CascadeA CSS feature (@layer) that introduces explicit layering into the cascade, allowing authors to control the priority of style sets without relying on specificity or source order. Styles in later-declared layers override earlier layers. Unlayered styles override all layers.
Custom Properties (CSS Variables)
Custom PropertiesUser-defined properties prefixed with -- that store values for reuse throughout a stylesheet. Declared with --name: value and accessed with var(--name, fallback). They cascade and inherit like regular properties. Foundation for theming and design tokens.
var()
Custom PropertiesThe CSS function used to access custom property values. Syntax: var(--property-name, fallback-value). The fallback is used when the custom property is not defined or is invalid. Fallbacks can be other var() calls. Computed at use time, not declaration time.
@property
Custom PropertiesAn at-rule that formally registers a custom property with a specified type, inheritance behavior, and initial value. Enables browser type-checking and animations of custom properties. Syntax: @property --name { syntax: "<color>"; inherits: false; initial-value: blue; }
Flexbox
LayoutA one-dimensional layout model for arranging items in rows or columns. Items can flex to fill available space or shrink to prevent overflow. Key properties: display: flex, flex-direction, justify-content, align-items, flex-grow, flex-shrink, flex-basis, gap.
Flex Container
LayoutAn element with display: flex or display: inline-flex. Its direct children become flex items. The container controls the main axis (flex-direction), alignment (justify-content, align-items), and wrapping behavior (flex-wrap).
Flex Item
LayoutA direct child of a flex container. Controlled by flex-grow (how much extra space to take), flex-shrink (how much to shrink), and flex-basis (initial size before growing/shrinking). The shorthand flex: 1 is equivalent to flex: 1 1 0%.
Main Axis
LayoutThe primary axis of a flex container along which flex items are laid out. Defined by flex-direction: row (horizontal) or column (vertical). justify-content aligns items along the main axis.
Cross Axis
LayoutThe axis perpendicular to the main axis in a flex container. If the main axis is horizontal (row), the cross axis is vertical. align-items and align-self control alignment along the cross axis.
CSS Grid
LayoutA two-dimensional layout system for creating complex grid-based layouts with rows and columns simultaneously. Key properties: display: grid, grid-template-columns, grid-template-rows, grid-template-areas, gap, grid-column, grid-row.
Grid Track
LayoutA row or column in a grid layout. Defined by grid-template-rows and grid-template-columns. Can use fixed sizes (px), flexible sizes (fr), auto, minmax(), and repeat(). A track is the space between two adjacent grid lines.
Grid Line
LayoutThe dividing lines that make up the grid structure. Lines are numbered starting from 1. Can be named for easier reference: grid-template-columns: [start] 1fr [mid] 1fr [end]. Items are placed between lines.
Grid Cell
LayoutThe smallest unit of the grid, formed by the intersection of a row track and a column track. A single grid cell occupies one column and one row. Grid items can span multiple cells.
Grid Area
LayoutA rectangular area spanning one or more grid cells. Can be named with grid-template-areas for semantic layout definition. Items are placed into areas with grid-area property.
Subgrid
LayoutA grid item that adopts its parent grid tracks for its own grid layout, allowing nested grids to align with the parent grid lines. Syntax: grid-template-columns: subgrid. Essential for consistent alignment in complex nested layouts.
fr Unit
LayoutA fractional unit that distributes available space in a grid container. 1fr 2fr means the second column gets twice the remaining space. Available space = container size minus fixed-size tracks. Only valid in grid contexts.
minmax()
LayoutA CSS function used in grid track sizing to define a minimum and maximum size range. Syntax: minmax(200px, 1fr). The track will be at least 200px and at most 1fr of available space. Essential for responsive grids.
auto-fill
LayoutA keyword used with repeat() in grid to create as many tracks as will fit in the container. Empty tracks remain even without content. Syntax: grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)).
auto-fit
LayoutLike auto-fill but collapses empty tracks to zero width, allowing remaining tracks to expand to fill the container. The go-to for responsive grids that stretch to fill available space.
Container Query
ResponsiveA CSS feature that allows styling elements based on the size of their container rather than the viewport. Requires a containment context (container-type: inline-size). Queried with @container. Enables truly component-scoped responsive design.
container-type
ResponsiveEstablishes an element as a query container. Values: inline-size (query width), size (query width and height), normal (no size queries). Required for @container rules to work.
container-name
ResponsiveGives a name to a query container for targeted container queries. Syntax: container-name: card. Queried with @container card (min-width: 300px). Multiple containers can have different names.
Container Units (cqw, cqh, cqi, cqb)
ResponsiveLength units relative to the container dimensions. cqw = 1% of container width, cqh = 1% of container height, cqi = 1% of container inline size, cqb = 1% of container block size. Enable container-relative sizing.
@media
ResponsiveAn at-rule for applying styles conditionally based on device characteristics: viewport width, color scheme preference, hover capability, pointer type, orientation, resolution, and more. Foundation of responsive web design since 2010.
Nesting
SyntaxNative CSS feature allowing selectors to be written inside their parent rule blocks, similar to Sass/Less. Reduces repetition and improves readability. Child selectors are prefixed with & or use the implicit nesting context.
@layer
CascadeAn at-rule that declares cascade layers. Layers provide explicit priority ordering independent of specificity or source order. Later-declared layers have higher priority. Styles outside layers override all layers.
@scope
CascadeAn at-rule that limits the reach of selectors to a subtree of the document. Syntax: @scope (.card) to (.card__footer) { ... }. Selectors inside only match within the scope root and stop at the scope limit.
BEM (Block Element Modifier)
MethodologyA CSS naming methodology: .block__element--modifier. Block = standalone component (.card), Element = part of block (.card__title), Modifier = variation (.card--featured). Prevents naming collisions and improves readability.
ITCSS (Inverted Triangle CSS)
MethodologyA CSS architecture that organizes styles from generic to specific: Settings, Tools, Generic, Elements, Objects, Components, Utilities. Each layer is more specific than the last, reducing specificity conflicts.
Utility-First CSS
MethodologyA methodology where styling is done primarily through small, single-purpose utility classes in HTML (e.g., class="flex items-center gap-4 p-2"). Popularized by Tailwind CSS. Avoids naming and specificity issues.
CSS-in-JS
MethodologyAn approach where CSS is authored in JavaScript files, often scoped to components. Libraries: styled-components, Emotion, Linaria. Declining in popularity as native CSS features (nesting, layers, scope) cover similar needs with better performance.
Design Token
Design SystemsA named value representing a design decision (color, spacing, font size, etc.). Stored as CSS custom properties, JSON, or platform-specific formats. Foundation of design systems. Example: --color-primary: oklch(0.55 0.15 250).
Logical Properties
InternationalizationCSS properties that map to the writing direction rather than physical direction. margin-inline-start instead of margin-left. Enables proper internationalization for RTL languages. inline = horizontal in LTR, block = vertical in LTR.
Writing Mode
InternationalizationThe writing-mode property controls the direction of block flow (horizontal-tb, vertical-rl, vertical-lr). Changes how inline and block axes are oriented. Essential for proper East Asian language support and creative layouts.
Containing Block
LayoutThe reference box used to calculate percentage sizes and positions of an element. For position: static/relative, it is the content box of the nearest block ancestor. For position: absolute, it is the padding box of the nearest positioned ancestor. For position: fixed, it is the viewport.
Block Formatting Context (BFC)
LayoutAn independent layout context where the internal layout does not affect outside elements. Created by: overflow other than visible, display: flow-root, flex/grid containers, position: absolute/fixed, float. Prevents margin collapse and contains floats.
Stacking Context
LayoutA three-dimensional layer ordering system. Elements with z-index on positioned elements, opacity < 1, transform, filter, will-change, and other properties create new stacking contexts. z-index only works within the same stacking context.
Paint Order
LayoutThe order in which elements are rendered: backgrounds and borders, negative z-index children, block-level children, float children, inline children, positioned children with z-index. Understanding paint order explains many z-index confusions.
Repaint
PerformanceWhen the browser redraws an element visual appearance without changing its layout (e.g., changing color, background, visibility). Less expensive than reflow. Properties like transform and opacity can be painted on the GPU for better performance.
Reflow (Layout Thrashing)
PerformanceWhen the browser recalculates the geometry and position of elements due to layout changes. Triggered by: changing width/height, adding/removing elements, reading offsetWidth/scrollTop. Batch DOM reads and writes to avoid layout thrashing.
Compositing
PerformanceThe final rendering step where the browser combines painted layers into the final screen image. Elements promoted to their own compositor layer (via will-change, transform: translateZ(0)) can be animated without triggering repaints of other elements.
will-change
PerformanceA CSS property that hints to the browser which properties will change, allowing optimization. Example: will-change: transform. Creates a new stacking context and compositor layer. Use sparingly as overuse wastes memory. Remove when animation is complete.
content-visibility
PerformanceA CSS property that enables the browser to skip rendering work for off-screen content. content-visibility: auto only renders elements when they are near the viewport. Can drastically improve initial page load for long pages. Use with contain-intrinsic-size.
contain
PerformanceA CSS property that tells the browser an element subtree is independent from the rest of the page, enabling optimization. Values: layout, paint, size, style, content (shorthand for layout + paint), strict (shorthand for all). Used for container queries.
@keyframes
AnimationAn at-rule that defines the intermediate steps in a CSS animation sequence. Syntax: @keyframes name { from { ... } to { ... } } or using percentage stops (0%, 25%, 50%, 100%). Referenced by animation-name property.
Scroll-Driven Animation
AnimationAnimations linked to scroll progress or element visibility within the viewport. Uses animation-timeline: scroll() or animation-timeline: view(). Replaces JavaScript scroll listeners for scroll-linked effects with much better performance.
View Transition
AnimationA browser API (document.startViewTransition) and CSS features (view-transition-name, ::view-transition-*) for animating between page states. Creates smooth transitions between pages (MPA) or DOM updates (SPA). Automatic crossfade by default.
@starting-style
AnimationAn at-rule defining the starting style for elements entering the DOM or becoming visible. Enables entry animations for display: none to display: block transitions. Solves the long-standing problem of animating element entry.
transition-behavior: allow-discrete
AnimationA property that enables transitions on discrete properties like display and visibility. Combined with @starting-style, allows smooth show/hide animations without JavaScript. Example: transition: opacity 0.3s, display 0.3s allow-discrete.
Anchor Positioning
PositioningA CSS feature for positioning elements relative to an "anchor" element elsewhere in the DOM. Replaces JavaScript-based tooltip and popover positioning. Uses anchor-name and position-anchor properties with position-area or anchor() function.
Popover API
UIAn HTML/CSS feature for creating popover UI (tooltips, menus, dialogs) declaratively. The popover attribute on HTML elements enables showing/hiding with popovertarget. CSS :popover-open pseudo-class styles the open state. Built-in focus management and light-dismiss.
Relative Color Syntax
ColorA CSS feature for deriving new colors from existing ones by modifying individual channels. Syntax: oklch(from var(--color) calc(l + 0.1) c h). Enables programmatic color manipulation (lighten, darken, desaturate) in pure CSS.
color-mix()
ColorA CSS function that mixes two colors in a specified color space. Syntax: color-mix(in oklch, var(--primary) 70%, white). Useful for generating tints, shades, and intermediate colors. The color space affects how colors blend.
Gamut Mapping
ColorThe process of converting colors from one color space gamut to another when the destination cannot display the source color. Browsers automatically gamut-map out-of-range colors. Wide-gamut displays (P3) can show colors outside sRGB.
@supports
Progressive EnhancementAn at-rule for conditional CSS based on browser feature support. Syntax: @supports (display: grid) { ... }. Can use not, and, or operators. Enables progressive enhancement by targeting browsers that support specific features.
Feature Query
Progressive EnhancementA @supports rule that tests for CSS property/value support. Used for progressive enhancement: base styles for all browsers, enhanced styles for supporting browsers. Example: @supports (container-type: inline-size) { ... }.
FAQ (20 Questions)
Try It Yourself
Format, generate, and experiment with CSS using our interactive tools below.
Paste any CSS and instantly format, beautify, or minify it.
Try it yourself
Css Formatter
Generate CSS box-shadow values visually with real-time preview.
Try it yourself
Box Shadow Generator
Build Flexbox layouts visually and copy the generated CSS.
Try it yourself
Flexbox Generator
Raw Data Downloads
All datasets from this report are available for download under a Creative Commons CC BY 4.0 license.
