AD JB Toolbox 01 EN

CSS Tutorial / CSS position: relative, absolute, fixed, and sticky

The position property changes how a box is positioned and how it participates in normal flow. relative retains its original space, absolute and fixed leave the flow, and sticky combines normal-flow placement with constrained sticking during scrolling.

Compare positioning modes with static

value Original space of normal flow Position and scroll criteria
static maintain General flow. Offsets such as top·left are not applied
relative maintain Move by an offset from the original placement location
absolute not occupied Usually the containing block of the nearest positioned ancestor.
fixed not occupied Normal viewport. Some ancestral properties may change criteria
sticky maintain Boundaries of nearby scroll mechanism ancestors and containing blocks

Normal flow is the layout in which elements occupy space according to the document's formatting rules. Text following an absolutely positioned element does not automatically move aside for it. When an element leaves the flow, following content can occupy its former space. Prevent overlap through the layout structure or appropriate padding. Compare positioning with CSS display: Block, Inline, inline-block, and Hiding to understand this difference.

Offsets depend on the positioning mode. With relative positioning, top: 16px shifts the box 16px down from its original position. With absolute positioning, top measures from its containing-block reference. The same number therefore represents different positioning relationships. See MDN: position.

Keep the original space with relative

relative does not re-populate the placement of other elements. Even if you move one card down a little, the original starting position of the next card is maintained. So it may overlap elements below or show empty space above. If the purpose is to change the spacing of the entire document, first check whether the margin, padding, and gap are appropriate rather than the relative top.

Another use of relative is to create an absolute positioning reference for children. If you only write position: relative to the parent and do not specify an offset, the parent itself will not move and will become the basis for the child badge. Specifying a position does not immediately mean that all elements overlap or fall out of the document flow.

Find the containing block for absolute

Absolute elements are usually positioned relative to their nearest non-static ancestor. If you give relative to the card and absolute·top·right to the child, it becomes a badge inside the card. If there is no corresponding ancestor, a criterion further outside is used, which may cause the badge to move towards the page rather than the card. There are times when you create a block that also includes properties such as transform, so you shouldn't just find the position declaration and end it.

A parent with only absolute children does not add the height of its children to the content height in the normal flow. Issues where the parent appears to have zero height or borders are collapsed can occur even though the children are visible. If the content needs to naturally determine the height of the parent, it is easier to manage it by placing the children in the flow and making only the small overlapping badges absolute.

Compare normal flow and an absolute badge

