Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Positioning

Normally elements stay in the document flow: each next block goes under the previous one, inline elements follow each other in a line. The position property lets you shift an element, lay it on top of others or pin it to the edge of the window.

Values of position

ValueWhat it does
staticThe normal place in the flow. The default
relativeA shift from its normal place
absoluteThe element leaves the flow and is placed by coordinates inside its parent
fixedPinned to the browser window and does not scroll
stickyScrolls with the page, but "sticks" at the edge of the window

The coordinates are set by top, right, bottom and left — the distance from that edge. They have no effect on static.

relative — a shift in place

An element with position: relative moves, but its old place stays taken, and the neighbours do not move:

<style>
  .box { padding: 8px; background: lavender; margin-bottom: 4px; }
  .moved { position: relative; top: 10px; left: 40px; background: gold; }
</style>
 
<div class="box">First</div>
<div class="box moved">Shifted 10px down and 40px right</div>
<div class="box">The third one stayed in place</div>

The yellow block overlaps the third one: for the other elements it still stands in its old place.

absolute — by coordinates inside the parent

An element with position: absolute is taken out of the flow and placed by coordinates. They are counted from the nearest ancestor whose position is not static — that is why the parent usually gets position: relative:

<style>
  .card { position: relative; padding: 16px; background: whitesmoke; }
  .badge { position: absolute; top: 8px; right: 8px; padding: 2px 8px; background: crimson; color: white; }
</style>
 
<div class="card">
  <span class="badge">New</span>
  A product card. The badge is pressed into the top right corner.
</div>

This is how badges, "close" buttons and captions over pictures are made. To attach an element to a block it does not sit inside, use anchor positioning — see the lesson "Anchor positioning".

inset — all sides at once

The inset property is a shorthand for the four coordinates. inset: 0 stretches an absolute element over the whole parent — handy for a darkening layer:

<style>
  .photo { position: relative; height: 100px; background: steelblue; }
  .shade { position: absolute; inset: 0; background: rgb(0 0 0 / 0.4); color: white; padding: 12px; }
</style>
 
<div class="photo">
  <div class="shade">A layer over the whole block</div>
</div>

fixed and sticky

fixed pins an element to the window: a "back to top" button or a chat in the corner is made this way. sticky keeps an element in place while its container scrolls. Scroll the list in the example:

<style>
  .list { height: 140px; overflow: auto; border: 1px solid silver; }
  .list h3 { position: sticky; top: 0; margin: 0; padding: 6px 8px; background: lightskyblue; }
  .list p { margin: 0; padding: 6px 8px; }
</style>
 
<div class="list">
  <h3>Letter A</h3><p>Anna</p><p>Anton</p><p>Arthur</p>
  <h3>Letter B</h3><p>Boris</p><p>Bella</p><p>Ben</p>
  <h3>Letter C</h3><p>Clara</p><p>Chris</p>
</div>

sticky needs at least one coordinate, such as top: 0 — otherwise there is nowhere to stick.

Common mistake

If no ancestor has a position, an absolute element counts its coordinates from the whole page and flies off into its corner:

<style>
  .card { padding: 16px; background: whitesmoke; margin-top: 40px; }
  .badge { position: absolute; top: 8px; right: 8px; background: crimson; color: white; }
</style>
 
<div class="card">
  <span class="badge">Where am I?</span>
  The card has no position: relative.
</div>

The badge ended up in the corner of the whole example, not the card. Give the parent position: relative.

Thanks for reading!

Donate to the site — we work hard for you.