CSS Interview Questions
Commonly asked CSS interview questions with clear, practical answers.
A curated set of CSS interview questions covering the topics that come up constantly in front-end interviews — specificity, layout models, and units.
The cascade & specificity
Q: How does CSS decide which rule wins when two selectors target the same element?
It's resolved in order: first by importance (!important beats normal rules), then by specificity (ID selectors beat class selectors, which beat element selectors), and finally, if specificity ties exactly, by source order — the rule declared later in the stylesheet wins. Inline style attributes outrank any selector-based rule except !important.
Q: What's the specificity of #nav .item:hover versus .nav-item.active?
#nav .item:hover has one ID, one class, and one pseudo-class → specificity (1, 2, 0). .nav-item.active has two classes → specificity (0, 2, 0). The first wins because an ID contributes more weight than any number of classes.
Box model & sizing
Q: What does box-sizing: border-box actually change?
By default (content-box), width/height size only the content area, so padding and border are added on top, making the element's rendered size larger than the declared width. border-box makes width/height include padding and border, so the declared size is the actual rendered size — which is far more predictable and is why most projects apply it globally via a reset.
Q: What's the difference between margin and padding?
padding is space inside the border, between the border and the content — it's part of the element's background and clickable area. margin is space outside the border, separating the element from its neighbors, and is always transparent. Adjacent vertical margins between block elements can also collapse into a single margin, which padding never does.
Layout models
Q: When would you use flexbox versus CSS Grid? Flexbox is one-dimensional — ideal for aligning items along a single row or column, like a navbar or a button group. Grid is two-dimensional — ideal when you need to control rows and columns simultaneously, like a full page layout or a dashboard. Many real interfaces use both together: grid for the page skeleton, flexbox for aligning content within an individual grid cell.
Q: What are the four main values of the position property, and how do they differ?
static (default, normal flow, offsets ignored), relative (stays in flow but can be visually offset from its normal position, and creates a positioning anchor for absolute descendants), absolute (removed from flow, positioned relative to the nearest non-static ancestor), and fixed (removed from flow, positioned relative to the viewport and unaffected by scrolling). sticky is a fifth, newer value that behaves like relative until a scroll threshold, then like fixed.
Units
Q: What's the difference between em and rem?
em is relative to the current element's own font-size (or its parent's, for non-font properties), which means it compounds when nested — a 1.2em inside another 1.2em produces a larger multiplied result. rem is always relative to the root (<html>) element's font-size, so it stays predictable no matter how deeply an element is nested. rem is generally the safer default for consistent sizing.
Custom properties, animation & modern CSS
Q: How is a CSS custom property (--name) fundamentally different from a Sass variable ($name)?
A Sass variable is a compile-time text substitution — once compiled, it no longer exists as a concept in the output CSS at all. A custom property is a genuine runtime value the browser tracks: it can be read and changed by JavaScript, it participates in the cascade and inherits down the DOM tree like any other property, and it can be redefined per-selector (or under a media query) to change what a shared component looks like in different contexts, all without a rebuild step.
Q: What's the difference between a CSS transition and a @keyframes animation, and when would you use each?
A transition needs a triggering state change (:hover, a class toggle, a JS style update) and only interpolates between two values — a start and an end. A @keyframes animation can define any number of intermediate steps via percentages, can run automatically without any trigger, and can loop indefinitely with animation-iteration-count: infinite. Use a transition for simple hover/focus feedback or a two-state toggle, and an animation for anything that loops, plays automatically, or needs more than two distinct steps, like a loading spinner.
Q: What does :has() let you do that wasn't previously possible in plain CSS?
It's the first native CSS selector that can match a parent based on what it contains, rather than only being able to describe relationships downward (descendants) or sideways (siblings). Before :has(), styling a container differently based on its children's state — like a form field wrapper reacting to its own <input> being :invalid — required JavaScript to detect the condition and toggle a class; :has() expresses the same logic in one declarative CSS rule.