Menu
CoddyTech

CSS Interview Questions and Answers

CSS questions from specificity, the box model and centering to Flexbox, Grid, responsive design and rendering. Most answers have a live example; keep the CSS cheat sheet open for syntax.

76 questionsBy Kevin Spektor, Co-founder & CTO

CSS interview questions for freshers

The basics of every junior round: how styles reach an element, display, units and centering.

What is CSS and why do we use it?

Fresherbasics

CSS (Cascading Style Sheets) controls how HTML looks: colors, fonts, spacing, layout and animation. HTML says what the content is and CSS how it is presented, so one cached stylesheet can restyle a whole site and give the same markup a different layout on a phone or on paper.

What are the three ways to add CSS to a page, and which one wins?

Fresherbasics

Inline (a style attribute), internal (a <style> element) and external (a file loaded with <link rel="stylesheet">).

<link rel="stylesheet" href="styles.css">      <!-- external -->
<style> p { color: navy; } </style>            <!-- internal -->
<p style="color: crimson;">Hello</p>           <!-- inline -->

Inline beats any selector; a stylesheet rule beats inline only with !important. Internal and external have no fixed rank: with equal specificity, the one later in the page wins.

What does "cascading" mean in CSS?

Freshercascade

The cascade picks the winner when several rules set the same property on one element. It compares, in order: origin and importance (author styles beat browser defaults, !important beats normal declarations), inline styles, cascade layers, specificity, and order of appearance, where the last rule wins. Inheritance applies only when no rule sets the property at all.

What is the difference between a class and an id selector?

Fresherselectors

An id must be unique in the page and scores (1, 0, 0); a class can go on any number of elements, one element can carry several, and it scores (0, 1, 0). Style with classes: a #header a rule can only be overridden by another id or !important. Keep ids for fragment links, label for and scripts.

Which CSS properties are inherited?

Freshercascade

Text properties inherit (color, font-family, font-size, line-height, text-align); box properties do not (margin, padding, border, width, background). Force either way with inherit, initial, unset or revert. The trap is form controls: button, input and select get their own font from the browser until you set font: inherit.

HTML
<style>
  .card { color: darkgreen; font-family: Georgia, serif; border: 2px solid darkgreen; padding: 8px; }
  .fixed { font: inherit; color: inherit; }
</style>
<div class="card">
  <p>This paragraph inherits the color and the font, but not the border.</p>
  <button>Default button font</button>
  <button class="fixed">font: inherit</button>
</div>

What is the difference between display: block, inline and inline-block?

Fresherdisplay

A block element starts on a new line and takes the full width; an inline element flows in the line of text and ignores width and height; inline-block flows inline but accepts width, height and vertical margins.

