WGU D276 practice

CSS Display and Positioning: block, inline, static, relative, absolute, fixed, sticky and z-index

Block or inline decides how a box flows; static, relative, absolute, fixed, or sticky decides what its coordinates are measured against. This guide walks through all five position values, the containing block rules that trip people up, and why z-index compares only inside a single stacking context — then gives you six practice questions with full explanations.

What display and position actually control

In CSS, display decides how a box participates in the flow of the page — a block box starts on a new line and takes the full available width, while an inline box flows along a line of text with its neighbors. position is a separate decision: it controls what an element's top, right, bottom, and left offsets are measured against. The five values are static, relative, absolute, fixed, and sticky, and only the last four count as positioned — which is the reason z-index silently does nothing on a default element.

Block vs. inline

Block-level elements like <div>, <p>, and <h2> honor width, height, and margins on all four sides. A non-replaced inline element like <span>, <a>, or <strong> lives inside a line box, so it ignores width, height, and top/bottom margins. Left and right padding and margin still apply. display: inline-block is the middle ground: the box stays on the line with its neighbors but accepts width, height, and vertical margins like a block.

The five position values

ValueStays in normal flow?Offsets are measured from
staticYesNothing — inset properties are ignored
relativeYes (original space is kept)Its own normal-flow position
absoluteNoPadding box of the nearest positioned ancestor
fixedNoThe viewport (continuous media)
stickyYesIts nearest scrolling ancestor, once a threshold is crossed — and never past its own containing block

Two footnotes on that table. For absolute and fixed, an ancestor can also become the containing block without any position at all — a transform, filter, or backdrop-filter other than none is enough, which is covered in the deep dive below. And relative is the most misread of the five: nudging an element with top: 20px moves only its painted box, while the page still reserves the space it would have taken as static, so no sibling shifts. sticky needs a threshold — at least one non-auto inset value on the axis you want it to stick on, such as top: 0. Without one, it behaves on that axis exactly like relative and never sticks.

z-index and stacking contexts

z-index applies to positioned elements and to flex and grid items; on an ordinary static element that is neither, it is ignored. With no z-index at all, positioned elements paint above non-positioned ones, and among positioned siblings the one later in the HTML wins. The real gotcha is the stacking context: a positioned element with any z-index other than auto creates one, and so do opacity below 1, a transform, and isolation: isolate. Inside a stacking context, children are sealed in — the whole subtree is painted as one unit at the parent's level, so a child's z-index: 9999 cannot climb past an element outside it.

Read the full WGU D276 Web Development Foundations study guide for the wider CSS picture, or jump straight into more D276 practice questions. Try the six below first.

