Interview Prep

HTML & CSSInterview Questions

63 hand-picked questions with detailed answers and code examples. Perfect prep for your next frontend interview.

Level:

Showing 63 of 63 questions

  • HTMLBeginner

    What is HTML and what does it stand for?

    HTML stands for HyperText Markup Language. It is the standard markup language used to structure and present content on the web. HTML uses a system of tags and elements to describe the structure of a webpage — headings, paragraphs, links, images, lists, and more.
  • HTMLBeginner

    What is the purpose of <!DOCTYPE html>?

    The DOCTYPE declaration tells the browser which version of HTML the document uses. <!DOCTYPE html> is the HTML5 declaration and forces the browser into "standards mode" so the page renders consistently across browsers. Without it, browsers fall back to "quirks mode" which emulates legacy bugs.
    <!DOCTYPE html>
    <html lang="en">
      <head>...</head>
      <body>...</body>
    </html>
  • HTMLBeginner

    What is semantic HTML and why does it matter?

    Semantic HTML uses elements that describe the meaning of their content (e.g., <header>, <nav>, <main>, <article>, <footer>) instead of generic <div>s. It improves accessibility for screen readers, helps SEO, and makes the markup easier to read and maintain.
    <!-- ✗ Non-semantic -->
    <div class="header">
      <div class="nav">...</div>
    </div>
    
    <!-- ✓ Semantic -->
    <header>
      <nav>...</nav>
    </header>
  • HTMLBeginner

    What is the difference between <div> and <span>?

    <div> is a block-level element that starts on a new line and takes the full available width. <span> is an inline element that only takes the width of its content and sits in the flow of text. Use <div> for grouping block content, <span> for styling small parts of text inline.
  • HTMLBeginner

    What is the difference between block, inline, and inline-block elements?

    Block elements (e.g., <div>, <p>) start on a new line and stretch full width. Inline elements (e.g., <span>, <a>) flow inside text and only take the width they need — width/height are ignored. Inline-block elements behave inline but accept width, height, padding, and margin like blocks.
  • HTMLBeginner

    What new features did HTML5 introduce?

    HTML5 added semantic elements (<header>, <nav>, <article>, <section>, <footer>), new form input types (email, date, number, range), <canvas> and <svg> for graphics, <audio> and <video> without plugins, the Web Storage API (localStorage, sessionStorage), Geolocation, Web Workers, and offline support via Application Cache (now replaced by Service Workers).
  • HTMLBeginner

    What does the viewport meta tag do?

    It controls how the page is sized and scaled on mobile devices. Without it, mobile browsers render at desktop width and shrink the page. With width=device-width, initial-scale=1.0, the layout uses the actual device width — a foundational requirement for responsive design.
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0">
  • HTMLBeginner

    What are data-* attributes used for?

    Custom data-* attributes let you store extra information on HTML elements without using non-standard attributes. They are accessible from JavaScript via element.dataset and from CSS via attribute selectors. Useful for state, IDs, or any context the UI needs without polluting the DOM.
    <button data-user-id="42" data-action="delete">×</button>
    
    <script>
      btn.dataset.userId; // "42"
    </script>
  • HTMLIntermediate

    What is the difference between async and defer on <script> tags?

    Both download scripts in parallel without blocking HTML parsing. async executes the script as soon as it downloads — order is not guaranteed, so use it for independent scripts (analytics). defer waits until the HTML is fully parsed and executes scripts in order — ideal for app code that depends on the DOM.
    <script src="analytics.js" async></script>
    <script src="app.js" defer></script>
  • HTMLIntermediate

    localStorage vs sessionStorage vs cookies — when to use which?

    localStorage persists until manually cleared, ~5–10MB, not sent to the server. sessionStorage clears when the tab closes, same size limits. Cookies are sent with every HTTP request to the same domain, ~4KB max — best for auth tokens and server-readable session info. Use localStorage for client-only preferences, cookies for server state.
  • HTMLIntermediate

    How do you do form validation in HTML5?

    HTML5 provides built-in validation via attributes like required, min, max, pattern, minlength, maxlength, and input types like email and url. The browser shows native error messages and prevents submission. Style invalid fields with the :invalid pseudo-class. Always validate again on the server — client validation can be bypassed.
    <input type="email" required
           pattern="[^@]+@[^@]+\.[a-z]{2,}" />
    
    input:invalid { border-color: crimson; }
  • HTMLIntermediate

    When should you use an <iframe> and what are its risks?

    Use <iframe> to embed external content (YouTube videos, maps, payment widgets, sandboxed previews). Risks: it can slow down the page, break layouts, and expose you to clickjacking. Mitigate with the sandbox attribute (restricts what the iframe can do), loading="lazy", and referrerpolicy.
    <iframe src="..."
            sandbox="allow-scripts allow-same-origin"
            loading="lazy"
            title="Live preview"></iframe>
  • HTMLIntermediate

    Why should <meta charset="UTF-8"> be the first thing in <head>?

    It tells the browser how to decode bytes into characters. If declared after the first ~1024 bytes, the browser may have already started parsing with the wrong encoding and need to restart. Putting it first guarantees correct encoding from byte one — important for special characters, emojis, and non-Latin alphabets.
  • HTMLIntermediate

    What are srcset and <picture> for?

    srcset lets the browser choose the best image based on screen density (@1x, @2x, @3x) or width. <picture> lets you serve different image formats (e.g., AVIF, WebP, JPEG fallback) or completely different images per breakpoint (art direction). Both reduce bandwidth and improve performance on mobile.
    <picture>
      <source srcset="hero.avif" type="image/avif">
      <source srcset="hero.webp" type="image/webp">
      <img src="hero.jpg" alt="Hero">
    </picture>
  • HTMLAdvanced

    What is the Shadow DOM?

    The Shadow DOM is a way to attach an encapsulated subtree to an element. Styles and scripts inside the shadow root cannot leak out, and outside CSS cannot reach in (except through CSS custom properties and ::part). It powers Web Components and isolates third-party widgets like the YouTube embed player.
    const host = document.querySelector('#app');
    const shadow = host.attachShadow({ mode: 'open' });
    shadow.innerHTML = `<style>p { color: red; }</style>
                       <p>Isolated</p>`;
  • HTMLAdvanced

    What are Web Components?

    A set of three native browser APIs for building reusable custom elements: Custom Elements (defining new HTML tags), Shadow DOM (style/markup encapsulation), and HTML Templates (<template> and <slot> for declarative content). Frameworks like Lit and Stencil build on top of them; they work in any framework or no framework.
  • CSSBeginner

    Explain the CSS box model.

    Every element is a rectangular box composed of four parts (inside out): contentpadding (transparent space inside the border) → bordermargin (transparent space outside the border). By default, width and height only set the content size; box-sizing: border-box makes them include padding and border, which is far more intuitive.
    * { box-sizing: border-box; }
  • CSSBeginner

    What is CSS specificity and how is it calculated?

    Specificity decides which CSS rule wins when multiple rules target the same element. Calculated as (inline, IDs, classes/attrs/pseudo-classes, elements/pseudo-elements) — higher beats lower. Example: #id (0,1,0,0) beats .class.class (0,0,2,0). !important overrides everything; inline styles beat external stylesheets at the same specificity.
  • CSSBeginner

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

    A pseudo-class (single colon) styles an element in a particular state — :hover, :focus, :nth-child(2). A pseudo-element (double colon in modern CSS) styles a virtual sub-part — ::before, ::after, ::first-letter, ::placeholder. Pseudo-classes target real elements; pseudo-elements create or target generated content.
  • CSSBeginner

    Explain the values of the position property.

    static (default) — normal flow. relative — flows normally but offset from its position with top/left; creates a new positioning context. absolute — removed from flow, positioned relative to nearest positioned ancestor. fixed — positioned relative to viewport, stays during scroll. sticky — relative until it hits a scroll threshold, then fixed.
  • CSSBeginner

    When do you use px, em, rem, %, vw/vh?

    px — fixed, predictable; good for borders, shadows. em — relative to parent font-size; cascading, useful inside components. rem — relative to root font-size; predictable scaling. % — relative to parent property. vw/vh — relative to viewport; great for full-screen layouts. Combine with clamp() for fluid typography.
    font-size: clamp(1rem, 2.5vw, 1.5rem);
  • CSSBeginner

    What do inherit, initial, and unset do?

    inherit — take the value from the parent element. initial — reset to the property's default value as defined by the spec (often not what you want — display: initial is inline, not block). unset — inherit if the property normally inherits, otherwise reset to initial. Use unset for safe resets.
  • LayoutIntermediate

    When should you use Flexbox vs CSS Grid?

    Flexbox is one-dimensional — distribute items in a row or column. Best for navbars, button groups, centering, and component-level layouts where the content size is unknown. Grid is two-dimensional — control rows and columns simultaneously. Best for page layouts, dashboards, image galleries. They compose well: a grid cell can contain a flex container.
  • LayoutIntermediate

    Explain main axis vs cross axis in Flexbox.

    The main axis is the direction items flow — horizontal by default (flex-direction: row), vertical when column. The cross axis is perpendicular. justify-content aligns along the main axis, align-items along the cross axis. Knowing which is which depends on flex-direction.
  • LayoutIntermediate

    What does the fr unit mean in CSS Grid?

    fr = "fraction" of the available space. 1fr 1fr 1fr = three equal columns. 200px 1fr 1fr = a fixed 200px column followed by two flexible columns sharing the rest equally. Combine with minmax() and repeat(auto-fit, minmax(200px, 1fr)) for responsive grids without media queries.
    grid-template-columns:
      repeat(auto-fit, minmax(240px, 1fr));
  • LayoutIntermediate

    What is mobile-first design and how do you write it?

    Write base styles for mobile (smallest screen) first, then layer on enhancements with min-width media queries as the screen grows. This produces less CSS for the most common device, gives a working mobile experience even if media queries fail, and forces you to prioritize content. The opposite (max-width) is "desktop-first" and is generally discouraged.
    .card { padding: 16px; }       /* mobile */
    @media (min-width: 768px) {
      .card { padding: 24px; }     /* tablet+ */
    }
  • CSSIntermediate

    What are CSS custom properties and how do you use them?

    Custom properties (a.k.a. CSS variables) start with -- and are read with var(). Unlike Sass variables, they are live in the DOM, can be changed at runtime via JavaScript, cascade like other properties, and respect the cascade for theming.
    :root {
      --brand: #4f46e5;
      --radius: 10px;
    }
    .btn {
      background: var(--brand);
      border-radius: var(--radius);
    }
    /* Theming with one class */
    .dark { --brand: #818cf8; }
  • CSSIntermediate

    How does z-index actually work?

    z-index only applies to elements with a non-static position (or flex/grid items). Each "stacking context" has its own z-index scale — a child with z-index: 9999 cannot escape a parent with a lower z-index. New stacking contexts are created by position + z-index, transform, opacity < 1, filter, will-change, and a few others.
  • CSSIntermediate

    What is the difference between transitions and animations?

    Transitions animate between two states (start → end), usually triggered by a state change like :hover or a class toggle. Animations use @keyframes to define multi-step sequences with full control over each frame, easing per step, iteration count, direction, and play state. Use transitions for simple state changes, animations for complex or looping motion.
  • PerformanceIntermediate

    Why are transform and opacity considered "cheap" to animate?

    They can be animated on the compositor thread without triggering layout or paint — only compositing. Properties like width, top, margin trigger layout, which is expensive and can cause jank, especially on mobile. Always animate transform (use translate/scale instead of top/left/width) and opacity for smooth 60fps motion.
  • CSSIntermediate

    What is the :has() selector and why is it a big deal?

    :has() is the long-awaited "parent selector". .card:has(img) selects cards that contain an image. form:has(:invalid) styles the entire form when any field is invalid. It enables conditional styling based on descendants without JavaScript. Supported in all modern browsers since 2023.
  • LayoutAdvanced

    What are container queries?

    Container queries let you style elements based on the size of a parent container instead of the viewport. This is huge for component-driven design — a card can adapt its layout based on whether its sidebar slot is wide or narrow, regardless of screen size.
    .parent { container-type: inline-size; }
    @container (min-width: 400px) {
      .card { display: flex; }
    }
  • CSSAdvanced

    What are CSS logical properties?

    Logical properties replace physical directions (left, right, top, bottom) with flow-relative ones (inline-start, inline-end, block-start, block-end). They adapt automatically when the writing mode changes — essential for RTL languages or vertical writing. margin-inline replaces margin-left/right; padding-block replaces padding-top/bottom.
  • PerformanceAdvanced

    What is critical CSS and why does it matter?

    Critical CSS is the minimum CSS needed to render the above-the-fold content. It is inlined in the <head> so the browser can render immediately without waiting for the full stylesheet. The rest of the CSS loads asynchronously. This dramatically improves Largest Contentful Paint (LCP), one of the Core Web Vitals.
  • CSSAdvanced

    How do you avoid CSS specificity wars without using !important?

    Use a flat selector convention (BEM, single classes per component), avoid IDs in selectors, never nest deeply (more than 2–3 levels). For utility frameworks (Tailwind), order matters more than specificity. For variants, use @layer to control cascade order explicitly. As a last resort, :where() adds zero specificity to selectors inside it.
    @layer reset, base, components, utilities;
  • AccessibilityAdvanced

    How do you respect users who prefer reduced motion?

    Check the prefers-reduced-motion media query and disable or simplify animations for users who have enabled the OS-level setting. This helps users with vestibular disorders or who simply find motion distracting.
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
      }
    }
  • AccessibilityIntermediate

    What is ARIA and when should you use it?

    ARIA (Accessible Rich Internet Applications) attributes add semantics for assistive tech when native HTML can't express them — like custom widgets (tabs, modals, tree views). The first rule of ARIA is: don't use ARIA. Always prefer the native semantic element first (<button> over <div role="button">). Only reach for ARIA when no native element fits.
  • AccessibilityBeginner

    How do you write good alt text for images?

    Describe the image's purpose in context. For decorative images, use empty alt="" so screen readers skip them. For informative images, describe what the user would miss without seeing it. For images inside links, the alt should describe where the link goes. Never start with "image of" — screen readers already announce it.
  • AccessibilityIntermediate

    How do you make a page keyboard-navigable?

    Use semantic elements (<button>, <a href>) so they're focusable by default. Provide visible :focus-visible styles. Manage tab order with tabindex="0" (focusable in document order) or -1 (focusable only via JavaScript). For modals, trap focus inside and restore it on close. Skip-links let users jump past nav to main content.
    .btn:focus-visible {
      outline: 2px solid #4f46e5;
      outline-offset: 2px;
    }
  • PerformanceBeginner

    What is image lazy loading?

    Lazy loading defers loading off-screen images until the user scrolls near them, saving bandwidth and improving initial page load. The native attribute loading="lazy" on <img> and <iframe> enables it without any JavaScript. Pair with explicit width and height attributes to prevent layout shift.
    <img src="hero.jpg" alt="..."
         width="800" height="450"
         loading="lazy">
  • PerformanceIntermediate

    What are Core Web Vitals?

    Three metrics Google uses to measure user experience and rank pages: LCP (Largest Contentful Paint, < 2.5s) — loading speed of the main content. INP (Interaction to Next Paint, < 200ms) — responsiveness, replaced FID. CLS (Cumulative Layout Shift, < 0.1) — visual stability, no unexpected jumps.
  • HTMLBeginner

    What is the difference between an HTML element and an HTML tag?

    A tag is the literal markup like <p> or </p>. An element is the complete unit — opening tag, content, and closing tag together (<p>Hello</p>). Tags define the boundaries; elements are the actual things you reason about in the DOM.
  • HTMLBeginner

    What are void (self-closing) elements?

    Void elements have no content and therefore no closing tag. The most common ones are <br>, <hr>, <img>, <input>, <link>, <meta>, <source>, <area>, <base>, <col>, <embed>, <param>, <track>, and <wbr>. In HTML the trailing slash (<img />) is optional; in XHTML/JSX it is required.
    <img src="logo.png" alt="Logo" />
    <br />
    <input type="email" required />
    <meta charset="UTF-8" />
  • HTMLBeginner

    What is the difference between id and class attributes?

    id must be unique within a document and is meant for a single element — typically used for in-page anchors and JavaScript hooks. class is for grouping any number of elements that share styling or behavior. In CSS specificity, #id is 100× stronger than .class, which is why classes are preferred for styling and IDs for unique anchors only.
    <!-- ID: unique, used for anchor + JS lookup -->
    <section id="pricing">…</section>
    
    <!-- Class: shared, used for styling -->
    <button class="btn btn-primary">Buy</button>
    <button class="btn btn-primary">Try free</button>
  • HTMLIntermediate

    Why does the type attribute on <button> matter?

    Inside a <form>, a <button> without an explicit type defaults to type="submit" — which means clicking it submits the form, often refreshing the page. Always set type="button" for non-submit buttons (modals, toggles, JS handlers) to prevent accidental submissions. Use type="reset" for clearing forms, type="submit" for the actual submit action.
    <form>
      <input type="text" name="email" />
      <button type="button" onclick="openHelp()">?</button>  <!-- safe -->
      <button type="reset">Clear</button>
      <button type="submit">Sign up</button>
    </form>
  • HTMLIntermediate

    What is the <picture> element used for?

    <picture> lets the browser choose the best image source from multiple options based on media query, format, or resolution. It is the canonical way to deliver modern formats (AVIF/WebP) with a JPG/PNG fallback, or to serve different art-direction crops on mobile vs desktop. The <img> inside is required as the fallback and where alt text lives.
    <picture>
      <source type="image/avif" srcset="hero.avif" />
      <source type="image/webp" srcset="hero.webp" />
      <source media="(max-width: 600px)" srcset="hero-mobile.jpg" />
      <img src="hero.jpg" alt="Sunset over a coastal town" />
    </picture>
  • HTMLIntermediate

    What are <details> and <summary>?

    Native, JavaScript-free disclosure widget — perfect for FAQs, accordions, and "show more" panels. <summary> is the always-visible heading; the rest of <details> is hidden by default and toggles open on click. Add the open boolean attribute to start expanded. Style the marker with details > summary::marker or hide it entirely.
    <details>
      <summary>How do I cancel my subscription?</summary>
      <p>Go to Settings → Billing → Cancel.</p>
    </details>
    
    <details open>
      <summary>Open by default</summary>
      <p>Useful for the first FAQ entry.</p>
    </details>
  • HTMLIntermediate

    What is the <dialog> element and how does it differ from a <div> modal?

    <dialog> is the native HTML modal. Calling dialog.showModal() opens it on the top layer (above all other content), traps focus, blocks the rest of the page with a ::backdrop pseudo-element, and dismisses on Escape — all without a single line of accessibility-trapping JS. dialog.close() shuts it. A <div> modal needs to manually replicate every one of those behaviors.
    <dialog id="confirm">
      <form method="dialog">
        <p>Delete this project?</p>
        <button value="cancel">Cancel</button>
        <button value="ok">Delete</button>
      </form>
    </dialog>
    
    <script>
      document.getElementById('confirm').showModal();
    </script>
  • HTMLIntermediate

    What are Open Graph (OG) tags?

    Open Graph is a meta-tag protocol Facebook introduced (now used by every major social platform) to control how a URL appears when shared. Without OG tags, the preview is whatever the crawler guesses. With them, you control the title, description, and image. Twitter has its own twitter: variants but falls back to OG when missing.
    <meta property="og:title" content="Instant CSS — Free Visual Tools" />
    <meta property="og:description" content="30+ free CSS generators…" />
    <meta property="og:image" content="https://instantcss.com/og.png" />
    <meta property="og:url" content="https://instantcss.com/" />
    <meta property="og:type" content="website" />
    <meta name="twitter:card" content="summary_large_image" />
  • HTMLAdvanced

    What is the <template> element?

    <template> holds inert markup that the parser recognises but does not render — no images load, no scripts run. You clone its content with JavaScript when you actually need it. It is the standard primitive for client-side templating (React/Vue compile down to similar idioms) and for declarative shadow-DOM in Web Components.
    <template id="card-tpl">
      <article class="card">
        <h3></h3><p></p>
      </article>
    </template>
    
    <script>
      const tpl = document.getElementById('card-tpl');
      const node = tpl.content.cloneNode(true);
      node.querySelector('h3').textContent = title;
      document.body.append(node);
    </script>
  • CSSBeginner

    What are the three ways to add CSS to HTML?

    Inline — the style attribute on a single element (highest specificity, hardest to maintain). Internal — a <style> block in <head> (page-scoped). External — a separate .css file linked with <link rel="stylesheet"> (cacheable, reusable across pages — almost always the right choice). When the same property is set in multiple places, inline wins, then last-loaded external/internal, unless !important is involved.
    <!-- Inline -->
    <p style="color:red">…</p>
    
    <!-- Internal -->
    <style>p { color: red; }</style>
    
    <!-- External (preferred) -->
    <link rel="stylesheet" href="/styles.css" />
  • CSSBeginner

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

    A reset (Eric Meyer's reset is the classic) zeroes out *every* default — margins, paddings, font sizes — so every browser starts from a blank slate. Normalize.css preserves useful browser defaults but smooths over inconsistencies between browsers. Modern projects often write a small custom reset (e.g. Josh Comeau's) that combines the best of both.
    /* Modern mini-reset */
    *, *::before, *::after { box-sizing: border-box; }
    body { margin: 0; line-height: 1.5; -webkit-font-smoothing: antialiased; }
    img, picture, video, svg { display: block; max-width: 100%; }
    input, button, textarea, select { font: inherit; }
  • CSSBeginner

    When should you use !important?

    Almost never. !important overrides every normal rule and breaks the cascade — once you reach for it, future overrides have to use !important too, and the cascade becomes a war. Legitimate uses: utility-first frameworks (Tailwind's !), undoing inline styles you cannot remove, or fixing third-party widgets. Otherwise, fix the specificity instead.
    /* ✗ Sledgehammer */
    .btn { color: red !important; }
    
    /* ✓ Bump specificity instead */
    .card .btn { color: red; }
  • CSSIntermediate

    What does `flex: 1` actually do?

    flex is shorthand for three properties: flex-grow (how much to expand into free space), flex-shrink (how much to give up when crowded), and flex-basis (starting size before grow/shrink). flex: 1 expands to flex: 1 1 0% — grow 1, shrink 1, basis 0 — which makes items share remaining space equally. flex: auto (1 1 auto) factors in content size; flex: none (0 0 auto) is fixed.
    /* Equal columns */
    .col { flex: 1; }                 /* 1 1 0%   */
    
    /* Sized by content, then grows */
    .col { flex: auto; }              /* 1 1 auto */
    
    /* Never grows or shrinks */
    .fixed { flex: none; }            /* 0 0 auto */
    
    /* 200px ideal, can shrink, can't grow */
    .sidebar { flex: 0 1 200px; }
  • CSSIntermediate

    How does `object-fit` work?

    object-fit controls how a replaced element's content (image, video) fits its box when their aspect ratios differ. cover fills the box and crops overflow (most common for hero images). contain shrinks until fully visible, leaving gaps. fill stretches to fit (distorts). none keeps natural size. scale-down picks the smaller of none and contain. Pair with object-position to control the focal point of cropping.
    img.hero {
      width: 100%;
      height: 320px;
      object-fit: cover;
      object-position: center 30%;
    }
  • CSSIntermediate

    Why does my `position: sticky` element not stick?

    The four most common reasons: (1) No top/bottom/left/right offset is set — sticky needs at least one. (2) An ancestor has overflow: hidden/auto/scroll — the sticky element's containing block is that scrolling ancestor, not the viewport. (3) The parent is taller than the sticky element by zero — there is nowhere for it to "stick" within. (4) Inside a flex/grid item without explicit height — the item collapses to the sticky element's height.
    /* ✓ Works: top offset + parent has scroll room */
    header {
      position: sticky;
      top: 0;
      z-index: 50;
    }
    
    /* ✗ Will not stick — overflow on a parent */
    .scroller { overflow-x: auto; }
    .scroller .toolbar { position: sticky; top: 0; }
  • CSSIntermediate

    How do you truncate text with an ellipsis in CSS?

    Single line uses three classic properties together: overflow: hidden, white-space: nowrap, text-overflow: ellipsis. Multi-line uses the WebKit line-clamp trick (now standard in all evergreens) — limits to N visible lines and adds the ellipsis on the last one. CSS line-clamp (without the prefix) is shipping but check support before using it standalone.
    /* Single line */
    .title {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    
    /* 3 lines, then ellipsis */
    .excerpt {
      display: -webkit-box;
      -webkit-line-clamp: 3;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
  • CSSIntermediate

    How does the `aspect-ratio` property work?

    aspect-ratio locks an element's height to a ratio of its width (or vice-versa). Replaces the legacy "padding-bottom hack" — no more padding-bottom: 56.25% for 16:9 video wrappers. Accepts ratios like 16 / 9 or single numbers (1 for square). When both width and height are set explicitly, aspect-ratio is ignored.
    .video-wrapper {
      width: 100%;
      aspect-ratio: 16 / 9;     /* legacy way needed padding-bottom: 56.25% */
    }
    
    .avatar {
      width: 64px;
      aspect-ratio: 1;          /* perfect square */
      border-radius: 50%;
    }
  • CSSAdvanced

    What does the :has() selector do?

    The "parent selector" CSS finally got. :has() matches an element if a child or descendant matches the inner selector. Lets you style a card that contains an image, a form that has invalid inputs, or a label whose checkbox is checked — all without JS or class toggling. Supported in every modern browser since late 2023.
    /* Cards that wrap images get less padding */
    .card:has(> img) { padding: 0; }
    
    /* Submit button dims when any input is invalid */
    form:has(:invalid) [type="submit"] {
      opacity: 0.5;
      pointer-events: none;
    }
    
    /* Label gets blue when its checkbox is checked */
    label:has(input:checked) { color: #2563eb; }
  • CSSAdvanced

    What are CSS cascade layers (@layer)?

    @layer lets you organise rules into named priority groups. Layers declared later win over earlier ones — *regardless of selector specificity inside them*. Solves the perennial "why does my utility class not override the component class?" headache. Typical setup: reset, base, tokens, layout, components, utilities — each group does its job and never accidentally overrides another.
    @layer reset, base, components, utilities;
    
    @layer reset {
      *, *::before, *::after { box-sizing: border-box; }
    }
    
    @layer components {
      .btn { padding: 0.5rem 1rem; background: #4f46e5; color: white; }
    }
    
    @layer utilities {
      .bg-red { background: red; }   /* always wins over .btn */
    }
  • CSSAdvanced

    What is CSS subgrid and when do you use it?

    When a grid item is itself a grid, subgrid makes it inherit the parent's tracks instead of defining its own. Lets nested elements align to the outer grid — for example, three card columns whose titles, images and CTAs line up perfectly across cards even though each card has different content lengths. Without subgrid you'd have to flatten the layout or hand-tune row heights.
    .cards {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: auto 1fr auto;
    }
    
    .card {
      display: grid;
      grid-row: span 3;
      grid-template-rows: subgrid;  /* inherits 3 rows from parent */
    }
    
    .card h3, .card p, .card .cta {
      /* now align across all cards in the row */
    }
  • CSSAdvanced

    What are scroll-driven animations?

    A modern CSS API that ties an animation's progress to scroll position instead of time. Build progress bars, parallax effects, sticky-reveal headers, and "scroll-tells-the-story" landing pages without requestAnimationFrame JS. Two timelines: scroll() (tied to a scroll container) and view() (tied to an element entering/leaving the viewport). Available in Chromium browsers; Safari/Firefox shipping support follows.
    @keyframes progress {
      from { width: 0%; }
      to   { width: 100%; }
    }
    
    .progress-bar {
      animation: progress linear;
      animation-timeline: scroll(root block);
    }
    
    .fade-in {
      animation: fadeIn linear;
      animation-timeline: view();
      animation-range: entry 0% cover 30%;
    }
  • CSSAdvanced

    What are oklch() and color-mix() and why use them?

    oklch() is a perceptually uniform color space — equal numeric changes look like equal visual changes, unlike HSL where bumping lightness by 10% on yellow vs blue produces wildly different perceptual jumps. Ideal for design-token color scales. color-mix() blends two colors in any color space — the modern replacement for SCSS mix() and a clean way to make hover/active variants from a single token.
    :root { --brand: oklch(58% 0.2 264); }
    
    .btn { background: var(--brand); }
    
    /* 20% darker on hover, no extra token needed */
    .btn:hover { background: color-mix(in oklch, var(--brand), black 20%); }
    
    /* Translucent border from the same token */
    .card { border-color: color-mix(in oklch, var(--brand), transparent 70%); }

Test what you've learned

Two free quizzes, 30 questions each. Lock in the concepts and earn a personalized completion certificate.