CSS architecture is the dimension senior frontend interviewers test for that generalist SWE preparation completely misses. The questions are not about whether you can write CSS — the question is whether your CSS scales. Whether you can design a system that thousands of pages share. Whether you can avoid specificity wars, dead styles, and inconsistent design that plagues most large frontend codebases.
This piece covers what senior interviewers test on CSS architecture, the dominant patterns, and how to articulate tradeoffs.
The four CSS architectural approaches
Most companies in 2026 use one of four approaches:
1. BEM (Block Element Modifier)
Naming convention: .block, .block__element, .block--modifier. Pros: clear ownership, low specificity, no JavaScript dependency. Cons: verbose class names, manual discipline required, can produce class-name explosions.
BEM remains common in larger enterprise codebases and in teams that prefer convention-driven CSS over tooling-driven approaches.
2. CSS-in-JS
JavaScript libraries (styled-components, emotion, vanilla-extract) that generate CSS at runtime or build time. Pros: scoped styles by default, theme integration, dynamic styles. Cons: bundle size cost, runtime overhead (for runtime libraries), some accessibility complications.
CSS-in-JS dominated 2018-2022. By 2026, it has receded somewhat as Tailwind has gained ground. Still common in React-heavy codebases that need dynamic styling.
3. Tailwind CSS (utility-first)
Atomic utility classes (flex, p-4, text-blue-500) composed in markup. Pros: no naming required, good consistency, small final CSS bundle (purged), rapid development. Cons: HTML can get verbose, learning curve, some patterns don’t fit utility-first cleanly.
By 2026, Tailwind is the most common new-project default. Vercel, Linear, Notion, many modern startups standardized on it.
4. CSS Modules
CSS files that get scoped class names automatically. Pros: regular CSS with automatic scoping, no runtime overhead, easy to learn. Cons: less expressive than CSS-in-JS for dynamic styling, less fast development than Tailwind for some workflows.
Common in Next.js projects that want CSS-in-JS-like scoping without the runtime cost.
What senior interviewers test
1. Choosing the right architecture
The interviewer presents a scenario: “You’re starting a new design-system-heavy SaaS product. How do you architect the CSS?” Strong candidates articulate the tradeoffs of multiple approaches and pick one with reasoning. Weak candidates say “Tailwind because everyone uses it” without engaging with the tradeoff.
2. Design system architecture
How do you build a component library that 50 product pages share? Specific topics:
- Design tokens. Color, spacing, typography, radius, shadow values defined as named variables (CSS custom properties or build-time tokens).
- Component variants. Buttons have primary, secondary, tertiary; sizes small, medium, large; states default, hover, active, disabled.
- Theming. Light/dark mode, brand variations, customer-specific theming (for B2B products).
- Versioning. Breaking changes to design tokens or components — how do you migrate?
3. Layout patterns
Modern CSS layout uses flexbox and grid. Senior candidates know:
- When to use flex vs grid (flex for one-dimensional, grid for two-dimensional).
- Container queries (CSS Container Queries Level 1) for component-level responsive design.
- Logical properties (inline-start, block-end) for internationalization.
- Aspect-ratio for reserving space.
- Subgrid for nested grid layouts.
4. Responsive design strategies
Approaches:
- Mobile-first media queries. Start with mobile styles; add larger breakpoints. Standard.
- Container queries. Component responds to its container’s size, not the viewport. Newer.
- Fluid type and spacing. Using clamp() for values that scale with viewport. Reduces breakpoint count.
- Intrinsic web design. Letting the layout adapt naturally without explicit breakpoints when possible.
5. CSS performance
How CSS affects rendering performance:
- CSS is render-blocking. Smaller CSS = faster first paint.
- Long selectors cost more to evaluate. Avoid deeply nested selectors.
- Will-change and transforms create compositor layers, which speed up animations but cost memory.
- Layout thrashing (alternating reads and writes to layout properties in JavaScript) is a common performance bug.
Common interview questions
“Build a responsive card grid that wraps and centers items”
Modern answer: display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem;. The grid-template-columns line creates as many 200px-min columns as fit, with each cell flexing to fill available space.
“How would you architect a design system?”
Strong answer: design tokens (colors, spacing, typography) → primitives (buttons, inputs, links) → composed components (cards, forms, modals) → templates (layouts, page patterns). Each layer depends only on the layer below. Document with Storybook or similar.
“What’s the difference between em and rem?”
em is relative to the parent’s font-size; rem is relative to the root (html element). rem is generally preferred for predictability. em is useful for component-internal scaling (a button’s padding scaling with its font-size).
“Why is CSS specificity a problem at scale?”
Strong answer: in a large codebase, specificity wars cause cascading bugs. Style A is overridden by style B with higher specificity; later, style C tries to override A but is silently overridden by B. Architecture conventions (BEM low specificity, CSS Modules’ scoping, Tailwind utility-first) all attempt to solve this.
Modern CSS features senior candidates know
- Container queries: components that respond to their container, not the viewport.
- :has() selector: parent selectors based on children. Powerful but use judiciously.
- CSS nesting: Sass-like nesting now native in CSS.
- Cascade layers: @layer for explicit specificity ordering across stylesheets.
- Color functions: oklch(), color-mix() for modern color systems.
- View transitions: View Transitions API for animated page transitions.
What scores well
- Articulating tradeoffs of CSS architectures with reasoning.
- Knowing the modern CSS layout primitives (grid, flex, container queries) cold.
- Understanding design system layering (tokens → primitives → components).
- Awareness of performance considerations (specificity, render-blocking, layout thrashing).
What scores poorly
- “Use Tailwind because it’s modern” without articulating tradeoffs.
- Memorized property lists without understanding when to apply.
- Treating CSS as decoration rather than architecture.
- Recommending CSS-in-JS for everything despite the runtime cost.
- Not knowing CSS Grid in 2026.
How to prepare
- Build a small design system from scratch. Tokens → primitives → composed components.
- Read Andy Bell’s “Every Layout” and “Cube CSS” for modern architecture thinking.
- Try each of the four major approaches on a project to internalize their tradeoffs.
- Read the actual CSS specs for Grid and Container Queries — depth matters at senior+.
- Audit the CSS of a site you use daily; identify what’s well-architected and what’s not.
Frequently Asked Questions
Is Tailwind universally adopted in 2026?
No, but it’s the most common new-project default. Established codebases use a mix of approaches. Senior candidates should be conversant with multiple.
Is CSS-in-JS dead?
Not dead, but receded from peak adoption. Still common in React codebases. Newer libraries like vanilla-extract do CSS-in-JS at build time, avoiding runtime overhead.
Should I learn CSS Grid before flexbox?
Both. They serve different purposes. Senior candidates fluent in both pick the right one for the job.
How much CSS do I need to know for a generalist SWE interview?
Less than for a frontend specialist role, but basic competence is expected. Layout fundamentals (flex, grid), responsive design, common patterns.
Are design tokens always required?
For any design system used by 5+ pages, yes. For one-off projects, you can hardcode values. The scaling threshold is when you start changing values in many places.