HTML
<style>
  span, div { background: #bfdbfe; margin: 4px; padding: 4px; }
  .sized { width: 120px; height: 40px; }
  .ib { display: inline-block; }
</style>
<div class="sized">block: own line, width works</div>
<span class="sized">inline: width ignored</span>
<span class="sized ib">inline-block: width works</span>
<span>and stays on the line</span>

Follow-up: why does width work on an img, which is inline? It is a replaced element. More in display.

What is the difference between display: none, visibility: hidden and opacity: 0?

Fresherdisplay

display: none removes the element from layout and from screen readers; visibility: hidden keeps its space but takes no clicks and is not read; opacity: 0 keeps the space, the clicks and the screen reader text.

HTML
<style>
  .row { display: flex; gap: 6px; margin-bottom: 8px; }
  .row div { background: #2563eb; color: white; padding: 8px; }
  .none { display: none; }
  .hidden { visibility: hidden; }
  .clear { opacity: 0; }
</style>
<div class="row"><div>A</div><div class="none">B</div><div>C</div></div>
<div class="row"><div>A</div><div class="hidden">B</div><div>C</div></div>
<div class="row"><div>A</div><div class="clear">B</div><div>C</div></div>

To hide something only visually and keep it for screen readers, use a class that clips it to 1px.

What CSS units do you know, and when do you use each?

Fresherunits

px is absolute. em follows the element's font size, rem the root's, % usually the parent, vw and vh the viewport (dvh, svh on mobile), fr the grid's free space. Use rem for type and spacing so the page follows the user's font setting, % and fr for layout, px for borders. Reference: CSS units.

How do you center a div horizontally and vertically?

Fresherlayout

Make the parent display: flex with justify-content: center and align-items: center, or display: grid with place-items: center, and give it a height.

HTML
<style>
  .flex { display: flex; justify-content: center; align-items: center; }
  .grid { display: grid; place-items: center; }
  .flex, .grid { height: 120px; background: #e5e7eb; margin-bottom: 8px; }
  .box { background: #2563eb; color: white; padding: 12px; }
</style>
<div class="flex"><div class="box">flex</div></div>
<div class="grid"><div class="box">grid</div></div>

Also accepted: margin: 0 auto with a set width (horizontal only), or absolute positioning at 50% plus transform: translate(-50%, -50%), whose percentages refer to the element itself. More in center a div.

What is the difference between a CSS reset and normalize.css?

Fresherbasics

A reset removes the browser's default styles (margins, heading sizes, list bullets); normalize keeps useful defaults and only fixes the differences between browsers. Most projects now use a short reset of their own:

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; }
img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; }

What are the ways to write a color in CSS?

Fresherbasics

Named colors (tomato), hex (#ff6347, short #f63), rgb(255 99 71), hsl(9 100% 64%) and newer spaces like oklch(), each with optional alpha: rgb(255 99 71 / 50%). HSL and OKLCH make shades easy because you change only the lightness.

What is the difference between opacity and an rgba() background?

Fresherbasics

opacity fades the whole element, text and children included; a background like rgb(37 99 235 / 50%) fades only the background.

HTML
<style>
  .stage { background: repeating-linear-gradient(45deg, #fde68a 0 10px, #ffffff 10px 20px); padding: 10px; }
  .box { color: white; padding: 10px; margin-bottom: 8px; font-weight: bold; }
  .op { background: #2563eb; opacity: 0.5; }
  .bg { background: rgb(37 99 235 / 50%); }
</style>
<div class="stage">
  <div class="box op">opacity: 0.5, the text fades too</div>
  <div class="box bg">rgb(... / 50%), the text stays solid</div>
</div>

A child cannot undo its parent's opacity, because the parent is drawn as one layer and then faded. More in opacity.

What are vendor prefixes in CSS, and do you still need them?

Fresherbasics

Prefixes (-webkit-, -moz-, -ms-) mark a browser's own or experimental version of a property. You rarely write them by hand now: browsers ship new features behind flags, and Autoprefixer adds what your Browserslist targets need. Put the standard property after the prefixed one.

.panel {
  -webkit-backdrop-filter: blur(6px);  /* Safari before version 18 */
  backdrop-filter: blur(6px);          /* standard property last */
}
.outlined {
  -webkit-text-stroke: 1px black;      /* only exists with the prefix, in every browser */
}

CSS selectors and specificity interview questions

Which selector matches what, and which rule wins when several match.

What types of CSS selectors are there?

Fresherselectors

Simple (*, p, .btn, #main), attribute ([type="email"], [href^="https"]), combinators (nav a, ul > li, h2 + p, h2 ~ p), pseudo-classes for a state (:hover, :nth-child(2n), :has(img)), pseudo-elements for a part (::before, ::placeholder), and grouping with commas. See selectors.

What is the difference between div p, div > p, div + p and div ~ p?

Fresherselectors

div p matches any p inside a div at any depth; div > p only direct children; div + p only the p right after a div; div ~ p every later p sibling of a div.

HTML
<style>
  .list li { color: gray; }
  .list > li { font-weight: bold; }
  h3 + p { color: crimson; }
  h3 ~ p { font-style: italic; }
</style>
<ul class="list"><li>Child of .list: gray and bold</li></ul>
<div class="list"><ul><li>Grandchild of .list: gray, not bold</li></ul></div>
<h3>Heading</h3>
<p>Right after the heading: crimson and italic</p>
<p>Later sibling: italic only</p>

Sibling combinators only look forward; reaching a previous sibling or a parent needs :has().

How is CSS specificity calculated?

Experiencedspecificity

A three-part score (a, b, c): a counts ids, b classes, attributes and pseudo-classes, c type selectors and pseudo-elements. Compared left to right, so one id beats any number of classes.

HTML
<style>
  #intro { color: green; }
  .lead.big { color: blue; }
  p.lead { color: red; }
  p { color: gray; }
</style>
<p id="intro" class="lead big">Green: the id wins</p>
<p class="lead big">Blue: (0, 2, 0) beats (0, 1, 1)</p>
<p class="lead">Red: (0, 1, 1) beats (0, 0, 1)</p>

* and combinators add nothing; :not(), :is() and :has() take their most specific argument; :where() is always zero.

What does !important do, and why is it considered bad practice?

Experiencedspecificity

!important puts a declaration in a higher cascade tier: it beats every normal declaration, inline styles included, whatever the specificity, and loses only to another !important that wins the usual comparison, or to a running transition. It is bad practice because each later override needs another one. It is fine for utilities like .hidden and against a third-party widget's inline styles. More in !important.

What is the difference between a pseudo-class and a pseudo-element?

Fresherselectors

A pseudo-class selects an element in a state or position (:hover, :checked, :first-child); a pseudo-element styles a part of an element or adds a box that is not in the HTML (::before, ::first-letter, ::placeholder). Pseudo-classes take one colon, pseudo-elements two (:before still works for old CSS2 code).

a:hover { text-decoration: underline; }        /* a state */
li:nth-child(odd) { background: #f3f4f6; }     /* a position */
p::first-line { font-weight: bold; }           /* a part */

How do ::before and ::after work, and why is my ::before not showing?

Experiencedselectors

They insert a generated first and last child, rendered only when content is set (content: "" for a shape).

HTML
<style>
  .required::after { content: " *"; color: crimson; }
  .tag { position: relative; padding-left: 18px; }
  .tag::before {
    content: "";
    position: absolute; left: 0; top: 50%;
    width: 10px; height: 10px; border-radius: 50%;
    background: #16a34a; transform: translateY(-50%);
  }
</style>
<label class="required">Email</label>
<p class="tag">Online</p>

If one does not show: content is missing; the element is a replaced element like img, whose content comes from outside the document; or it is empty and inline, so it needs display: inline-block to take a size.

What is the difference between :nth-child() and :nth-of-type()?

Experiencedselectors

:nth-child(n) counts all siblings whatever their tag, then checks the rest of the selector; :nth-of-type(n) counts only siblings with the same tag.

HTML
<style>
  p:nth-child(2) { background: #fde68a; }
  p:nth-of-type(2) { color: #2563eb; font-weight: bold; }
</style>
<div>
  <h3>Heading (child 1)</h3>
  <p>Paragraph, child 2: yellow background</p>
  <p>Paragraph, child 3, second p: blue text</p>
</div>

So p:nth-child(1) matches nothing here: the first child is the h3. Both take formulas such as 2n+1 or -n+3 (the first three).

How do attribute selectors work?

Experiencedselectors

They match by an attribute's presence or value: [attr], [attr="x"] (exact), ^= (starts with), $= (ends with), *= (contains), ~= (one word in a list). Add i for a case-insensitive match: [type="EMAIL" i]. Specificity equals a class.

HTML
<style>
  input[type="email"] { border: 2px solid #2563eb; }
  [data-state="error"] { color: crimson; }
  [class*="badge-"] { padding: 2px 6px; border-radius: 4px; background: #e5e7eb; }
</style>
<input type="email" placeholder="email: blue border">
<input type="text" placeholder="text: default border">
<p data-state="error">data-state="error" is red</p>
<span class="badge-new">badge-new</span> <span class="badge-sale">badge-sale</span>

A common use is JavaScript state: set data-state="open" and style [data-state="open"].

What do :is(), :where() and :has() do?

Seniorselectors

:is() and :where() match any selector in their list. :is() takes its most specific argument's specificity and :where() zero, which suits defaults meant to be overridden. :has() matches an element by what it contains or what follows it, the parent selector CSS lacked, in Chrome, Safari and Firefox (since 121).

HTML
<style>
  .task { padding: 6px; border-radius: 6px; }
  .task:has(input:checked) { text-decoration: line-through; background: #dcfce7; }
  .btn { background: #7c3aed; } /* wins, even though it comes first */
  :where(.btn) { color: white; background: #2563eb; } /* specificity (0, 0, 0) */
</style>
<label class="task"><input type="checkbox"> Tick me, the row styles itself</label>
<p><button class="btn">.btn overrides :where(.btn)</button></p>

body:has(...) on a large page can be slow; anchor it to a small container, as the MDN :has() performance notes advise.

CSS box model interview questions

Content, padding, border and margin, how box-sizing changes the math, and margin surprises.

What is the CSS box model?

Fresherbox model

Every element is a rectangle of four layers, inside out: content, padding (takes the background), border, and margin (always transparent).

+------------------- margin -------------------+
|  +--------------- border ----------------+   |
|  |  +----------- padding ------------+   |   |
|  |  |            content             |   |   |
|  |  +--------------------------------+   |   |
|  +---------------------------------------+   |
+----------------------------------------------+

By default width measures only the content; box-sizing changes that. More in the box model docs.

What is the difference between box-sizing: content-box and border-box?

Fresherbox model

With content-box (the default), width sets the content only and padding and border are added on top. With border-box, width is the whole box.

HTML
<style>
  .box { width: 200px; padding: 20px; border: 5px solid #2563eb; margin-bottom: 8px; background: #dbeafe; }
  .content { box-sizing: content-box; }
  .border { box-sizing: border-box; }
</style>
<div class="box content">content-box</div>
<div class="box border">border-box</div>
<script>
  for (const el of document.querySelectorAll('.box')) el.textContent += ': ' + el.offsetWidth + 'px wide';
</script>

The first box is 250px (200 + 2 × 20 + 2 × 5), the second 200px, which is why most resets set border-box on everything.

What is the difference between margin and padding?

Fresherbox model

Padding is space inside the border and shows the element's background; margin is space outside it and is always transparent. Only margins can be negative or auto (margin: 0 auto centers a block), and only vertical margins collapse. Space siblings with gap on the parent. See margin vs padding.

What is margin collapsing?

Experiencedbox model

Two touching vertical margins become one equal to the larger, not the sum: 30px then 20px leaves 30px.

HTML
<style>
  .a { margin-bottom: 30px; }
  .b { margin-top: 20px; }
  .a, .b { background: #2563eb; color: white; padding: 6px; }
  .flex { display: flex; flex-direction: column; }
  .note { font: 13px monospace; }
</style>
<div class="box"><div class="a">block layout</div><div class="b">next</div></div>
<div class="box flex"><div class="a">flex column</div><div class="b">next</div></div>
<script>
  for (const box of document.querySelectorAll('.box')) {
    const [a, b] = box.children;
    const gap = b.getBoundingClientRect().top - a.getBoundingClientRect().bottom;
    box.insertAdjacentHTML('afterend', '<p class="note">gap: ' + gap + 'px</p>');
  }
</script>

It happens between siblings, between a parent and its first or last child (the margin leaks out), and on empty blocks. Never horizontally, never in flex or grid (the second box shows 50px), and not across padding, a border or display: flow-root.

What are the values of the overflow property?

Fresherbox model

visible (the default, content spills out), hidden (clipped), clip (clipped, no scrolling at all), scroll (scrollbars always) and auto (scrollbars when needed).

HTML
<style>
  .box { display: inline-block; vertical-align: top; width: 140px; height: 60px; margin: 0 8px 40px 0;
         border: 2px solid #2563eb; font-size: 13px; }
  .v { overflow: visible; } .h { overflow: hidden; } .s { overflow: scroll; } .a { overflow: auto; }
</style>
<div class="box v">visible: this text is too long for the box and spills out below it</div>
<div class="box h">hidden: this text is too long for the box and is cut off at the border</div>
<div class="box s">scroll: this text is too long for the box, so you scroll it</div>
<div class="box a">auto: a scrollbar appears only because this text is too long</div>

Trap: hidden still makes a scroll container, which breaks position: sticky inside it; clip does not. Setting only overflow-x: hidden turns overflow-y into auto, so a vertical scrollbar can appear. More in overflow.

Why do width, height and vertical margin not work on a span?

Experiencedbox model

A span is inline: its size comes from its text, so width, height and vertical margins are ignored, and vertical padding overlaps the lines around it instead of pushing them away.

HTML
<style>
  span { background: #fde68a; }
  .try { width: 200px; height: 60px; margin: 30px; padding: 10px; }
  .ib { display: inline-block; }
</style>
<p>Text before <span class="try">inline span</span> text after, with a second line of text to show that the padding overlaps it.</p>
<p>Text before <span class="try ib">inline-block span</span> text after.</p>

Use display: inline-block or block. Inside a flex or grid parent a span is blockified and accepts a width.

What is the difference between outline and border?

Experiencedbox model

A border is part of the box and takes space; an outline is drawn outside the border, takes none, never shifts the layout and cannot be set per side. Browsers draw keyboard focus with it, so never write outline: none without a replacement; style :focus-visible. For debugging, * { outline: 1px solid red; } shows every box.

How do you truncate text with an ellipsis?

Fresherbox model

For one line you need all four: a constrained width, white-space: nowrap, overflow: hidden and text-overflow: ellipsis. For several lines use -webkit-line-clamp, which every current browser supports despite the prefix.

HTML
<style>
  p { width: 220px; border: 1px solid #9ca3af; padding: 4px; }
  .one { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .two { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
</style>
<p class="one">A long product title that will not fit on a single line of this box</p>
<p class="two">A longer description that runs over several lines, and the box shows only the first two of them before the dots appear at the end</p>

Inside a flex row, the item may refuse to shrink: see the min-width: 0 question.

CSS position, z-index and float interview questions

The five position values, absolute children, sticky bugs and stacking contexts.

What are the values of the position property?

Fresherpositioning

static (the default), relative (offset from its normal spot, space kept), absolute (out of flow, placed against the nearest positioned ancestor), fixed (out of flow, placed against the viewport) and sticky (in flow until it reaches its offset in its scroll container, then sticks). Anything but static counts as positioned. More in position.

How is an absolutely positioned element placed?

Fresherpositioning

Out of the normal flow, against its containing block: the nearest ancestor whose position is not static, or one with a transform, filter or contain: paint. With none, it uses the initial containing block. Hence relative parent, absolute child:

HTML
<style>
  .card { position: relative; width: 220px; padding: 16px; background: #f3f4f6; border-radius: 8px; }
  .badge { position: absolute; top: -8px; right: -8px; background: crimson; color: white; border-radius: 999px; padding: 2px 8px; font-size: 12px; }
</style>
<div class="card">
  Notifications
  <span class="badge">3</span>
</div>

position: relative alone does not move the parent; it only makes it the reference.

Why is my position: sticky not working?

Experiencedpositioning

It sticks within its nearest scrolling ancestor, and only while its parent is on screen. Usual causes:

  1. No top (or other offset).
  2. An ancestor has overflow: hidden, auto or scroll and becomes the scroll container.
  3. The parent is no taller than the sticky element.
  4. In a flex row it stretches to full height; add align-self: flex-start.
HTML
<style>
  .scroller { height: 160px; overflow: auto; border: 1px solid #9ca3af; }
  .head { position: sticky; top: 0; background: #2563eb; color: white; padding: 6px; }
  .scroller p { margin: 0; padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style>
<div class="scroller">
  <div class="head">Sticky header: scroll this box</div>
  <p>Row 1</p><p>Row 2</p><p>Row 3</p><p>Row 4</p><p>Row 5</p><p>Row 6</p><p>Row 7</p>
</div>

Why does my z-index: 999 not bring the element to the front?

Experiencedpositioning

Because z-index only competes inside one stacking context: if an ancestor makes one with a low z-index, nothing inside it can rise above that ancestor's siblings.

HTML
<style>
  div { color: white; padding: 10px; }
  .parent { position: relative; z-index: 1; background: #93c5fd; width: 220px; }
  .child { position: relative; z-index: 999; background: #2563eb; width: 160px; }
  .sibling { position: relative; z-index: 2; background: #f97316; width: 200px; margin: -30px 0 0 60px; }
</style>
<div class="parent"><div class="child">child, z-index: 999</div></div>
<div class="sibling">sibling, z-index: 2</div>

The real contest is parent (1) against sibling (2). Stacking contexts come from z-index on a positioned, flex or grid item, position: fixed or sticky, opacity below 1, transform, filter and isolation: isolate. More in z-index.

How does float work, and what is a clearfix?

Experiencedpositioning

float pushes an element to one side and lets text wrap around it. Floats leave the flow, so a parent holding only floats collapses to zero height; a clearfix makes it contain them.

HTML
<style>
  .box { border: 2px solid #2563eb; margin-bottom: 30px; }
  .img { float: left; width: 80px; height: 80px; background: #f97316; margin-right: 8px; }
  .contained { display: flow-root; }
</style>
<div class="box contained"><div class="img"></div>With display: flow-root the box grows to contain the float.</div>
<div class="box"><div class="img"></div>Without it the border ignores the float.</div>

The old clearfix was a ::after with clear: both; display: flow-root now does it in one line. More in float.

Why is my position: fixed element not fixed to the viewport?

Seniorpositioning

An ancestor with transform (even translateX(0)), filter, backdrop-filter, perspective, contain: paint, or will-change for one of those, becomes the containing block for fixed descendants, which then stick to it instead of the viewport.

HTML
<style>
  .panel { height: 120px; border: 2px dashed #9ca3af; margin-bottom: 8px; padding: 6px; }
  .moved { transform: translateX(0); }
  .toast { position: fixed; bottom: 8px; left: 8px; background: #111827; color: white; padding: 6px 10px; }
</style>
<div class="panel moved">This box has a transform, so its toast is trapped at the box's bottom left.
  <div class="toast">trapped</div>
</div>
<div class="panel">This box has none, so its toast is fixed to the bottom left of the preview window.
  <div class="toast">viewport</div>
</div>

Render modals at the end of body (a React portal), or use <dialog> with showModal(), which draws in the top layer.

CSS Flexbox interview questions

Axes, alignment, how flex-grow and flex-shrink share space, and the overflow bug everyone meets.

What is Flexbox and when do you use it?

Fresherflexbox

A one-dimensional layout model: display: flex lays a parent's direct children out in a row or column (the main axis) and controls how they share space and align on the cross axis. Use it for one line of items, like a nav bar or toolbar; for rows and columns at once, use Grid. Reference: Flexbox.

What is the difference between justify-content and align-items?

Fresherflexbox

justify-content distributes items along the main axis; align-items aligns them along the cross axis. In the default row that is horizontal and vertical; flex-direction: column swaps them.

HTML
<style>
  .row { display: flex; height: 90px; background: #e5e7eb; margin-bottom: 8px;
         justify-content: space-between; align-items: center; }
  .col { display: flex; flex-direction: column; height: 140px; width: 160px; background: #e5e7eb;
         justify-content: center; align-items: flex-end; }
  .item { background: #2563eb; color: white; padding: 6px 10px; margin: 2px; }
</style>
<div class="row"><div class="item">1</div><div class="item">2</div><div class="item">3</div></div>
<div class="col"><div class="item">1</div><div class="item">2</div></div>

There is no justify-self in flexbox. To push one item to the end, give it margin-left: auto.

How do flex-grow, flex-shrink and flex-basis work together?

Experiencedflexbox

flex-basis is the starting size. Leftover free space is shared in proportion to flex-grow; overflow is taken back in proportion to flex-shrink, weighted by each basis.

HTML
<style>
  .row { display: flex; width: 500px; background: #e5e7eb; }
  .a { flex: 1 1 100px; background: #93c5fd; }
  .b { flex: 2 1 100px; background: #2563eb; color: white; }
</style>
<div class="row"><div class="a">grow 1</div><div class="b">grow 2</div></div>
<script>
  for (const el of document.querySelectorAll('.row > div')) el.textContent += ': ' + el.offsetWidth + 'px';
</script>

The bases use 200px, leaving 300px: a gets a third and b two thirds, so they end at 200px and 300px, not 1:2. For true 1:2 use flex: 1 and flex: 2, which set the bases to 0.

What do flex: 1, flex: auto and flex: none mean?

Experiencedflexbox

Shorthands for flex-grow flex-shrink flex-basis:

  • flex: initial (0 1 auto), the default: content size, can shrink, never grows.
  • flex: 1 (1 1 0%): splits space equally, ignoring content.
  • flex: auto (1 1 auto): content size, then shares the rest.
  • flex: none (0 0 auto): rigid, for an icon that must not squash.

The trap: flex: 1 gives equal widths whatever the text; flex: auto lets longer text take more.

Why does a flex item overflow its container instead of shrinking?

Seniorflexbox

Flex items default to min-width: auto, so they will not shrink below their content's minimum width: the longest word, an image, a nowrap child. Set min-width: 0 (or overflow: hidden) on the item.

HTML
<style>
  .row { display: flex; gap: 8px; width: 260px; border: 1px solid #9ca3af; padding: 6px; margin-bottom: 8px; }
  .avatar { flex: none; width: 40px; height: 40px; border-radius: 50%; background: #2563eb; }
  .main { flex: 1; }
  .fixed .main { min-width: 0; }
  .name { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
</style>
<div class="row"><div class="avatar"></div><div class="main"><p class="name">A very long display name that will not fit here</p></div></div>
<div class="row fixed"><div class="avatar"></div><div class="main"><p class="name">A very long display name that will not fit here</p></div></div>

Only the second row, with min-width: 0 on .main, shows the ellipsis. Grid 1fr tracks have the same issue.

How do flex-wrap, gap and align-content work?

Experiencedflexbox

flex-wrap: wrap moves items to new lines instead of shrinking them; gap spaces items and lines but not the outer edges; align-content spaces the lines, so it does nothing on a single-line nowrap container.

HTML
<style>
  .wrap { display: flex; flex-wrap: wrap; gap: 8px; width: 280px; height: 180px;
          align-content: space-between; background: #e5e7eb; padding: 8px; }
  .item { flex: 1 1 60px; background: #2563eb; color: white; padding: 8px; }
</style>
<div class="wrap">
  <div class="item">1</div><div class="item">2</div><div class="item">3</div>
  <div class="item">4</div><div class="item">5</div>
</div>

Items 4 and 5 stretch across the last line and stop lining up with the row above. For columns, use Grid.

CSS Grid interview questions

Grid versus Flexbox, fr units, auto-fill vs auto-fit, template areas and track sizing.

What is the difference between Flexbox and CSS Grid?

Freshergrid

Flexbox is one-dimensional: items sit in one row or column and their content sets their size. Grid is two-dimensional: you define rows and columns and place items in them, so they line up both ways. Use grid for the page and card grids and flex inside each card. More in CSS Grid.

What is the fr unit in CSS Grid?

Freshergrid

fr is a share of the free space in the grid: what is left after fixed tracks and gaps.

HTML
<style>
  .grid { display: grid; grid-template-columns: 200px 1fr 2fr; width: 500px; background: #e5e7eb; }
  .grid div { background: #2563eb; color: white; padding: 8px 0; border-right: 2px solid white; }
</style>
<div class="grid"><div>200px</div><div>1fr</div><div>2fr</div></div>
<script>
  for (const el of document.querySelectorAll('.grid div')) el.textContent += ' = ' + el.offsetWidth + 'px';
</script>

200px is fixed and 300px is free, so 1fr is 100px and 2fr is 200px. Unlike 33.33% columns, repeat(3, 1fr) subtracts the gap first, so the gaps never cause overflow.

What is the difference between auto-fill and auto-fit in repeat()?

Experiencedgridresponsive

Both create as many columns as fit, so repeat(auto-fill, minmax(120px, 1fr)) is a responsive grid with no media queries. With fewer items than columns, auto-fill keeps the empty columns and auto-fit collapses them, so the items stretch to fill the row.

HTML
<style>
  .g { display: grid; gap: 8px; width: 520px; background: #e5e7eb; padding: 8px; margin-bottom: 8px; }
  .fill { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
  .fit { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
  .g div { background: #2563eb; color: white; padding: 10px; }
</style>
<div class="g fill"><div>auto-fill</div><div>2</div></div>
<div class="g fit"><div>auto-fit</div><div>2</div></div>

How do grid-template-areas work?

Experiencedgrid

Name each child's region with grid-area, then draw the layout as strings on the container: one string per row, . for an empty cell. Each area must be a rectangle.

HTML
<style>
  .page {
    display: grid; gap: 6px; height: 220px;
    grid-template-columns: 120px 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
      "header header"
      "side   main"
      "footer footer";
  }
  .page > * { background: #2563eb; color: white; padding: 8px; }
  header { grid-area: header; } aside { grid-area: side; } main { grid-area: main; } footer { grid-area: footer; }
</style>
<div class="page"><header>header</header><aside>side</aside><main>main</main><footer>footer</footer></div>

A media query can redefine only grid-template-areas, and the children follow with no HTML change.

What is the difference between the explicit and the implicit grid?

Seniorgrid

The explicit grid is the tracks you define with grid-template-columns and grid-template-rows. Extra items get tracks the browser adds, the implicit grid, sized by grid-auto-rows and grid-auto-columns (default auto).

.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* explicit: 3 columns */
  grid-auto-rows: 120px;                 /* every implicit row is 120px */
  grid-auto-flow: row dense;             /* backfill holes left by big items */
}
.gallery .wide { grid-column: span 2; }

dense backfills holes with later items, so visual order stops matching the DOM: fine for a gallery, not for text.

Why does a 1fr column grow wider than its share?

Seniorgrid

Because 1fr means minmax(auto, 1fr): its minimum is the content's minimum width, so a long word or a wide table forces the track wider. minmax(0, 1fr) lets it shrink; then handle the content with overflow-wrap: anywhere or overflow: auto.

HTML
<style>
  .g { display: grid; gap: 8px; width: 300px; border: 1px solid #9ca3af; margin-bottom: 8px; }
  .one { grid-template-columns: 1fr 1fr; }
  .two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .g div { background: #dbeafe; padding: 4px; }
  .two div { overflow-wrap: anywhere; }
</style>
<div class="g one"><div>Pneumonoultramicroscopicsilicovolcanoconiosis</div><div>short</div></div>
<div class="g two"><div>Pneumonoultramicroscopicsilicovolcanoconiosis</div><div>short</div></div>

It is the grid twin of the flexbox min-width: 0 bug.

What is subgrid and what problem does it solve?

Seniorgrid

grid-template-rows: subgrid (or columns) makes a nested grid reuse its parent's tracks, so titles and buttons line up across cards even when one title wraps. It works in Chrome 117+, Firefox 71+ and Safari 16+ (see MDN subgrid).

HTML
<style>
  .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 10px; }
  .card { display: grid; grid-row: span 3; grid-template-rows: subgrid; gap: 6px;
          border: 1px solid #9ca3af; border-radius: 8px; padding: 8px; margin-bottom: 8px; }
  .card h4 { margin: 0; }
  .card p { margin: 0; }
  button { align-self: end; }
</style>
<div class="cards">
  <div class="card"><h4>Basic</h4><p>Short text.</p><button>Buy</button></div>
  <div class="card"><h4>A much longer plan name that wraps</h4><p>Text.</p><button>Buy</button></div>
  <div class="card"><h4>Pro</h4><p>A longer description that takes more lines than the others.</p><button>Buy</button></div>
</div>

Each card spans three parent rows, so the tallest title sets every card's title row.

Responsive design CSS interview questions

Media queries, mobile-first, relative units, fluid sizes and container queries.

What are media queries and how do you write one?

Fresherresponsive

A media query applies CSS only when a condition about the device or viewport is true, most often its width.

HTML
<style>
  .card { padding: 12px; background: #fde68a; }
  .card::after { content: " (narrow: under 500px)"; }
  @media (min-width: 500px) {
    .card { background: #bbf7d0; }
    .card::after { content: " (wide: 500px or more)"; }
  }
</style>
<div class="card">The preview's width picks the color</div>

Change 500px to 2000px to see the other branch. You can also test preferences (prefers-color-scheme), input (pointer: coarse), print, and ranges like @media (width >= 600px). More in media queries.

Why does a responsive page need the viewport meta tag?

Fresherresponsive

Without it, mobile browsers lay the page out about 980px wide and zoom out, so your small-screen media queries never match and the text is tiny.

<meta name="viewport" content="width=device-width, initial-scale=1">

Do not add maximum-scale=1 or user-scalable=no: blocking zoom is an accessibility failure.

What is mobile-first CSS?

Fresherresponsive

Base styles target the smallest screen, and min-width media queries enhance the layout as the screen grows. Desktop-first is the reverse, with max-width queries that undo things.

.list { display: grid; gap: 12px; }            /* phones: one column */

@media (min-width: 640px) {
  .list { grid-template-columns: 1fr 1fr; }    /* tablets */
}
@media (min-width: 1024px) {
  .list { grid-template-columns: repeat(4, 1fr); }
}

Phones then skip the wide-screen rules instead of applying and undoing them. Put breakpoints where your content breaks, not at device widths.

What is the difference between em and rem?

Experiencedunitsresponsive

rem is relative to the root font size; em to the element's own font size (for font-size, its parent's), so em compounds when nested.

HTML
<style>
  .em { font-size: 1.2em; }
  .rem { font-size: 1.2rem; }
</style>
<div class="em">1.2em <div class="em">1.2em <div class="em">1.2em</div></div></div>
<div class="rem">1.2rem <div class="rem">1.2rem <div class="rem">1.2rem</div></div></div>

With a 16px root the em levels are 19.2px, 23.04px and 27.648px; every rem level is 19.2px. Use rem for type and spacing, em where sizes should follow the element's own text.

How do you make font sizes fluid with clamp()?

Experiencedresponsive

clamp(min, preferred, max) returns the preferred value kept between the limits. With a viewport unit in the middle, the size grows with the screen with no breakpoints.

HTML
<style>
  h1 { font-size: clamp(1.5rem, 1rem + 4vw, 3rem); margin: 0 0 8px; }
  .box { width: clamp(200px, 50%, 400px); background: #dbeafe; padding: 8px; }
</style>
<h1>Fluid heading</h1>
<div class="box">Between 200px and 400px, otherwise half the width</div>

Keep a rem part (1rem + 4vw, not 4vw): pure viewport units ignore browser zoom and the user's font size.

How do you make images responsive?

Experiencedresponsive

In CSS, max-width: 100%; height: auto; stops overflow and keeps the ratio, and object-fit: cover crops into a fixed box. In HTML, srcset and sizes let the browser pick the file:

<img src="photo-800.jpg"
     srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
     sizes="(min-width: 800px) 50vw, 100vw"
     width="800" height="600" alt="Team at the office">

Keep width and height: the browser reserves the space before loading, which prevents layout shift (CLS).

What are container queries and how are they different from media queries?

Seniorresponsive

A media query asks about the viewport; a container query asks about an ancestor marked as a container, so one card can stack in a sidebar and sit side by side in the main column.

HTML
<style>
  .slot { container-type: inline-size; border: 1px dashed #9ca3af; padding: 6px; margin-bottom: 8px; }
  .narrow { width: 240px; }
  .wide { width: 480px; }
  .card { display: grid; gap: 8px; }
  .thumb { height: 60px; background: #2563eb; }
  @container (min-width: 400px) {
    .card { grid-template-columns: 100px 1fr; }
  }
</style>
<div class="slot narrow"><div class="card"><div class="thumb"></div><p>Narrow container: stacked</p></div></div>
<div class="slot wide"><div class="card"><div class="thumb"></div><p>Wide container: side by side</p></div></div>

container-type: inline-size is required so the container's width cannot depend on its children.

Why does height: 100vh cause problems on mobile?

Seniorresponsiveunits

On mobile, 100vh assumes the address bar is hidden, so while it shows, the bottom of a 100vh section is cut off. Use svh (browser UI shown), lvh (UI hidden) or dvh (follows the UI).

.hero {
  min-height: 100vh;   /* fallback for old browsers */
  min-height: 100svh;  /* never hidden under the address bar */
}

Prefer svh: dvh resizes while the user scrolls. Use min-height so content can grow.

CSS animation and transition interview questions

Transitions, keyframes, transforms, what is cheap to animate, and reduced motion.

What is the difference between a CSS transition and a CSS animation?

Fresheranimation

A transition animates a property from its old value to its new one when it changes (on :hover, a class toggle); an animation runs @keyframes on its own, with any number of steps, can loop, and needs no state change.

HTML
<style>
  .btn { background: #2563eb; color: white; border: 0; padding: 10px 16px; border-radius: 6px;
         transition: background-color 0.3s ease, transform 0.3s ease; }
  .btn:hover { background: #7c3aed; transform: translateY(-3px); }
</style>
<button class="btn">Hover me</button>

More in transition.

How do you create a CSS animation with @keyframes?

Fresheranimation

Define the steps with @keyframes name { ... }, then attach them with animation: at least a name and a duration.

HTML
<style>
  @keyframes spin { to { transform: rotate(360deg); } }
  @keyframes pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.15); }
  }
  .spinner { width: 32px; height: 32px; border: 4px solid #dbeafe; border-top-color: #2563eb;
             border-radius: 50%; animation: spin 0.8s linear infinite; }
  .dot { width: 20px; height: 20px; margin-top: 16px; border-radius: 50%; background: crimson;
         animation: pulse 1.2s ease-in-out infinite; }
</style>
<div class="spinner"></div>
<div class="dot"></div>

Useful longhands: -iteration-count, -direction (alternate plays back and forth), -fill-mode (forwards keeps the last frame) and -play-state. More in animation.

What does the transform property do, and does it affect layout?

Fresheranimation

transform moves, rotates, scales or skews an element and does not affect layout: it keeps its original space and its neighbors do not move.

HTML
<style>
  .row { display: flex; gap: 10px; }
  .row div { width: 70px; height: 70px; background: #2563eb; color: white; display: grid; place-items: center; }
  .t1 { transform: translate(10px, 10px); }
  .t2 { transform: rotate(20deg); }
  .t3 { transform: scale(1.3); }
</style>
<div class="row"><div>none</div><div class="t1">move</div><div class="t2">rotate</div><div class="t3">scale</div></div>

Order matters: each function works in the coordinates left by the one before, so rotate(45deg) translateX(50px) differs from the reverse. transform-origin sets the pivot.

Why can you not transition display: none, and what do you do instead?

Experiencedanimation

display is discrete: there is no halfway between none and block, so the change is instant. Animate opacity with visibility instead; visibility: hidden also keeps the element out of the tab order.

HTML
<style>
  .panel { opacity: 0; visibility: hidden; transform: translateY(-6px);
           transition: opacity 0.25s, transform 0.25s, visibility 0.25s;
           background: #dbeafe; padding: 10px; margin-top: 8px; }
  #toggle:checked ~ .panel { opacity: 1; visibility: visible; transform: none; }
</style>
<input type="checkbox" id="toggle"> <label for="toggle">Show panel</label>
<div class="panel">Fades and slides, and is not focusable while hidden.</div>

Chrome and Safari 18 can animate display with transition-behavior: allow-discrete and @starting-style; Firefox cannot yet.

Which CSS properties are cheap to animate, and why?

Senioranimationperformance

transform and opacity. In the style, layout, paint, composite pipeline they touch only composite, which can run off the main thread, so they stay smooth. width, top, left and margin force layout every frame; background-color and box-shadow force paint. Move with translate(), grow with scale(), and use will-change: transform sparingly: every layer costs memory.

How do you respect users who turn off animations?

Experiencedanimationaccessibility

Use the prefers-reduced-motion media query, which matches when the user turned on "reduce motion" in their operating system.

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Cleaner: write static styles first and add motion inside @media (prefers-reduced-motion: no-preference). A short fade is fine; parallax and large slides should go.

CSS interview questions for experienced developers (3 to 10 years)

Theming, formatting contexts, rendering performance, cascade layers and architecture for mid-level and senior developers.

What are CSS custom properties, and how are they different from Sass variables?

Experiencedvariables

Custom properties (--brand: #2563eb;, read with var(--brand)) live in the browser: they cascade, inherit and can change at runtime. Sass variables become fixed values at build time.

HTML
<style>
  :root { --bg: #ffffff; --text: #111827; --accent: #2563eb; }
  .dark { --bg: #111827; --text: #f9fafb; --accent: #93c5fd; }
  .card { background: var(--bg); color: var(--text); border: 2px solid var(--accent);
          padding: 10px; margin-bottom: 8px; border-radius: 8px; }
  .card b { color: var(--accent); }
</style>
<div class="card">Default theme, <b>accent</b></div>
<div class="dark"><div class="card">Same rule inside .dark, <b>accent</b></div></div>

Redefine them on a parent and everything below changes, which is how themes work; JavaScript can set them with element.style.setProperty(). More in CSS variables.

How would you implement dark mode in CSS?

Seniorvariables

Put every color in custom properties, define a dark set in @media (prefers-color-scheme: dark), and set color-scheme so scrollbars and form controls darken too. A data-theme attribute lets a manual toggle override the system setting.

:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --text: #111827;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --bg: #0f172a; --text: #e5e7eb; }
}
:root[data-theme="dark"] { color-scheme: dark; --bg: #0f172a; --text: #e5e7eb; }
:root[data-theme="light"] { color-scheme: light; }

body { background: var(--bg); color: var(--text); }

Apply the saved choice from a small inline script in the head, before first paint, or the page flashes light first.

What is a block formatting context (BFC)?

Seniorlayout

An isolated layout region: floats inside stay inside, floats outside do not overlap it, and margins inside it do not collapse with margins outside it. Floats, absolute elements, inline-block, table cells, overflow other than visible or clip, flex and grid items, and display: flow-root create one.

HTML
<style>
  .float { float: left; width: 90px; height: 90px; background: #f97316; margin-right: 10px; }
  .text { background: #dbeafe; padding: 6px; margin-bottom: 8px; }
  .bfc { display: flow-root; }
</style>
<div class="float"></div>
<div class="text">Normal block: its background runs under the float, only the text wraps.</div>
<div style="clear: both"></div>
<div class="float"></div>
<div class="text bfc">New BFC: the whole box sits beside the float.</div>

flow-root exists only to create a BFC; overflow: hidden also clips.

What is the difference between reflow and repaint, and what is layout thrashing?

Seniorperformance

Reflow (layout) recalculates sizes and positions; repaint redraws pixels without changing geometry. width triggers both, color only a repaint, transform and opacity can skip both. Layout thrashing is JavaScript alternating writes and reads, which forces a layout on every read:

const items = [...document.querySelectorAll('.item')];

// Slow: every offsetHeight read forces layout after the previous write
for (const el of items) {
  el.style.height = el.offsetHeight + 10 + 'px';
}

// Fast: read everything first, then write
const heights = items.map((el) => el.offsetHeight);
items.forEach((el, i) => { el.style.height = heights[i] + 10 + 'px'; });

Layout-forcing reads include offsetWidth, getBoundingClientRect() and scrollTop.

What are cascade layers (@layer) and what problem do they solve?

Seniorcascadearchitecture

@layer groups styles into named layers whose order you declare once. A later layer beats an earlier one regardless of specificity, so a plain class in components overrides a long selector in vendor.

@layer reset, vendor, components, utilities;

@layer vendor {
  .widget .header nav ul li a { color: gray; }  /* high specificity */
}
@layer components {
  .nav-link { color: navy; }                     /* wins: later layer */
}

Unlayered styles beat every layer, and for !important declarations the order is reversed.

How do you organize CSS in a large project: BEM, CSS Modules, utility classes or CSS-in-JS?

Seniorarchitecture

Pick by team and stack; all four fight global class names that collide. BEM is a naming convention with no tooling; CSS Modules rename classes per file at build time; Tailwind replaces custom class names with long utility lists; CSS-in-JS gives dynamic styles at a runtime cost. Whatever you pick, keep design tokens in custom properties, specificity low and flat, and no styling by id.

Why is CSS render-blocking, and how do you load it faster?

Seniorperformance

The browser will not paint until every stylesheet in the head that matches the current media has loaded, or it would flash unstyled content. To cut the delay, inline the critical CSS for the first screen, give non-matching sheets a media attribute (media="print" does not block), remove unused CSS, and avoid @import, which chains requests.

What are CSS logical properties and why do they matter?

Seniorlayoutaccessibility

They name sides by writing direction instead of physical direction: margin-inline-start instead of margin-left, padding-block instead of top and bottom, inset-inline-end instead of right. In right-to-left languages like Arabic or Hebrew they flip automatically, so you skip a second set of [dir="rtl"] rules.

HTML
<style>
  .note { border-inline-start: 4px solid #2563eb; padding-inline-start: 10px;
          margin-block: 8px; background: #f3f4f6; }
</style>
<p class="note" dir="ltr">Left to right: the border is on the left.</p>
<p class="note" dir="rtl">من اليمين إلى اليسار: الحد على اليمين.</p>

What is the difference between :focus and :focus-visible?

Experiencedaccessibility

:focus matches whenever an element has focus, including after a mouse click (except in Safari, which by design does not focus a button on click); :focus-visible matches only when the browser decides focus should show, typically during keyboard navigation.

HTML
<style>
  button { padding: 8px 14px; margin: 4px; border: 1px solid #9ca3af; border-radius: 6px; background: white; }
  .a:focus { outline: 3px solid crimson; }
  .b:focus { outline: none; }
  .b:focus-visible { outline: 3px solid #2563eb; outline-offset: 2px; }
</style>
<button class="a">:focus (click me)</button>
<button class="b">:focus-visible (click, then press Tab)</button>

The anti-pattern is *:focus { outline: none; } with no replacement.

How do you keep an element at a fixed aspect ratio?

Experiencedlayout

Set one dimension and the aspect-ratio property; the browser computes the other.

HTML
<style>
  .row { display: flex; gap: 10px; align-items: flex-start; }
  .video { width: 200px; aspect-ratio: 16 / 9; background: #2563eb; color: white; display: grid; place-items: center; }
  .square { width: 90px; aspect-ratio: 1; background: #f97316; color: white; display: grid; place-items: center; }
</style>
<div class="row"><div class="video">16 / 9</div><div class="square">1 / 1</div></div>

Follow-up: why did the old padding-top: 56.25% hack work? Vertical padding percentages are calculated from the containing block's width.

Do you still need Sass now that CSS has variables and nesting?

Seniorarchitecture

Less than before. CSS now has custom properties, nesting, calc(), color-mix() and cascade layers, and nesting works in Chrome 120+, Firefox 117+ and Safari 17.2+.

.card {
  padding: 1rem;
  & h2 { margin: 0; }
  &:hover { box-shadow: 0 2px 8px rgb(0 0 0 / 20%); }
  @media (min-width: 640px) { padding: 2rem; }
}

Sass still adds mixins, loops and partials. New projects can often skip it; existing Sass codebases have no urgent reason to migrate.

How do you debug a CSS rule that is not being applied?

Experienceddebugging

In DevTools, read the element's Styles pane: matching rules in cascade order, overridden ones struck through, invalid ones flagged. Then check:

  1. The selector does not match (a typo, a class added later by JavaScript).
  2. Another rule wins on specificity, layer or order.
  3. The value is invalid, so it is dropped (colour).
  4. The property does nothing here (z-index on a static element).
  5. The stylesheet did not load (Network tab).

Preparing for the interview

How do I prepare for a CSS interview?
Build small things from memory: a centered card, a Flexbox nav bar, a responsive card grid, a sticky header, a modal. Then explain out loud why each property is there. Most CSS rounds are "what does this do" questions or a short layout task.
What CSS questions are asked for freshers?
The three ways to add CSS, selectors and specificity, the box model and box-sizing, display and position values, em and rem, and centering. Expect a Flexbox question and a simple media query layout.
What do interviewers ask experienced frontend developers about CSS?
Reasoning more than definitions: why a layout breaks (stacking contexts, min-width: auto, margin collapsing), what is cheap to animate, how CSS affects page load, theming with custom properties, and keeping a large stylesheet maintainable. You may be asked to fix existing CSS.
Is CSS alone enough for a frontend interview?
No. Frontend rounds combine HTML, CSS and JavaScript, and most add a short JavaScript coding problem. Prepare the JavaScript interview questions and a few easy string and array problems.
Should I learn Flexbox or Grid first?
Flexbox first: most components use it. Learn Grid right after for page layouts and card grids; Flexbox vs Grid is one of the most common CSS questions.
Coddy programming languages illustration

Learn to code with Coddy

GET STARTED