Module 12: Interview Questions
Conceptual Questions: Fundamentals, Cascade and Rendering
Fifteen questions interviewers actually ask about the box model, specificity, display, stacking, rendering cost and variables, each with the answer a senior engineer would give.
Interviewers are rarely checking whether you memorized a definition. They want to see whether you know why something behaves the way it does, and whether you can reason about a case you have not seen. Each answer below gives the short version first, then the explanation that shows depth.
Q1. What is the box model, and what does box-sizing change?#
Every element is a rectangle made of content, padding, border and margin, from the inside out. By default (content-box), width and height set the content area only, so padding and border make the element larger than the number you wrote. With border-box, width and height include padding and border, and the content area shrinks to compensate. Margin is never included in either.
Most projects set box-sizing: border-box on everything, because it makes percentage layouts add up: two 50% columns with padding still fit on one line.
A good follow-up detail to mention: with border-box, if padding plus border exceed the declared width, the content area becomes zero and the box is still as large as its padding plus border.
Q2. How does the browser decide which rule wins?#
It sorts the matching declarations with the cascade, in this order:
- Origin and importance (
!importantand where the style came from). - Inline styles.
- Cascade layers.
- Specificity.
- Order of appearance, where the later declaration wins.
Specificity is a tuple of (IDs, classes and attributes and pseudo-classes, elements and pseudo-elements). Compare left to right. It is not a decimal number: ten classes do not beat one ID.
The senior answer adds how you avoid fights: single-class selectors, no IDs for styling, :where() for easy-to-override defaults, @layer to order whole groups, and !important only for utilities.
Q3. What is inheritance? Which properties inherit?#
Some properties pass their computed value from parent to child when no rule targets the child. Typography and color inherit: color, font-*, line-height, text-align, visibility, cursor, list styles. Box-related properties do not: margin, padding, border, background, width, display, position. It would be absurd if a border on a list gave a border to every item.
Inherited values have the lowest priority. Any rule that targets the element directly beats them, which is why links do not take the parent's text color unless you set color: inherit.
Keywords worth knowing: inherit, initial, unset (inherit if the property inherits, else initial) and revert.
Q4. What is the difference between display: none, visibility: hidden and opacity: 0?#
display: none | visibility: hidden | opacity: 0 | |
|---|---|---|---|
| Takes up space | no | yes | yes |
| Receives clicks and focus | no | no | yes |
| In the accessibility tree | no | no | yes |
| Can be transitioned smoothly | no (not by default) | limited | yes |
opacity: 0 is a common trap: the element is invisible but still clickable and announced to screen readers. If it should be unreachable, add visibility: hidden or pointer-events: none.
Q5. Compare px, em, rem, %, vw and ch.#
px is a fixed CSS pixel. rem is relative to the root font size, so it never compounds and follows the user's browser setting.
em is relative to the element's own font size (or the parent's, when used on font-size), so nested em values compound.
% is relative to something that depends on the property: the containing block's width for width, the parent's font size for font-size, and the containing block's width even for vertical padding.
vw is a percentage of the viewport width and includes the scrollbar. ch is the width of the zero glyph, handy for line length.
The practical rule: rem for font sizes and spacing, em for spacing that should scale with a component's text, px for borders and hairlines, % or fr for layout, ch for measure.
Q6. What is the difference between a pseudo-class and a pseudo-element?#
A pseudo-class (one colon) selects an existing element in a state or position: :hover, :focus-visible, :nth-child(2), :checked. A pseudo-element (two colons) selects a part of an element or creates a generated box: ::before, ::after, ::first-line, ::placeholder.
::before and ::after need the content property to exist. They are in the render tree, not the DOM, so JavaScript cannot query them and users cannot select their text.
Q7. What is margin collapse?#
When the vertical margins of two blocks touch, they merge into one margin equal to the larger. It happens between adjacent siblings, between a parent and its first or last child when nothing separates them (no padding, border or content), and for an empty block's own top and bottom margins. It never happens horizontally.
It does not happen for flex or grid items, or when the parent establishes a new formatting context. The cleanest fix for a child margin escaping its parent is display: flow-root on the parent.
Q8. What is a stacking context, and why does z-index: 9999 sometimes not work?#
A stacking context is an isolated layer group. Children are ordered against each other inside it, and the whole group is then ordered as a single unit within its parent context. z-index only compares elements that share a stacking context.
An element creates one if it is the root, is positioned with a z-index other than auto, is a flex or grid item with a z-index, has opacity below 1, or has transform, filter, clip-path or isolation: isolate, among others.
So a dropdown with a huge z-index inside a header with z-index: 1 cannot rise above a sibling with z-index: 10. The fix is to find the ancestor that creates the context, not to raise the number. Also note that z-index has no effect on a static element unless it is a flex or grid item.
Q9. What happens between receiving CSS and seeing pixels? Which properties are cheap to animate?#
The browser builds the DOM and CSSOM, combines them into a render tree with computed styles, runs layout to compute sizes and positions, paints each layer, and composites the layers on screen.
Changing a layout property (width, margin, font-size) forces layout, then paint, then composite. Changing a paint property (color, box-shadow) skips layout. Changing transform or opacity can often skip both and be handled by the compositor on the GPU. That is why animations should move things with transform and fade with opacity.
CSS is also render-blocking: the browser will not paint until the stylesheets in the head have loaded, to avoid showing unstyled content.
Q10. How do CSS custom properties differ from Sass variables?#
A Sass variable is replaced at compile time and does not exist in the browser. A custom property is a real property that exists at runtime: it participates in the cascade, inherits down the tree, can be overridden for a subtree, can be changed from media queries and JavaScript, and can be read with getComputedStyle.
That is why themes use custom properties and build-time constants like breakpoint values (which cannot be used inside a media query condition) still sometimes use Sass.
One gotcha worth mentioning: if a variable holds a value that is invalid for the property using it, the declaration becomes "invalid at computed-value time" and falls back to the property's unset value, not to an earlier declaration.
Q11. How does the browser evaluate a selector like .nav ul li a?#
Right to left. It takes each a as the key selector, then walks up to verify an li, a ul, and a .nav ancestor. Rightmost selectors that are very general (*, div, a) match many elements and force more ancestor checks.
In practice, selector performance is rarely the bottleneck in modern browsers. The real reasons to keep selectors short are specificity and maintainability: long chains are brittle, and they are expensive to override.
Q12. What are the differences between block, inline and inline-block?#
A block box starts on a new line and fills the available width, and accepts width, height and vertical margins. An inline box flows within a line of text, ignores width and height, and its vertical margins and padding do not push surrounding lines. An inline-block flows like inline but behaves like a block inside, so it accepts sizes and vertical spacing.
Inline-block elements also render the whitespace between them in the HTML as a gap, which is one reason flexbox replaced them for layout.
Q13. What is a block formatting context?#
A region in which block boxes are laid out according to normal block rules, isolated from the outside. A BFC contains its floats (so the parent does not collapse), prevents margin collapse between the container and its children, and does not overlap with neighboring floats.
It is created by the root element, floats, absolutely positioned elements, inline-blocks, flex and grid items, elements with overflow other than visible, and display: flow-root. The last one exists specifically to create a BFC with no side effects.
Q14. What happens when the browser meets invalid CSS?#
It recovers in specific ways. An invalid declaration is dropped and the rest of the rule survives. An invalid selector in a selector list drops the whole rule, except inside forgiving selectors like :is(). An unknown at-rule is ignored.
The parser never stops, which makes CSS forward compatible. Writing an older declaration first and a newer one after it is therefore the oldest feature-detection technique in CSS.
Q15. When is !important acceptable?#
Rarely. It reverses the normal cascade order and can only be beaten by another !important with higher priority, so it escalates. It is acceptable for utility classes meant to always win (.hidden, .visually-hidden), for user-preference overrides such as reducing motion globally, and for overriding third-party styles you cannot change. In your own components, it signals that the selector structure needs fixing.
Practice#
- Pick five of the questions above and answer them out loud in under 90 seconds each, with no notes. Record yourself and listen for hesitation.
- For each answer you gave, add a concrete example you could draw on a whiteboard, such as the collapsing margins diagram or a stacking context tree.
- Write three follow-up questions an interviewer might ask for Q8 and Q9. Answer them.
- Build a small demo for one question you were weakest on, and keep it as a reference.