pencils ready ✎

HTML & CSS MCQs multiple-choice questions with answers & explanations

All 28 HTML & CSS quiz questions on one page. Pick an answer in your head, then open Show answer to check it and read why. Want a score and a timer? Take them as a quiz instead.

  1. 1.

    How wide is .card on screen, measured from the outer edges of its border?

    easy
    .card {
      box-sizing: content-box;
      width: 200px;
      padding: 20px;
      border: 5px solid;
      margin: 10px;
    }
    1. A200px
    2. B240px
    3. C250px
    4. D270px
    Show answer

    Answer: C (250px)

    With content-box, width sets only the content area, so padding (2 × 20px) and border (2 × 5px) are added on top: 200 + 40 + 10 = 250px. Margin lies outside the border, so 270px is wrong. With box-sizing: border-box the box would be exactly 200px.

  2. 2.

    What are the computed font sizes of .child and .label?

    easy
    html { font-size: 16px; }
    .parent { font-size: 20px; }
    .child { font-size: 1.5em; }   /* inside .parent */
    .label { font-size: 1.5rem; }  /* inside .child */
    1. A24px and 24px
    2. B30px and 45px
    3. C24px and 36px
    4. D30px and 24px
    Show answer

    Answer: D (30px and 24px)

    For font-size, em is relative to the parent's font size, so .child is 1.5 × 20 = 30px, and nested em values compound. rem is always relative to the root (html) font size, so .label is 1.5 × 16 = 24px however deeply it is nested.

  3. 3.

    How much vertical space separates the two paragraphs?

    mid
    .first { margin-bottom: 20px; }
    .second { margin-top: 30px; }
    /* .first and .second are adjacent <p> siblings in a normal block container */
    1. A50px
    2. B30px
    3. C20px
    4. D25px
    Show answer

    Answer: B (30px)

    Adjacent vertical margins of block-level boxes in normal flow collapse into one margin the size of the larger, so the gap is 30px, not 50px. Margins never collapse horizontally, and they do not collapse between flex or grid items.

  4. 4.

    The link is being hovered. What color is it?

    mid
    /* <nav id="sidebar" class="nav"><ul class="menu"><li><a href="#">Home</a></li></ul></nav> */
    #sidebar a { color: red; }
    .nav .menu li a:hover { color: blue; }
    1. Ablue, because the second rule has more selectors
    2. Bblue, because it comes later in the stylesheet
    3. Cred, because one ID outranks any number of classes and pseudo-classes
    4. DIt depends on the browser
    Show answer

    Answer: C (red, because one ID outranks any number of classes and pseudo-classes)

    Specificity is compared column by column: #sidebar a is (1,0,1) and .nav .menu li a:hover is (0,3,2). The ID column decides first, so red wins even though the blue rule has more parts and comes later. Source order only breaks exact ties.

  5. 5.

    What color is the paragraph text?

    mid
    <style>
      p { color: red !important; }
    </style>
    <p style="color: blue">Hello</p>
    1. Ablue, because inline styles always win
    2. BWhichever declaration the browser parses last
    3. Cblue, because inline styles have the highest specificity
    4. Dred, because an !important declaration beats a normal inline one
    Show answer

    Answer: D (red, because an !important declaration beats a normal inline one)

    The cascade checks importance before it looks at the style attribute or specificity, so an author !important rule beats every normal author declaration, inline styles included. Only an inline declaration that is itself !important would win back, which is why !important in shared CSS is so hard to override.

  6. 6.

    What does flex: 1 expand to?

    mid
    1. Aflex: 1 1 auto
    2. Bflex: 1 0 0%
    3. Cflex: 1 1 0%
    4. Dflex: 0 1 auto
    Show answer

    Answer: C (flex: 1 1 0%)

    A single unitless number sets flex-grow, keeps flex-shrink: 1 and sets flex-basis to zero (browsers report 0%). Because the basis is zero, items with flex: 1 split the space equally regardless of their content. flex: auto is 1 1 auto, and the initial value is 0 1 auto.

  7. 7.

    Assuming short content in each cell, how wide are the three columns?

    mid
    .grid {
      display: grid;
      width: 800px;
      grid-template-columns: 200px 1fr 2fr;
      column-gap: 30px;
    }
    1. A200px 200px 400px
    2. B200px 180px 360px
    3. C200px 300px 300px
    4. D266px 266px 266px
    Show answer

    Answer: B (200px 180px 360px)

    fr units share the space left after fixed tracks and gaps: 800 − 200 − 2 × 30 = 540px, split into 3 fractions of 180px, so the columns are 200px, 180px and 360px. Forgetting the gaps gives 200/200/400. With long unbreakable content, a 1fr track (really minmax(auto, 1fr)) can grow beyond its share.

  8. 8.

    An element has position: absolute; top: 0; left: 0. What is it positioned relative to?

    easy
    1. AIts parent element, always
    2. BThe nearest ancestor whose position is not static, or the initial containing block if there is none
    3. CThe viewport, always
    4. DThe nearest ancestor with display: block
    Show answer

    Answer: B (The nearest ancestor whose position is not static, or the initial containing block if there is none)

    An absolutely positioned element is placed against the padding box of its containing block: the nearest positioned ancestor (relative, absolute, fixed or sticky). Ancestors with a transform or filter also qualify. With none, it falls back to the initial containing block. That is why you put position: relative on the parent you want to anchor to.

  9. 9.

    A header with position: sticky; top: 0 scrolls away with the page instead of sticking. What is the most likely cause?

    mid
    1. AAn ancestor has overflow: hidden, so the header sticks inside that box, which never scrolls
    2. BThe header has no z-index
    3. CIts parent uses display: flex
    4. DIts parent needs position: relative
    Show answer

    Answer: A (An ancestor has overflow: hidden, so the header sticks inside that box, which never scrolls)

    A sticky element sticks relative to its nearest ancestor with a scrolling mechanism, which overflow: hidden, auto or scroll all create. If that ancestor is not the box that actually scrolls, the header never sticks. overflow: clip clips without creating a scroll container. Sticky also needs a threshold like top: 0 and room to move inside its parent.

  10. 10.

    Which statement about visibility: hidden is true?

    easy
    1. AIt removes the element from the layout, like display: none
    2. BIt behaves exactly like opacity: 0
    3. CThe element can still receive keyboard focus
    4. DIt keeps the element's space in the layout but hides it from sight and from screen readers
    Show answer

    Answer: D (It keeps the element's space in the layout but hides it from sight and from screen readers)

    visibility: hidden still takes up space, but the element is not painted, cannot be clicked or focused, and is removed from the accessibility tree. display: none also removes it from layout. opacity: 0 is the odd one out: invisible, but still clickable, focusable and announced. Children can opt back in with visibility: visible.

  11. 11.

    Why is a <button> preferred over a <div> with a click handler for a clickable control?

    easy
    1. AA <div> cannot receive click events
    2. BClick events on a <div> do not bubble
    3. C<button> is focusable, activates with Enter and Space, and is announced as a button, with no extra code
    4. D<button> elements render faster than <div> elements
    Show answer

    Answer: C (<button> is focusable, activates with Enter and Space, and is announced as a button, with no extra code)

    A <div> gets clicks just fine, but it is not in the tab order, ignores the keyboard and has no role, so keyboard and screen-reader users cannot operate it. Rebuilding a button takes role="button", tabindex="0" and Enter/Space key handlers; the native element gives you all of that for free.

  12. 12.

    Clicking the label does not focus the input, and screen readers announce the field without a label. Why?

    easy
    <label for="email">Email</label>
    <input type="email" name="email" />
    1. Afor matches an element's id, and this input only has a name
    2. BA <label> must wrap its input to be associated with it
    3. Ctype="email" inputs cannot be labelled
    4. DThe input also needs an aria-label
    Show answer

    Answer: A (for matches an element's id, and this input only has a name)

    A <label for="x"> is associated with the element whose id is x; name is only used when the form is submitted. Add id="email" to the input, or wrap the input inside the label for implicit association. Adding aria-label on top of a working label is redundant.

  13. 13.

    What is the right alt value for a purely decorative image?

    easy
    1. ALeave out the alt attribute
    2. Balt="image"
    3. Calt=""
    4. Dalt="decorative"
    Show answer

    Answer: C (alt="")

    An empty alt="" tells assistive technology to skip the image. Leaving alt out is worse, because many screen readers then read out the file name. Words like "image" or "decorative" are just noise, since the screen reader already announces it as an image.

  14. 14.

    What does aria-hidden="true" on a container do?

    mid
    1. AIt hides the container visually
    2. BIt removes the container and its children from the accessibility tree, but focusable children can still be reached with Tab
    3. CIt removes its children from the tab order
    4. DIt is equivalent to display: none
    Show answer

    Answer: B (It removes the container and its children from the accessibility tree, but focusable children can still be reached with Tab)

    aria-hidden only affects the accessibility tree; nothing changes visually or for the keyboard. A button inside can still receive Tab focus, and screen-reader users then land on something announced as nothing. To hide a region from everyone use hidden or display: none; to keep it visible but non-interactive use the inert attribute.

  15. 15.

    Which of these properties is inherited by child elements by default?

    easy
    1. Amargin
    2. Bcolor
    3. Cborder
    4. Dbackground-color
    5. Epadding
    Show answer

    Answer: B (color)

    Text-related properties inherit: color, the font-* properties, line-height, text-align, visibility and cursor. Box properties such as margin, padding, border and background-color do not. A child often seems to share its parent's background only because its own background-color is transparent.

  16. 16.

    Which declaration is required for a ::before pseudo-element to be generated at all?

    easy
    1. Acontent
    2. Bdisplay: block
    3. Cposition: absolute
    4. Dz-index
    Show answer

    Answer: A (content)

    Without content, its computed value is none and no ::before or ::after box is created, whatever else you set. For purely decorative shapes use content: ''. The generated box is inline by default, so it also needs display: inline-block or block before width and height apply.

  17. 17.

    Which paragraph turns red?

    mid
    <style>
      .post p:nth-child(2) { color: red; }
    </style>
    <div class="post">
      <h2>Title</h2>
      <p>First</p>
      <p>Second</p>
    </div>
    1. AThe "Second" paragraph
    2. BNeither paragraph
    3. CThe "First" paragraph
    4. DBoth paragraphs
    Show answer

    Answer: C (The "First" paragraph)

    :nth-child(2) counts all siblings regardless of type, then checks the rest of the selector. The second child of .post is the "First" paragraph, and it is a p, so it matches. To select the second p, use p:nth-of-type(2), or :nth-child(2 of p) in modern browsers.

  18. 18.

    What color is the paragraph?

    hard
    /* <div class="content"><p>Text</p></div> */
    :is(#main, .content) p { color: red; }
    :where(#main, .content) p { color: blue; }
    .content p { color: green; }
    1. Ared, because :is() takes the specificity of its most specific argument
    2. Bblue, because :where() rules override :is() rules
    3. Cgreen, because .content p comes last and matches through a class
    4. Dgreen, because all three rules tie and the last one wins
    Show answer

    Answer: A (red, because :is() takes the specificity of its most specific argument)

    The specificity of :is() is that of its most specific argument, #main, even though this element matched through .content, so the first rule is (1,0,1). :where() always contributes zero, so the second rule is (0,0,1), and .content p is (0,1,1). Red wins. :not() and :has() count specificity the same way as :is().

  19. 19.

    A flex item with flex: 1 contains a long unbreakable string and overflows its container instead of shrinking. What is the usual fix?

    hard
    1. ASet flex-shrink: 1 on the item
    2. BSet flex-basis: 0 on the item
    3. CSet width: 100% on the container
    4. DSet min-width: 0 (or overflow: hidden) on the item
    Show answer

    Answer: D (Set min-width: 0 (or overflow: hidden) on the item)

    Flex items default to min-width: auto, which stops them shrinking below their min-content width, here the width of the long string. flex: 1 already includes flex-shrink: 1 and a zero basis, so neither of those helps. min-width: 0 removes the floor, and so does making the item a scroll container with overflow: hidden. Then you can clip or truncate the text inside it.

  20. 20.

    How much top padding does .child get?

    hard
    .parent { width: 400px; height: 100px; }
    .child { padding-top: 50%; } /* .child is inside .parent */
    1. A50px
    2. B200px
    3. C0, because the child has no height
    4. DIt depends on the content
    Show answer

    Answer: B (200px)

    Percentage padding and margin, vertical ones included, resolve against the containing block's width (its inline size), not its height. So 50% of 400px is 200px. The old padding trick for fixed aspect-ratio boxes relied on this; today you would use aspect-ratio.

  21. 21.

    At a viewport width of 800px, what is the font size of .title?

    mid
    .title { font-size: 16px; }
    @media (min-width: 600px) { .title { font-size: 24px; } }
    @media (min-width: 400px) { .title { font-size: 20px; } }
    1. A16px
    2. B24px
    3. C20px
    Show answer

    Answer: C (20px)

    Both media queries match at 800px, and a media query adds no specificity, so the two rules tie and the later one wins: 20px. With mobile-first min-width queries, order them from the smallest breakpoint to the largest so the widest match comes last.

  22. 22.

    Where .modal and the header overlap, which one is painted on top?

    hard
    <div class="wrapper" style="position: relative; z-index: 1">
      <div class="modal" style="position: fixed; z-index: 9999"></div>
    </div>
    <header style="position: relative; z-index: 2"></header>
    1. A.modal, because 9999 is the highest z-index
    2. BThe header, because .modal is confined to the stacking context of .wrapper
    3. C.modal, because position: fixed escapes its ancestors
    4. DWhichever comes later in the DOM
    Show answer

    Answer: B (The header, because .modal is confined to the stacking context of .wrapper)

    .wrapper is positioned with z-index: 1, so it forms a stacking context. .modal is stacked inside it, and the wrapper as a whole is compared with the header: 1 against 2. position: fixed changes how the modal is positioned, not which stacking context it belongs to. Render the modal outside the wrapper (a portal), or use the top layer with dialog.showModal().

  23. 23.

    Which declaration does NOT create a new stacking context on its own?

    hard
    1. Aopacity: 0.9
    2. Btransform: translateZ(0)
    3. Cposition: relative (with z-index: auto)
    4. Disolation: isolate
    5. Eposition: fixed
    Show answer

    Answer: C (position: relative (with z-index: auto))

    A relatively positioned element forms a stacking context only once it has a z-index other than auto. opacity below 1, any transform, isolation: isolate and position: fixed or sticky create one immediately, which is why adding an innocent-looking transform can suddenly trap a child that has a high z-index.

  24. 24.

    Two scripts need the parsed DOM, and b.js depends on a.js. Which option loads them without blocking the HTML parser and runs them in order?

    mid
    1. Aasync on both script tags
    2. BPlain script tags at the top of the head
    3. Casync on a.js and defer on b.js
    4. Ddefer on both script tags
    Show answer

    Answer: D (defer on both script tags)

    defer scripts download in parallel with parsing and run in document order once parsing finishes, just before DOMContentLoaded. async scripts run as soon as each one arrives, in any order and possibly mid-parse, so they suit independent scripts like analytics. Plain scripts in the head block the parser. Module scripts (type="module") are deferred by default.

  25. 25.

    A web font is referenced only inside a CSS file, so the browser discovers it late. Which tag fetches it early for the current page?

    mid
    1. A<link rel="prefetch" href="/font.woff2">
    2. B<link rel="dns-prefetch" href="https://fonts.example">
    3. C<link rel="preconnect" href="https://fonts.example">
    4. D<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>
    Show answer

    Answer: D (<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>)

    preload requests a high-priority fetch of a resource the current page will need. as="font" sets the right priority and request type, and crossorigin is required because fonts are always fetched in CORS mode, even from your own origin. prefetch is a low-priority hint for future navigations, and dns-prefetch and preconnect only warm up the connection.

  26. 26.

    Images push content down as they load, causing layout shift. What is the simplest fix?

    mid
    1. ASet width and height attributes on each img so the browser can reserve space from the aspect ratio
    2. BAdd loading="lazy" to every image
    3. CConvert the images to WebP
    4. DGive the images display: block
    Show answer

    Answer: A (Set width and height attributes on each img so the browser can reserve space from the aspect ratio)

    Browsers use the width and height attributes to compute an aspect-ratio before the file arrives, so with CSS like width: 100%; height: auto the box already has the right size and nothing shifts. Lazy loading and smaller formats help loading speed but not Cumulative Layout Shift. For other containers, CSS aspect-ratio does the same job.

  27. 27.

    Which change is most likely to make Largest Contentful Paint (LCP) worse?

    hard
    1. AAdding loading="lazy" to the above-the-fold hero image
    2. BAdding fetchpriority="high" to the hero image
    3. CServing the hero image as AVIF
    4. DPreloading the hero image
    Show answer

    Answer: A (Adding loading="lazy" to the above-the-fold hero image)

    Lazy images are not requested until layout shows they are near the viewport, so a lazy hero image starts downloading late and LCP suffers. Load above-the-fold images eagerly, ideally with fetchpriority="high" or a preload, and keep loading="lazy" for images further down the page. A smaller format such as AVIF usually helps.

  28. 28.

    Which property is usually cheapest to animate for smooth 60 fps motion?

    hard
    1. Aleft
    2. Bwidth
    3. Ctransform
    4. Dmargin-left
    Show answer

    Answer: C (transform)

    Changing left, width or margin-left changes geometry, so every frame re-runs layout and paint. transform (like opacity) can be applied by the compositor to an already-painted layer, often off the main thread, so it stays smooth even when JavaScript is busy. Animate transform: translateX() instead of left.

esc