Curated questions covering flexbox, grid, specificity, box model, animations, responsive design, CSS variables, and modern CSS features.
The CSS Box Model describes every element as a rectangular box with four areas: content (innermost), padding (space between content and border), border, and margin (outermost space between elements). Total width = content + padding + border + margin.
content-box (default) — width/height applies to content only; padding and border are added on top. border-box — width/height includes content, padding, and border. border-box makes layout calculations much easier and is the modern standard.
* { box-sizing: border-box; } /* recommended global reset */
a:hover { color: blue; }
p::first-line { font-weight: bold; }
z-index controls the stacking order of positioned elements (position other than static). Higher z-index appears on top. z-index only works on positioned elements. Elements in the same stacking context are compared; nested stacking contexts are treated as a unit.
CSS custom properties (--variable-name) store reusable values. They cascade and can be overridden in nested scopes. Accessed with var().
:root {
--primary: #38bdf8;
--spacing: 16px;
}
.btn {
background: var(--primary);
padding: var(--spacing);
}
display: none removes the element from the document flow — it takes up no space and is not accessible to screen readers. visibility: hidden hides the element visually but it still occupies its space in the layout and remains in the accessibility tree.
Media queries apply styles based on device characteristics like screen width, height, orientation, or resolution. They are the foundation of responsive design.
@media (max-width: 768px) {
.container { flex-direction: column; }
}
@media (prefers-color-scheme: dark) {
body { background: #0f172a; }
}
The cascade determines which CSS rule applies when multiple rules target the same element. Priority order: !important > inline styles > specificity > source order. The browser also applies user-agent (browser default) styles at the lowest priority.
CSS Grid creates a two-dimensional layout system with explicit rows and columns.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 16px;
}
.item { grid-column: 1 / 3; /* span 2 columns */ }
/* Transition */
.btn { transition: background 0.3s ease; }
.btn:hover { background: blue; }
/* Animation */
@keyframes spin { to { transform: rotate(360deg); } }
.loader { animation: spin 1s linear infinite; }
:root selects the highest-level parent element (the <html> element). It has higher specificity than the html selector. Commonly used to define CSS custom properties (variables) that are globally accessible.
object-fit controls how an <img> or <video> fills its container. Values: fill (default, stretches), contain (fits inside, letterbox), cover (fills, crops), none (original size), scale-down.
img {
width: 300px;
height: 200px;
object-fit: cover;
}
Padding is the space between the content and the border (inside the element). Margin is the space outside the border (between elements). Margins can collapse (adjacent vertical margins merge into the larger one); padding never collapses.
clamp(min, preferred, max) sets a value that scales between a minimum and maximum. Commonly used for fluid typography that responds to viewport size without media queries.
h1 { font-size: clamp(1.2rem, 4vw, 2.5rem); }
:nth-child(n) selects the nth child of its parent regardless of element type. :nth-of-type(n) selects the nth sibling of the same element type. They differ when mixed element types are present as siblings.
will-change hints to the browser that an element will be animated, allowing it to optimize rendering in advance (e.g., promote to a GPU compositing layer). Use sparingly — overuse wastes memory and can degrade performance.
.animated { will-change: transform, opacity; }
The contain property tells the browser that an element and its contents are independent from the rest of the document tree. This allows the browser to optimize rendering by limiting layout, paint, and style recalculations to the contained element.
.card { contain: layout paint; }
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
}
/* opacity affects everything including children */
.overlay { opacity: 0.5; }
/* rgba affects only the background */
.overlay { background: rgba(0, 0, 0, 0.5); }
div > p { color: red; } /* direct children only */
h2 + p { margin-top: 0; } /* first p after h2 */
CSS Grid auto-placement automatically places items into grid cells when no explicit placement is defined. Controlled by grid-auto-flow (row, column, dense). grid-auto-rows and grid-auto-columns define the size of implicitly created tracks.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px;
grid-auto-flow: dense;
}
.item { flex: 1 1 200px; } /* grow, shrink, basis */
/* Instead of h1 a, h2 a, h3 a */
:is(h1, h2, h3) a { color: blue; }
/* Zero specificity reset */
:where(h1, h2, h3) { margin: 0; }
transform (translate, scale, rotate) is GPU-accelerated and does not trigger layout reflow — it is the preferred way to animate movement. Changing position (top, left) triggers layout recalculation on every frame, which is much more expensive.
/* Preferred — GPU accelerated */
.box { transition: transform 0.3s; }
.box:hover { transform: translateX(20px); }
/* Avoid for animation */
.box:hover { left: 20px; }
Subgrid allows a grid item to participate in the parent grid's tl-row or column tracks. Without subgrid, a nested grid creates its own independent tracks. With subgrid, nested items align to the parent grid lines.
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.child {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid; /* inherits parent columns */
}
:focus applies styles whenever an element receives focus (mouse click or keyboard). :focus-visible applies styles only when the element is focused via keyboard navigation. This allows you to show focus rings for keyboard users without showing them on mouse clicks.
button:focus-visible {
outline: 2px solid #38bdf8;
outline-offset: 2px;
}
Logical properties use writing-mode-relative directions (inline/block) instead of physical directions (left/right/top/bottom). This makes layouts work correctly for RTL languages and vertical writing modes.
/* Physical */
.box { margin-left: 16px; padding-top: 8px; }
/* Logical equivalents */
.box { margin-inline-start: 16px; padding-block-start: 8px; }
aspect-ratio sets a preferred aspect ratio for an element. The browser maintains this ratio as the element resizes. Replaces the old padding-top hack for responsive embeds.
.video-wrapper {
aspect-ratio: 16 / 9;
width: 100%;
}
.avatar {
aspect-ratio: 1; /* square */
width: 80px;
}
fr (fractional unit) distributes available space after fixed-size tracks and gaps are accounted for. Percentage is calculated from the tl-container width and does not account for gaps. fr is more flexible and avoids overflow caused by gaps.
/* fr accounts for gap automatically */
.grid { grid-template-columns: repeat(3, 1fr); gap: 16px; }
/* % causes overflow with gap */
.grid { grid-template-columns: repeat(3, 33.33%); gap: 16px; }
html { scroll-behavior: smooth; }
.carousel {
scroll-snap-type: x mandatory;
overflow-x: scroll;
}
.slide { scroll-snap-align: start; }
gap (formerly grid-gap) sets the spacing between rows and columns in Grid and Flexbox layouts. It is shorthand for row-gap and column-gap. Unlike margins, gap only applies between items, not on the outer edges.
.flex { display: flex; gap: 16px; }
.grid { display: grid; gap: 24px 16px; /* row-gap column-gap */ }
@layer (Cascade Layers) allows you to organize CSS into named layers with explicit priority order. Styles in later-declared layers win over earlier ones regardless of specificity. Useful for managing third-party CSS and design systems.
@layer reset, base, components, utilities;
@layer base {
h1 { font-size: 2rem; }
}
@layer utilities {
.text-lg { font-size: 1.25rem; } /* wins over base */
}
.grid {
display: grid;
place-items: center; /* center items in cells */
place-content: center; /* center grid in tl-container */
}
CSS counters allow automatic numbering of elements using counter-reset, counter-increment, and counter() or counters() functions. Useful for custom ordered lists, section numbering, and tl-table of contents.
ol {
counter-reset: item;
list-style: none;
}
li::before {
counter-increment: item;
content: counter(item) ". ";
font-weight: bold;
}
:has() is a relational pseudo-class that selects a parent based on its children — the first true "parent selector" in CSS. It can also select elements based on following siblings.
/* tl-card with an image gets different padding */
.card:has(img) { padding: 0; }
/* Label before a required input */
label:has(+ input:required)::after { content: " *"; color: red; }
.grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
h1 { font-size: clamp(1.5rem, 5vw, 3rem); }
A stacking context is a three-dimensional conceptual model where elements are stacked along the z-axis. A new stacking context is created by: position + z-index, opacity < 1, transform, filter, will-change, isolation: isolate. Elements inside a stacking context are painted together and z-index only compares within the same context.
.modal-wrapper {
isolation: isolate; /* creates new stacking context */
}
/* auto-fit: items stretch to fill */
.grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
/* auto-fill: empty columns remain */
.grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
color-scheme tells the browser which color schemes an element supports. Setting it to light dark allows the browser to automatically apply appropriate system UI colors (scrollbars, form controls, backgrounds) for the user's preferred color scheme.
:root { color-scheme: light dark; }
/* Or per-element */
.dark-section { color-scheme: dark; }
content-visibility: auto tells the browser to skip rendering of off-screen elements until they are near the viewport. This can dramatically improve initial page load performance for long pages by reducing the rendering work.
.article-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px; /* estimated height to prevent layout shift */
}
Both can center content, but Grid is simpler for two-dimensional centering.
/* Flexbox centering */
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
/* Grid centering (simpler) */
.grid-center {
display: grid;
place-items: center;
}
Explore 500+ free tutorials across 20+ languages and frameworks.