Save the code below as position-flow.html. The three sections are composed of the front element, target, and back element in the same HTML order. The 12px of the card badge is the distance to the standard area of the card, and the top padding is secured so that it does not overlap with the body of the card.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>position-flow.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.flow { border: 2px dashed #789; margin-bottom: 40px; margin-right: 24px; }
 .flow > div { height: 56px; padding: 12px; background: #e8f5de; }
 .flow .target { background: #dceefa; }
 .relative .target { position: relative; top: 16px; left: 20px; }
 .absolute { position: relative; }
 .absolute .target { position: absolute; top: 16px; left: 20px; }
 .card { position: relative; padding: 64px 20px 20px; background: #dceefa; max-width: 600px; }
 .badge { position: absolute; top: 12px; right: 12px; padding: 4px 12px; background: #ffe4b5; }
  </style>
</head>
<body>
<h1>Does the original space remain?</h1>
<h2>static</h2><div class="flow static"><div>Front element</div><div class="target">Target</div><div class="after">Back element</div></div>
<h2>relative</h2><div class="flow relative"><div>Front element</div><div class="target">Target</div><div class="after">Back element</div></div>
<h2>absolute</h2><div class="flow absolute"><div>Front element</div><div class="target">Target</div><div class="after">Back element</div></div>
<h2>Badge inside the card</h2><div class="card"><span class="badge">News</span><p>The badge sits at the top right of the card. Top padding separates it from the text.</p></div>
</body>
</html>
  1. Compares the position of the following element in the static and relative sections. Even if the relative target is moved down by 16px, the placement space for the rear element is maintained relative to the original target position. Confirm by changing only the top to 0 and then restore it to 16px.
  2. An absolute section takes the target out of the flow and places the following element immediately after the preceding element. If you change the position of .absolute .target to static, the parent height will increase by the target height. After comparison, restore to absolute.
  3. Try deleting only the position: relative of .card from the card badge. After confirming that the badge is no longer anchored to the top right corner of the card, restore it immediately. Other conditions do not change.
  4. Elongate the letters on the badge and check the spacing between them and the main text. absolute does not automatically push out the body, so if your badge can be multiple lines, you should consider whether fixed padding alone is sufficient. After practice, return to the original letters.

Distinguish fixed and sticky scrolling

fixed is usually anchored to the viewport, maintaining its position on the screen even when the document is scrolled. It can be used for small operating elements, such as the top button at the bottom right of the screen. It doesn't take up space in the flow, so if you have a sticky bar, make sure to leave enough space so it doesn't obscure the end of the body text and the focus object.

An ancestor's transform can establish the containing block for a fixed descendant, replacing the usual viewport reference. If a fixed element moves with a particular box, inspect ancestor properties such as transform and filter. This example excludes those properties to demonstrate viewport positioning.

Sticky requires a non-auto boundary value such as top on the axis to observe the sticky effect. The title is not fixed on the screen from the beginning, but rather stays in its own flow position and is attached when it reaches the upper border by scrolling. When it reaches the end of its parent, it moves along its limits and doesn't continue to float above the next section.

sticky is influenced by its close scroll mechanism ancestors. Overflow: Not only auto·scroll but also hidden ancestors can affect the standard. If the actual scrolling area is different from the expected ancestor, or the height of the container and title are similar and there is no room for movement, the sticking action may not be visible. Rather than just removing the overflow, first check which elements are scroll-based.

Observe sticky start and parent limits

Save the example as position-scroll.html. A lead-in area at least 320px high keeps the sticky heading below the initial viewport top. The chapter and the following section have enough height to observe when sticking begins and when the parent boundary releases it.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>position-scroll.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
body { margin: 0; padding-bottom: 80px; }
 .intro { min-height: 320px; padding: 24px; background: #eef2f6; }
 .chapter { min-height: 760px; background: #e8f5de; }
 .sticky { position: sticky; top: 0; margin: 0; padding: 16px; background: #dceefa; border-bottom: 2px solid #789; }
 .chapter p { padding: 16px; }
 .tail { min-height: 900px; padding: 24px; background: #fff2df; }
 .fixed { position: fixed; right: 16px; bottom: 16px; padding: 12px; background: #fff; border: 2px solid #145f8f; }
  </style>
</head>
<body>
<div class="intro" id="top"><h1>A heading that sticks while scrolling</h1><p>The heading below starts in normal flow. It sticks when it reaches the top of the screen and remains within its parent at the end of the chapter.</p></div>
<section class="chapter"><h2 class="sticky">Chapter heading</h2><p>This content is inside the chapter. The extra height lets you observe how long its heading remains sticky.</p></section>
<section class="tail"><h2>Another section</h2><p>Check whether the previous chapter's heading stays above this section.</p></section>
<a class="fixed" href="#top">Back to top</a>
</body>
</html>
  1. Before scrolling, make sure the title is below the introductory area. Lower it slowly so that the title sticks in place when it reaches the top of the screen. The top link in the bottom right is in the same screen location from the beginning.
  2. Scroll through the chapter and go down to another area. sticky titles are pushed to the end of the parent chapter, but fixed links remain visible. Click the link to return to the introduction area.
  3. If you change only the top of .sticky to auto, there will be no border on the vertical axis and it will scroll like a normal flow. After confirmation, restore to 0.
  4. Just add overflow: hidden to your .chapter to see sticky results in window scrolling when the nearest scroll mechanism ancestor is changed. After comparing, remove the added declaration.

Diagnose unexpected positioning

If the stacking order does not change even after specifying the position, check the CSS z-index and Stacking Contexts.

  1. First, check if there is space left. The placement of surrounding elements varies depending on whether they are relative/sticky or absolute/fixed.
  2. Check the actual position and top·right·bottom·left applied values in the developer tools. Also check which rules and media queries take precedence.
  3. absolute checks for the base ancestor, and fixed checks for the ancestor property that changes the containing block. sticky checks boundary, scroll ancestor, parent height and movement margin.
  4. If the coordinates are correct but are obscured, distinguish between a location problem and an overlap order/overflow truncation. A large z-index does not solve all occlusions.
More in This Category
CSS Tutorial / Build a Responsive Website with HTML and CSS

CSS Tutorial / Build a Responsive Website with HTML and CSS

Create a complete two-file learning website with responsive cards and navigation, then test long text, keyboard focus, zoom, and reduced motion.

CSS Tutorial / CSS Form States: Focus, Validation, disabled, and readonly

CSS Tutorial / CSS Form States: Focus, Validation, disabled, and readonly

Compare form states, create accessible labels and error messages, and inspect which enabled, disabled, and read-only fields enter submitted form data.

CSS Tutorial / Organize CSS with Shared Styles, Nesting, and Layers

CSS Tutorial / Organize CSS with Shared Styles, Nesting, and Layers

Refactor a small stylesheet without changing its layout, compare nesting and cascade layers, and check relative file paths and selector specificity.

CSS Tutorial / CSS Grid: repeat, auto-fit, auto-fill, and Areas

CSS Tutorial / CSS Grid: repeat, auto-fit, auto-fill, and Areas

Compare auto-fit and auto-fill, test minimum track sizes and long text, and use named areas without confusing visual placement with reading order.

CSS Tutorial / CSS Paragraph and List Styling

CSS Tutorial / CSS Paragraph and List Styling

Style paragraphs and ordered or unordered lists, compare inside and outside markers, and check spacing and wrapped text on narrow screens.

CSS Tutorial / CSS Combinators and Pseudo-Classes

CSS Tutorial / CSS Combinators and Pseudo-Classes

Compare descendant, child, and sibling selectors, then test hover, focus, and child-position conditions in a complete example.

CSS Tutorial / Inspect CSS with DevTools: Styles and Computed

CSS Tutorial / Inspect CSS with DevTools: Styles and Computed

Use Styles, Computed, and the box model display to diagnose CSS, compare temporary edits, and transfer a confirmed change to the correct source file.

CSS Tutorial / CSS Background Colors and Images: cover and contain

CSS Tutorial / CSS Background Colors and Images: cover and contain

Create and load a local background image, compare repetition, cover, contain, and position, and diagnose image-path and cropping problems.

CSS Tutorial / The CSS Box Model: Content, Padding, Border, and Margin

CSS Tutorial / The CSS Box Model: Content, Padding, Border, and Margin

Measure the four box areas, compare padding shorthand and vertical margin collapse, and inspect the resulting dimensions in DevTools.

CSS Tutorial / Responsive Images and Video: aspect-ratio and object-fit

CSS Tutorial / Responsive Images and Video: aspect-ratio and object-fit

Compare original image proportions, cover, contain, and object-position, then test responsive video sizing with a downloadable sample.