Practice: Css Positioning Display

  1. A <div> in normal flow is given position: relative; top: 20px; left: 20px;. What happens to the elements that come after it in the document?

    • They shift up and to the left by 20px to close the gap the div left behind.
    • They stay exactly where they were, because the page still reserves the div's original space.
    • They shift down and to the right by 20px, following the div's movement.
    • They reflow as though the div had been removed from the document entirely.
    Show answer & explanation

    Correct answer: They stay exactly where they were, because the page still reserves the div's original space.. Relative positioning offsets an element visually but does not take it out of normal flow — MDN states the space given for the element in the page layout is the same as if position were static, so no other element moves. The tempting wrong answer is that surrounding content closes the gap; that is what happens with position: absolute or fixed, which are removed from flow, not with relative.

  2. A <span class="badge"> has position: absolute; top: 0; right: 0;. It sits inside <div class="card">, which sits inside <main>. The .card has no position declared and no transform or filter; <main> has position: relative. Which box does the badge position itself against?

    • The padding box of .card, because .card is its direct parent element.
    • The viewport, because absolutely positioned elements are always measured from the viewport.
    • The padding box of <main>, the nearest ancestor whose position is not static.
    • The content box of <body>, since the badge's parent is not positioned.
    Show answer & explanation

    Correct answer: The padding box of <main>, the nearest ancestor whose position is not static.. An absolutely positioned element uses the padding box of the nearest ancestor with a position value other than static as its containing block. Because .card is left at the default static — and has no transform or filter that would make it a containing block anyway — the search continues up to <main>, which is relative. Assuming the direct parent is the reference is the classic mistake, and it is exactly why you add position: relative to a card before pinning a badge inside it.

  3. You write .table-head { position: sticky; } but do not set top, bottom, left, or right. What does the element do when you scroll?

    • It sticks to the top of the scrolling container, because top: 0 is assumed by default.
    • It is removed from normal flow and pinned to the viewport like a fixed element.
    • The declaration is invalid, so the element falls back to static and collapses to zero height.
    • It behaves just like position: relative and never sticks to anything.
    Show answer & explanation

    Correct answer: It behaves just like position: relative and never sticks to anything.. Sticky positioning requires at least one inset property set to a non-auto value on the axis you want it to stick on; MDN is explicit that if both inset properties for an axis are auto, sticky behaves as relative on that axis. Nothing defaults to top: 0 — that is the assumption that sends people hunting for a JavaScript bug when the fix is one missing line of CSS. The declaration is perfectly valid, so the element keeps its normal size and its space in flow.

  4. Inside an ordinary block container (no flexbox or grid anywhere), an element styled only with .overlay { z-index: 9999; background: white; } still paints behind a sibling that has position: relative. What is the actual reason?

    • The overlay's position is static, and in a block container z-index only affects positioned elements.
    • The z-index value is too large, so the browser clamps it back to auto.
    • z-index is working, but relatively positioned elements always paint above everything else no matter what z-index says.
    • You must also declare opacity: 1 on the overlay to create a stacking context before z-index takes effect.
    Show answer & explanation

    Correct answer: The overlay's position is static, and in a block container z-index only affects positioned elements.. z-index has no effect on an element whose position is static unless it is a flex or grid item, and the stem rules that out; MDN lists z-index as applying to positioned elements. Giving the overlay position: relative (or absolute) makes the 9999 meaningful. Option three is wrong because a relatively positioned sibling would lose to another positioned element with a higher z-index — it only wins here because the overlay is not competing at all.

  5. Two sibling <div>s are both position: relative. #panelA has z-index: 5. #panelB has z-index: 4 and contains #tooltip, which is position: absolute; z-index: 99. Where does the tooltip paint?

    • Above #panelA, because 99 is greater than 5 and z-index values are compared across the whole document.
    • Below #panelA, because #panelB forms a stacking context and paints as a single unit at level 4.
    • Above #panelA, because absolutely positioned elements always escape their ancestors' stacking contexts.
    • Below #panelA, because a child element can never paint above anything outside its own parent.
    Show answer & explanation

    Correct answer: Below #panelA, because #panelB forms a stacking context and paints as a single unit at level 4.. A positioned element with a z-index other than auto creates a stacking context, so #panelB's entire subtree is painted atomically at z-index 4 — the tooltip's 99 only orders it against its siblings inside #panelB. The last option lands on the right side of #panelA by false reasoning: children escape their ancestors' layer all the time, and if #panelB had z-index: auto it would create no stacking context and the tooltip could then paint above #panelA.

  6. You write nav a { width: 120px; height: 40px; margin-top: 12px; } but the links keep hugging their text and the top margin does nothing. What explains this?

    • Your rule loses to the browser's user-agent stylesheet, so it needs !important to take effect.
    • Anchors are replaced elements, so they ignore the CSS box model entirely.
    • width and height are only honored once you also set box-sizing: border-box.
    • <a> defaults to display: inline, and non-replaced inline boxes ignore width, height, and vertical margins.
    Show answer & explanation

    Correct answer: <a> defaults to display: inline, and non-replaced inline boxes ignore width, height, and vertical margins.. An inline box is sized by its content within a line box, so width, height, and top/bottom margins do not apply — switching to display: inline-block or display: block makes all of them work. box-sizing is a red herring: it changes how width is measured, not whether width applies at all, so it cannot rescue an inline element. Anchors are not replaced elements; images and form controls are.

A worked example: card, badge, and sticky header

