All jobs / Frontend / web developer
CSS interview questions
CSS questions a Frontend / web developer can be asked, from first job to senior. Open one to see the strongest answer and why it works.
You need to hide a panel but keep its space in the layout. What do you use, and why not display: none?
The strongest answer: visibility: hidden keeps the box; display: none removes it from layout and the accessibility tree
Why it works: visibility: hidden (or a sized inert region) is the direct answer; display: none is a different job.
- Pick the hide that matches layout and AT.
- display: none — gone from layout and usually from AT.
- visibility: hidden — space remains, not shown.
- If you use opacity, also remove it from focus (inert / aria-hidden + tabindex).
A 200px-wide card with 20px padding and a 2px border overflows its parent. How do you explain and fix it?
The strongest answer: Default content-box adds padding and border outside the width — set box-sizing: border-box, or account for the extra pixels
Why it works: You are being scored on whether you can name content-box vs border-box and pick the fix that keeps the layout honest.
- Name the box model before changing numbers.
- content-box: width + padding + border.
- border-box: padding and border sit inside the width.
- Set box-sizing once, then size the box you mean.
How do you write breakpoints so a layout grows rather than fights itself?
The strongest answer: Mobile-first min-width queries that add columns as space appears — avoid overlapping min and max queries that fight
Why it works: min-width layers are easier to reason about: the base is the small screen, enhancements add up.
- Let the layout grow with min-width.
- Write the small-screen CSS as the default.
- Add columns at min-width breakpoints.
- Don't mix conflicting max-width overrides without a reason.
When do you pick Flexbox versus Grid for a layout?
The strongest answer: Flex for one-dimensional alignment — a nav, a cluster of chips; Grid when rows and columns must line up together
Why it works: The useful answer is the axis: one line of alignment vs a two-dimensional template.
- Choose the layout tool for the axis you need.
- Flex: one dimension, distribution, wrapping.
- Grid: two dimensions, shared tracks.
- Position absolute is a last resort, not a page system.
A card looks fine at 1280px and overflows at 360px. How do you approach it?
The strongest answer: Build mobile-first with fluid flex/grid (minmax, clamp), then test the widths you support — don't assume one phone width
Why it works: Overflow is a layout problem: fluid tracks and real widths, not a single magic breakpoint.
- Fix overflow with fluid layout.
- Start from the narrow width.
- Use flex/grid wrap, minmax, and clamp.
- Check real widths, not one device preset.
A utility class loses to a nested selector. How do you reason about it?
The strongest answer: Read specificity, source order, and layers (@layer) — fix the source; don't sprinkle !important
Why it works: Cascade literacy is the answer: who won and why, then a smaller selector or a layer.
- Explain who won the cascade.
- Check specificity, order, and @layer.
- Lower the winner or raise the utility honestly.
- Reserve !important for utilities or third-party overrides, not features.
Three apps disagree on 'primary' blue. How do you fix it as a system?
The strongest answer: One token source — Style Dictionary or CSS variables — consumed by web and native; no raw hex in features
Why it works: A token pipeline is how brands stay one product. Features consume names, not paint.
- Tokens are the contract.
- Author color once.
- Emit CSS variables and native tokens.
- Ban hex in feature code.
A one-off marketing module cannot use the Button component. How does a design system allow that without chaos?
The strongest answer: Document a time-boxed escape — composition, a variant, or a local override — and don't fork the system
Why it works: Systems that cannot bend will be forked. Escapes are explicit, reviewed, and temporary or promoted.
- Plan the exception.
- Prefer composition or a new variant.
- Record the escape and an expiry.
- Never fork via copy or node_modules.
Runtime CSS-in-JS is showing up in INP on low-end phones. What do you consider?
The strongest answer: Extract critical CSS and prefer static or zero-runtime styles — CSS modules, vanilla-extract — on the hot path
Why it works: Runtime style insertion is main-thread work. Static extraction is the usual 2026 move for busy UIs.
- Styles can be INP.
- Find the runtime insertion in a trace.
- Move hot UI to static CSS.
- Don't generate a sheet per row.
A team wants a new Button variant that breaks the token model. How do you govern it?
The strongest answer: RFC plus design and a11y review — add a variant or compose; reject one-off color props that explode the matrix
Why it works: Governance is a path, not a door slam. Variants are cheap; open-ended paint props are not.
- Govern through RFCs, not vibes.
- Ask what token or composition is missing.
- Add a variant when it is shared.
- Refuse unbounded color props.
Hebrew and Arabic layout should mirror, but CSS uses margin-left everywhere. What do you do at scale?
The strongest answer: Switch to logical properties (margin-inline-start), set dir on the document, and treat RTL as a first-class test surface
Why it works: Logical properties and a document dir are how one stylesheet serves LTR and RTL — on web and in native yoga/flex.
- One stylesheet, logical sides.
- dir on the root from locale.
- margin-inline / inset-inline, not left/right.
- Test RTL in the same pipeline as LTR.
Global CSS collisions are blocking a move to CSS modules (or a layered system). How do you sequence it?
The strongest answer: New code on the new path, isolate globals with @layer, migrate by route, delete the global last
Why it works: Strangler migrations beat rewrites. Layers let old and new coexist without an !important war.
- Strangle the global CSS.
- New routes use modules/layers.
- Contain leftovers with @layer.
- Delete the global sheet last.
One codebase, four brands — each with color, type, and logo. How do you theme without forks?
The strongest answer: A token contract plus runtime or build-time brand packages; components consume tokens only
Why it works: Brands are data. Components never name a brand; they name a token. Same idea on native theme providers.
- Theme is a package, not a fork.
- Define the token contract.
- Swap the brand pack at boot or build.
- No brand conditionals in components.
A brand needs dark mode and high-contrast on top of four brands. How do you model it?
The strongest answer: Orthogonal axes — brand × appearance — via tokens; don't multiply component variants
Why it works: Brand and appearance are independent token layers. Components stay one set.
- Multiply tokens, not components.
- Brand pack × appearance pack.
- One component consumes both.
- No invert-filter themes.