CSS Basics Interview Questions and Answers | Selectors, Cascade, Inheritance, Units, and Production Examples
Master CSS basics with real interview questions covering selectors, the cascade, specificity, inheritance, units, the display property, positioning, pseudo-classes, pseudo-elements, custom properties, and production best practices.
Introduction
CSS (Cascading Style Sheets) is the language that controls the visual presentation of HTML documents.
It is one of the three core web technologies alongside HTML and JavaScript, and it is tested in virtually every frontend engineering interview.
CSS questions evaluate whether a candidate can:
- Understand how browsers resolve conflicting styles through the cascade
- Select elements precisely using selectors and combinators
- Reason about specificity, inheritance, and default browser styles
- Use units correctly for responsive and accessible layouts
- Control layout with the
displayproperty and positioning - Apply modern CSS features like custom properties and logical properties
- Debug common visual bugs caused by misunderstood CSS rules
- Write maintainable, production-quality CSS
This article covers the most frequently asked CSS Basics interview questions with detailed explanations, code examples, and production insights.
Learning Objectives
After completing this article, you will understand:
- The purpose and role of CSS in web development
- How the cascade resolves conflicting style declarations
- CSS selector types and specificity calculation
- How inheritance works and which properties inherit by default
- CSS units — absolute, relative, and viewport-based
- The
displayproperty and its most important values - CSS positioning — static, relative, absolute, fixed, sticky
- Pseudo-classes and pseudo-elements
- CSS custom properties (variables)
- Common production patterns and interview mistakes
1. What Is CSS and What Does It Do?
Answer
CSS (Cascading Style Sheets) is a stylesheet language used to control the visual presentation of HTML elements in a browser.
It separates content from presentation.
HTML defines the structure and content:
<h1>Welcome</h1>
<p>This is a paragraph.</p>
CSS defines how those elements look:
h1 {
color: #1a1a2e;
font-size: 2rem;
margin-bottom: 1rem;
}
p {
color: #444;
line-height: 1.7;
}
CSS controls:
- Colors, fonts, and typography
- Layout — spacing, sizing, alignment
- Responsive behaviour across screen sizes
- Animations and transitions
- Print and accessibility styles
Production note:
In a large application, CSS is typically organized into design tokens, utility classes, or component-scoped styles to prevent conflicts and maintain consistency across a codebase.
2. What Is the CSS Cascade?
Answer
The cascade is the algorithm browsers use to decide which CSS declaration wins when multiple rules target the same element and the same property.
The cascade evaluates rules in this order of priority:
1. Origin and Importance
(browser default < author < author !important < user agent !important)
2. Specificity
(inline > ID > class/attribute/pseudo-class > element/pseudo-element)
3. Source Order
(later declarations win when specificity is equal)
Example:
/* Rule 1 — lower specificity */
p {
color: blue;
}
/* Rule 2 — higher specificity */
#intro p {
color: red;
}
<div id="intro">
<p>This text is red.</p> <!-- Rule 2 wins -->
</div>
<p>This text is blue.</p> <!-- Rule 1 wins -->
Production note:
Understanding the cascade prevents common bugs where styles are unexpectedly overridden. Avoid !important in production code except for utility overrides — it makes debugging significantly harder.
3. What Is CSS Specificity and How Is It Calculated?
Answer
Specificity is a weight assigned to a CSS selector that determines which declaration takes precedence when multiple rules target the same element.
Specificity is represented as a four-part value:
(inline, ID, class/attribute/pseudo-class, element/pseudo-element)
e.g. (0, 1, 2, 1)
| Selector type | Specificity value |
|---|---|
Inline style (style="") |
(1, 0, 0, 0) |
ID selector (#id) |
(0, 1, 0, 0) |
Class (.class), attribute ([attr]), pseudo-class (:hover) |
(0, 0, 1, 0) |
Element (div, p), pseudo-element (::before) |
(0, 0, 0, 1) |
Universal selector (*), combinators |
(0, 0, 0, 0) |
Example calculation:
/* Specificity: (0, 0, 0, 1) */
p { color: black; }
/* Specificity: (0, 0, 1, 0) */
.text { color: grey; }
/* Specificity: (0, 1, 0, 0) */
#main { color: blue; }
/* Specificity: (0, 1, 1, 1) */
#main p.text { color: green; } /* wins */
Production note:
Keep specificity as flat and low as possible. High-specificity selectors create overriding battles. Prefer class selectors over ID selectors for styling.
4. What Is Inheritance in CSS?
Answer
Inheritance is the mechanism by which some CSS properties are automatically passed from a parent element to its children when no explicit value is set on the child.
Properties that inherit by default:
color, font-family, font-size, font-weight, font-style,
line-height, letter-spacing, text-align, text-transform,
list-style, cursor, visibility
Properties that do NOT inherit by default:
margin, padding, border, background, width, height,
display, position, overflow, box-shadow, opacity
Example:
body {
font-family: 'Inter', sans-serif;
color: #333;
}
Every p, h1, span, li etc. inside body inherits font-family and color automatically.
Controlling inheritance explicitly:
.child {
color: inherit; /* force inherit from parent */
color: initial; /* reset to browser default */
color: unset; /* inherit if inheritable, else initial */
color: revert; /* reset to browser stylesheet value */
}
Production note:
Setting font-family, color, and line-height on body or :root propagates them throughout the document, reducing repetition.
5. What Are the Different Types of CSS Selectors?
Answer
CSS provides several selector types to target elements.
Element selector:
p { color: navy; }
Class selector:
.card { border-radius: 8px; }
ID selector:
#header { background: #fff; }
Attribute selector:
input[type="text"] { border: 1px solid #ccc; }
a[href^="https"] { color: green; } /* starts with */
a[href$=".pdf"] { color: red; } /* ends with */
a[href*="docs"] { color: blue; } /* contains */
Combinators:
/* Descendant — any level deep */
nav a { text-decoration: none; }
/* Child — direct children only */
ul > li { list-style: disc; }
/* Adjacent sibling — immediately after */
h1 + p { margin-top: 0; }
/* General sibling — all following siblings */
h1 ~ p { color: #555; }
Pseudo-class selector:
a:hover { color: blue; }
li:first-child { font-weight: bold; }
li:nth-child(2n) { background: #f5f5f5; } /* every even row */
input:focus { outline: 2px solid #3b82f6; }
input:disabled { opacity: 0.5; }
Pseudo-element selector:
p::first-line { font-variant: small-caps; }
p::first-letter { font-size: 2em; float: left; }
.card::before { content: ''; display: block; }
.card::after { content: '✓'; color: green; }
Grouping:
h1, h2, h3 { font-family: 'Roboto', sans-serif; }
Production note:
Prefer class selectors for styling components. Avoid over-qualifying selectors (e.g., div.card instead of just .card) — it increases specificity unnecessarily.
6. What Are CSS Units and When Should You Use Each?
Answer
CSS supports absolute, relative, and viewport-based units.
Absolute units:
| Unit | Description | Use case |
|---|---|---|
px |
1 logical pixel | Borders, shadows, fine-grained control |
pt |
1/72 inch | Print stylesheets |
cm, mm |
Physical dimensions | Print stylesheets |
Relative units:
| Unit | Relative to | Use case |
|---|---|---|
em |
Font size of the element itself | Component-local spacing, nested scaling |
rem |
Font size of the root element (html) |
Global spacing, typography scale |
% |
Parent element's value | Fluid widths, heights |
ch |
Width of the 0 character |
Input width sizing |
ex |
x-height of the current font | Rare typographic use |
Viewport units:
| Unit | Relative to | Use case |
|---|---|---|
vw |
1% of viewport width | Full-width layouts, hero sections |
vh |
1% of viewport height | Full-height layouts |
svh |
Small viewport height | Mobile-safe full-height (avoids address bar) |
dvh |
Dynamic viewport height | Responsive mobile layouts |
vmin |
Smaller of vw/vh | Responsive font scaling |
vmax |
Larger of vw/vh | Background coverage |
Example — responsive type scale:
:root {
font-size: 16px; /* 1rem = 16px */
}
h1 { font-size: 2.5rem; } /* 40px */
p { font-size: 1rem; } /* 16px */
.card { padding: 1.5rem; } /* 24px */
Production note:
Prefer rem for font sizes and global spacing. Use em for component-internal scaling (e.g., button padding that should scale with button font size). Avoid px for font sizes — it ignores user browser font preferences.
7. What Is the display Property and What Are Its Most Important Values?
Answer
The display property controls how an element participates in the document layout flow.
block:
div { display: block; }
- Takes full available width.
- Starts on a new line.
- Respects
width,height,margin,paddingon all sides. - Examples:
div,p,h1–h6,section,article.
inline:
span { display: inline; }
- Takes only as much width as its content.
- Does not start on a new line.
- Ignores
widthandheight. Verticalmarginandpaddingare ignored (or have limited effect). - Examples:
span,a,strong,em.
inline-block:
.badge { display: inline-block; }
- Flows inline like
inlinebut respectswidth,height,margin, andpaddinglikeblock. - Used for buttons, tags, icon+label combinations.
none:
.hidden { display: none; }
- Removes element from layout completely — not rendered, not accessible to screen readers.
- Compare with
visibility: hidden— which hides visually but keeps layout space.
flex:
.container { display: flex; }
- Creates a flex formatting context for its children.
- Enables powerful one-dimensional layout.
grid:
.layout { display: grid; }
- Creates a grid formatting context.
- Enables two-dimensional layout.
contents:
.wrapper { display: contents; }
- The wrapper element itself is removed from the box tree; its children behave as if they are direct children of the wrapper's parent.
- Useful for accessibility wrappers in Flexbox and Grid.
Production note:
Choosing the wrong display value is one of the most common CSS bugs. Always verify whether inline-block or flex is needed when display: inline behaves unexpectedly with dimensions.
8. What Is the CSS Box Model?
Answer
The box model describes the rectangular boxes that every HTML element generates.
Every box has four layers from inside out:
┌──────────────────────────────────────────┐
│ margin │
│ ┌────────────────────────────────────┐ │
│ │ border │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ padding │ │ │
│ │ │ ┌────────────────────────┐ │ │ │
│ │ │ │ content │ │ │ │
│ │ │ └────────────────────────┘ │ │ │
│ │ └──────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘
content-box (default):
box-sizing: content-box;
/* width = content width only */
/* total rendered width = width + padding + border */
border-box (recommended):
box-sizing: border-box;
/* width = content + padding + border combined */
/* total rendered width = width (as declared) */
Example:
/* content-box — confusing */
.card {
width: 300px;
padding: 20px;
border: 2px solid #ccc;
/* actual rendered width = 300 + 40 + 4 = 344px */
}
/* border-box — predictable */
.card {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #ccc;
/* actual rendered width = 300px exactly */
}
Production note:
Always set box-sizing: border-box globally. This is the universal reset used in every modern CSS framework and design system:
*,
*::before,
*::after {
box-sizing: border-box;
}
9. What Is CSS Positioning and How Does Each Value Work?
Answer
The position property controls how an element is placed in the document and how it interacts with other elements.
static (default):
.element { position: static; }
- Normal document flow.
top,right,bottom,lefthave no effect.z-indexhas no effect.
relative:
.element {
position: relative;
top: 10px;
left: 20px;
}
- Positioned relative to its own normal flow position.
- The space it would have occupied is preserved.
- Creates a containing block for absolutely positioned children.
absolute:
.tooltip {
position: absolute;
top: 0;
right: 0;
}
- Removed from normal document flow — no space reserved.
- Positioned relative to the nearest ancestor with
positionother thanstatic. - If no such ancestor exists, positioned relative to the viewport.
fixed:
.navbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
- Removed from normal flow.
- Positioned relative to the viewport — stays in place on scroll.
- Unaffected by scrolling.
sticky:
.table-header th {
position: sticky;
top: 0;
background: #fff;
}
- Acts as
relativeuntil the element reaches a defined scroll threshold. - Then behaves as
fixedwithin its containing block. - Stays visible while its parent is in view.
- Requires
top,bottom,left, orrightto activate.
Production note:
sticky is the modern solution for sticky table headers, section headings, and sidebar navigation. It requires the parent not to have overflow: hidden or overflow: auto, which breaks the sticky behaviour.
10. What Are Pseudo-Classes and How Do They Differ from Pseudo-Elements?
Answer
Pseudo-classes target elements based on their state or position in the DOM. They use a single colon :.
/* State-based */
a:hover { color: darkblue; }
a:visited { color: purple; }
a:active { color: red; }
input:focus { outline: 2px solid #3b82f6; }
input:disabled { opacity: 0.5; cursor: not-allowed; }
input:checked { accent-color: #3b82f6; }
input:valid { border-color: green; }
input:invalid { border-color: red; }
input:required { border-left: 3px solid orange; }
/* Position-based */
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(2) { background: #f0f0f0; }
li:nth-child(odd) { background: #fafafa; }
p:not(.intro) { font-size: 0.9rem; }
Pseudo-elements target a specific part of an element or insert generated content. They use double colons ::.
/* Typography */
p::first-line { font-variant: small-caps; }
p::first-letter { font-size: 3em; float: left; line-height: 1; }
/* Generated content */
.card::before {
content: '';
display: block;
height: 4px;
background: #3b82f6;
}
.required-label::after {
content: ' *';
color: red;
}
/* Text selection */
::selection {
background: #3b82f6;
color: white;
}
/* Placeholder */
input::placeholder {
color: #999;
font-style: italic;
}
Key difference:
| Pseudo-class | Pseudo-element | |
|---|---|---|
| Syntax | Single colon : |
Double colon :: |
| Targets | Element state or position | Part of element or generated content |
| Creates DOM node? | No | No (but renders content) |
| Examples | :hover, :focus, :nth-child |
::before, ::after, ::placeholder |
Production note:
::before and ::after require content: '' (even if empty) to render. They are positioned relative to their parent by default — set position: absolute on the pseudo-element and position: relative on the parent for precise placement.
11. What Are CSS Custom Properties (Variables)?
Answer
CSS custom properties (also called CSS variables) allow you to define reusable values in CSS and reference them throughout a stylesheet.
They are declared with a -- prefix and read with the var() function.
Declaration:
:root {
--color-primary: #3b82f6;
--color-secondary: #7c5cd8;
--color-text: #1f2328;
--color-muted: #57606a;
--color-bg: #ffffff;
--color-surface: #f7f8fa;
--color-border: #e5e7eb;
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 16px;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
}
Usage:
.button {
background-color: var(--color-primary);
color: var(--color-bg);
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-md);
font-family: var(--font-sans);
}
.card {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: var(--space-6);
}
Fallback values:
color: var(--color-accent, #3b82f6);
/* Uses #3b82f6 if --color-accent is not defined */
Dynamic theming with JavaScript:
// Light to dark theme switch
document.documentElement.style
.setProperty('--color-bg', '#0d1117');
document.documentElement.style
.setProperty('--color-text', '#e6edf3');
Scoped custom properties:
.card {
--card-padding: 1.5rem;
padding: var(--card-padding);
}
.card.compact {
--card-padding: 0.75rem;
/* padding automatically updates */
}
Production note:
Custom properties are the foundation of modern design tokens. Defining them on :root ensures global availability. Scoping them to a component enables per-component theming without class name collisions.
12. What Is the Difference Between visibility: hidden, display: none, and opacity: 0?
Answer
All three hide an element visually, but they behave very differently:
| Property | Visually hidden | Takes up layout space | Accessible to screen readers | Responds to events |
|---|---|---|---|---|
display: none |
Yes | No | No | No |
visibility: hidden |
Yes | Yes | No (usually) | No |
opacity: 0 |
Yes | Yes | Yes | Yes |
display: none:
.modal { display: none; } /* removed from layout entirely */
The element is completely removed from the layout. Adjacent elements reflow to fill its space. Screen readers cannot find it.
visibility: hidden:
.tooltip { visibility: hidden; } /* invisible but still occupies space */
The element is invisible but its space is preserved. Screen readers typically skip it. Useful when you do not want layout reflow.
opacity: 0:
.overlay { opacity: 0; } /* transparent, fully interactive */
The element is fully transparent but still occupies space, responds to pointer events, and is accessible to screen readers.
Combine with pointer-events: none to also remove interactivity:
.overlay {
opacity: 0;
pointer-events: none;
}
visibility and opacity with transitions:
.dropdown {
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
}
.dropdown.open {
opacity: 1;
visibility: visible;
}
Using both together allows a smooth fade-in transition while also removing screen reader access when hidden. Using display: none cannot be transitioned directly.
Production note:
For accessible modals and dropdowns, display: none is recommended when closed (removes from accessibility tree). For animations, transition from opacity: 0; visibility: hidden to opacity: 1; visibility: visible.
13. What Is the z-index Property and How Does the Stacking Context Work?
Answer
z-index controls the vertical stacking order of positioned elements along the Z axis (toward the viewer).
Basic rule:
.overlay {
position: fixed;
z-index: 100;
}
.modal {
position: fixed;
z-index: 200; /* renders above overlay */
}
z-index only works on elements with a position value other than static.
Stacking context:
A stacking context is an isolated Z-axis scope. An element creates a new stacking context when it has certain CSS properties applied.
Properties that create a new stacking context include:
position: relative/absolute/fixed/sticky + z-index other than auto
opacity < 1
transform (any value other than none)
filter (any value other than none)
will-change: transform / opacity
isolation: isolate
Within a stacking context, child elements can only stack relative to each other — they cannot escape their parent's stacking context.
Example of a common bug:
/* Parent creates a stacking context with opacity */
.card {
opacity: 0.99; /* creates new stacking context! */
position: relative;
}
/* Child z-index is now relative to .card, not the page */
.tooltip {
position: absolute;
z-index: 9999; /* only stacks within .card */
}
The tooltip appears behind a modal at z-index: 10 on the page because it is trapped inside .card's stacking context.
isolation: isolate — intentional stacking context:
.component {
isolation: isolate; /* creates stacking context without visual side effects */
}
Production note:
Z-index conflicts are one of the most common CSS debugging challenges. Keep z-index values in a documented scale (e.g., 10 = dropdowns, 100 = modals, 200 = toasts) and use isolation: isolate on self-contained components to prevent leakage.
14. What Is the Difference Between em and rem?
Answer
Both em and rem are relative font-size units. They differ in what they are relative to.
em — relative to the element's own font size:
.button {
font-size: 16px;
padding: 0.75em 1.5em;
/* padding = 12px 24px — scales with button font size */
}
.button.large {
font-size: 20px;
/* padding automatically becomes 15px 30px */
}
Nested em compounds:
html { font-size: 16px; }
.parent { font-size: 1.5em; } /* 24px */
.child { font-size: 1.5em; } /* 36px — 1.5 × 24px */
This compounding makes em hard to predict in nested structures.
rem — relative to the root (html) font size:
html { font-size: 16px; }
h1 { font-size: 2.5rem; } /* always 40px */
h2 { font-size: 2rem; } /* always 32px */
p { font-size: 1rem; } /* always 16px */
.small { font-size: 0.875rem; } /* always 14px */
rem values are predictable regardless of nesting depth.
When to use each:
| Use case | Recommended unit |
|---|---|
| Global font sizes and spacing | rem |
| Component-internal spacing that should scale with the component's font size | em |
| Button padding | em (scales with button size) |
| Layout spacing and margins | rem |
| Media query breakpoints | em or rem (avoids px-based zoom issues) |
Production note:
Set a base font-size on html and build all typography and spacing in rem. Use em only where intentional parent-relative scaling is desired. This respects user browser font preferences (users who set their browser to 20px base get proportionally larger type).
15. What Are CSS Resets and Normalizations? Why Are They Used?
Answer
Browsers apply their own default styles (the user agent stylesheet) to HTML elements — margins on body, bold on h1–h6, list styles, border on input, etc.
These defaults differ across browsers, causing inconsistent rendering.
CSS Reset (e.g., Eric Meyer's Reset):
A CSS reset removes all browser default styles, reducing everything to a baseline of zero.
/* Simplified reset example */
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
This gives full control but means every element must be styled from scratch.
CSS Normalize (normalize.css):
A normalize stylesheet preserves useful browser defaults while fixing cross-browser inconsistencies.
It does not strip everything — it makes browsers render HTML consistently.
/* normalize.css example excerpts */
html { line-height: 1.15; -webkit-text-size-adjust: 100%; }
body { margin: 0; }
h1 { font-size: 2em; margin: 0.67em 0; }
hr { box-sizing: content-box; height: 0; overflow: visible; }
Modern CSS baseline (recommended):
/* Global reset + sensible defaults */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
-webkit-text-size-adjust: 100%;
}
body {
font-family: var(--font-sans, system-ui, sans-serif);
line-height: 1.6;
color: var(--color-text, #1f2328);
background-color: var(--color-bg, #ffffff);
}
img,
video,
canvas {
max-width: 100%;
display: block;
}
input,
button,
textarea,
select {
font: inherit;
}
| Approach | Browser defaults | Cross-browser consistency |
|---|---|---|
| No reset | Preserved | Inconsistent |
| CSS Reset | Removed entirely | Consistent zero baseline |
| Normalize | Fixed selectively | Consistent useful defaults |
| Modern baseline | Selectively removed | Consistent + purposeful |
Production note:
Most modern CSS frameworks (Tailwind's Preflight, Chakra UI, Material UI) include their own baseline reset. When building from scratch, use a minimal modern reset with box-sizing: border-box, zero margins/padding, and font: inherit on form elements.
Common Interview Mistakes
❌ Confusing em and rem — em is relative to the element, rem to the root.
❌ Forgetting position: relative on the parent of an position: absolute child — the child positions to the viewport instead.
❌ Using display: none when an animated show/hide transition is needed — use opacity + visibility instead.
❌ Adding high z-index to fix stacking without understanding stacking contexts — the element may be trapped inside a parent context.
❌ Using !important to override specificity instead of restructuring the selector.
❌ Forgetting content: '' on ::before and ::after — the pseudo-element will not render.
❌ Using px for font sizes — it overrides user browser font size preferences and breaks accessibility.
❌ Using ID selectors (#id) for styling — they create unnecessarily high specificity that is difficult to override.
Summary
CSS Basics form the essential foundation of all frontend engineering.
The cascade, specificity, and inheritance determine which styles are applied and why.
Selectors provide precise targeting of elements by type, class, ID, attribute, state, and position.
Units determine whether your layout adapts to different screens, devices, and user preferences.
The display property is the entry point to understanding every layout model.
Positioning removes elements from normal flow and enables tooltips, modals, sticky headers, and overlays.
Custom properties (variables) enable consistent design tokens and dynamic theming across an entire application.
Understanding these fundamentals allows you to reason about CSS confidently, debug visual bugs systematically, and architect maintainable styles at production scale.
Key Takeaways
- The cascade resolves conflicts through origin, specificity, and source order — in that priority.
- Specificity is calculated as (inline, ID, class, element) — lower specificity keeps the codebase maintainable.
- Inherited properties propagate through the DOM automatically — use this to reduce repetition.
- Prefer
remfor global typography and spacing; useemfor component-local relative scaling. - Always apply
box-sizing: border-boxglobally — it makes width calculations predictable. position: absoluteis relative to the nearest non-static ancestor — always setposition: relativeon the intended parent.stickypositioning requirestop/bottomto activate and breaks if any ancestor hasoverflow: hidden.- CSS custom properties on
:rootform the design token layer — use them for colors, spacing, and typography. display: noneremoves from layout and accessibility;opacity: 0hides visually but keeps accessibility and events.- High
z-indexvalues fail silently when trapped inside a stacking context — useisolation: isolateon components.