Picture a product card with a "Sale" badge in the corner, inside a page with a header that should stick while you scroll. Here is the shape of it:

.card   { position: relative; padding: 1rem; }
.badge  { position: absolute; top: 8px; right: 8px; }
.site-header { position: sticky; top: 0; z-index: 10; }

Three separate decisions are doing the work. The .card is given relative purely so it becomes a containing block — it is not offset at all, and that is the most common legitimate use of relative in real code. The .badge then measures from the card's padding box, so top: 8px is 8px inside the padding edge, not inside the content. The header keeps its space in flow and pins once the scroll position reaches its top: 0 threshold.

Mistakes people actually make

  • Forgetting the anchor. An absolutely positioned child with no positioned ancestor falls all the way back to the initial containing block, and usually lands in the top corner of the page instead of inside its card.
  • A sticky element inside a container with overflow: hidden, scroll, or auto. MDN notes that a sticky element sticks to its nearest ancestor with a scrolling mechanism even when that ancestor is not the thing actually scrolling — so the element appears to do nothing. This is one of the most common reasons "sticky is broken," alongside a parent that is no taller than the sticky element itself.
  • Escalating z-index. When a modal will not cover a dropdown, bumping it to 999999 almost never helps. Find the ancestor that created a stacking context — often an opacity: 0.99, a transform, or a nearby z-index — and fix the layer boundary instead.
  • Expecting vertical padding on inline elements to move things. Padding on a <span> does render, but it overlaps the lines above and below instead of pushing them apart. Use inline-block when you need the space.

How to reason about the tricky cases

When something is in the wrong place, ask what is my containing block? Walk up the DOM until you hit an ancestor with a non-static position. For absolute and fixed elements, MDN also lists ancestor properties that form a containing block on their own: a filter, backdrop-filter, transform, perspective, rotate, scale, or translate other than none; a contain value of layout, paint, strict, or content; a qualifying will-change; and content-visibility: auto. That is why a position: fixed element inside a transformed parent stops tracking the viewport and starts tracking that parent. MDN's containing block reference lists every trigger.

When something is on the wrong layer, ask are these two elements even in the same stacking context? If they are not, their z-index numbers were never being compared in the first place. Reading the tree from the root down, one context at a time, turns almost every layering mystery into an obvious answer.

Want someone to walk you through this?

Book 1-on-1 prep for WGU D276 — original coaching, never exam content.

Stuck on this topic? WhatsApp us on +1 646 980 4914.

Working through the whole course? Read the full WGU D276 study guide, or see every WGU D276 practice topic.

More WGU D276 practice

Html Document Structure

The five lines at the top of every HTML file are not decoration. Here is what the doctype, the html/head/body split, meta charset, and the viewport tag each do — why the browser misbehaves when you leave one out, and how to reason about the cases that trip people up.

Semantic Structure Tags

Semantic structure tags describe what a block of content is, not how it looks. This lesson explains the difference between article, section, aside, main, nav, header and footer — including the syndication test that settles article vs. section, the strict placement rules for main, and how header and footer change meaning depending on where they sit — then gives you practice questions with worked explanations.

Headings Text Links Lists

Heading elements rank content instead of sizing it, strong and em carry meaning that b and i do not, a fragment link points at an element's id, and ul, ol, and dl each describe a different kind of grouping. Work through how each one behaves, then test yourself on the cases people actually get wrong.

Images And Alt Text

An image starts with one element and one honest description. From there, srcset, sizes, and picture answer a single question: which file should the browser download on this screen? This guide walks through alt text, figure and figcaption, resolution switching, and art direction, then gives you six practice questions with full explanations.

Html5 Audio And Video

The audio and video elements embed media without a plugin. Learn how the browser chooses among source children, which MIME types to use for MP4, WebM, and MP3, what controls and preload actually do, and why fallback content between the tags is not an error message. Includes practice questions with full explanations.

Html Tables

A plain-English walkthrough of HTML table markup for WGU D276: how table, caption, thead, tbody, tr, th and td nest, what the scope attribute actually does for assistive technology, and how colspan and rowspan reshape the grid — plus practice questions with worked explanations.