On this page

Display and positioning in CSS

12 min read TextCh. 2 — Box Model and Positioning

The display property

The display property is one of the most fundamental in CSS. It defines how an element participates in the document flow and how its children behave.

Classic display values

Value Behavior Default example
block Takes up full width, creates a line break <div>, <p>, <h1>
inline Flows with text, does not accept width/height <span>, <a>, <strong>
inline-block Flows inline but accepts dimensions <img>, <button>
none Removes the element from flow and rendering -

block vs inline: the fundamental difference

A block element behaves like a paragraph: it starts on a new line and stretches to the full width of its container. You can control its width, height, margin, and padding in all directions.

An inline element behaves like a word within a sentence: it flows horizontally with the surrounding content. It does not respect width or height, and only accepts horizontal margin and padding.

inline-block: the best of both worlds

inline-block allows an element to flow inline alongside other elements, but unlike inline, it does accept dimensions (width, height) and margin/padding in all directions.

Positioning with position

The position property controls how an element is placed on the page. It works together with the top, right, bottom, and left properties.

static (default)

The element follows the normal document flow. The top, right, bottom, left, and z-index properties have no effect.

relative

The element keeps its space in the flow but can be visually offset relative to its original position.

.offset {
  position: relative;
  top: 10px;   /* Moves 10px downward */
  left: 20px;  /* Moves 20px to the right */
}

The element's original space is preserved; other elements do not move.

absolute

The element leaves the flow and is positioned relative to its closest positioned ancestor (with position other than static). If there is none, it is positioned relative to the <html>.

.parent {
  position: relative; /* Creates the context */
}

.absolute-child {
  position: absolute;
  top: 0;
  right: 0; /* Top-right corner of the parent */
}

fixed

Similar to absolute, but it is positioned relative to the viewport (the browser window). It does not move when scrolling.

Common uses: fixed navigation bars, floating buttons, modals.

sticky

Combines relative and fixed. The element behaves as relative until the scroll reaches a threshold defined with top, and then it "sticks" like fixed.

.sticky-nav {
  position: sticky;
  top: 0; /* Sticks when it reaches the top */
}

Requirement: the parent container must have enough height for the sticky effect to be visible.

The stacking context (z-index)

When elements overlap (with position: absolute, fixed, etc.), z-index controls which one appears on top. Higher values are rendered in front.

.modal-overlay { z-index: 100; }
.modal-content { z-index: 101; }
.tooltip { z-index: 200; }

Stacking context

A new stacking context is created when an element has:

  • position + z-index other than auto
  • opacity less than 1
  • transform, filter, or backdrop-filter
  • isolation: isolate

Within each context, z-index values are independent. A z-index: 9999 inside a context does not beat a z-index: 1 outside of it.

The inset shorthand (modern shortcut)

Instead of writing top, right, bottom, and left separately, you can use inset:

.overlay {
  position: fixed;
  inset: 0; /* Equivalent to top:0 right:0 bottom:0 left:0 */
}

With display and position mastered, you are ready to learn Flexbox, the layout system that revolutionized the way we build interfaces.

Practice

  1. Compare block, inline, and inline-block: Create three elements, one with each display value, and verify which ones accept width and height and which ones create a line break.
  2. Create a badge with position absolute: Build a card with position: relative and place a notification badge in the top-right corner using position: absolute.
  3. Implement a sticky header: Create a page with long content and a header that sticks to the top when scrolling using position: sticky.
Key difference
block takes up the full available width and creates a line break. inline flows with the text and does not accept width/height. inline-block combines both: it flows inline but accepts dimensions.
Be careful with z-index
z-index only works on elements with a position value other than static. Additionally, it creates a new stacking context, which can cause unexpected behavior if not well understood.
/* Block behavior */
.block {
  display: block;
  width: 100%;
  padding: 1rem;
  background: #e8f4f8;
  margin-block-end: 0.5rem;
}

/* Inline behavior */
.inline {
  display: inline;
  padding: 0.25rem 0.5rem;
  background: #ffeaa7;
  /* width and height do NOT work on inline */
}

/* The best of both worlds */
.inline-block {
  display: inline-block;
  width: 150px;
  height: 50px;
  padding: 0.5rem;
  background: #dfe6e9;
  vertical-align: middle;
}

/* Disappear without a trace */
.hidden {
  display: none;
}
/* Sticky: sticks when scrolling */
.header-sticky {
  position: sticky;
  top: 0;
  z-index: 100;
  background: white;
  box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
}

/* Fixed: always visible */
.floating-button {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  z-index: 50;
}

/* Absolute inside relative */
.card {
  position: relative;
  padding: 1.5rem;
}

.card .badge {
  position: absolute;
  top: -0.5rem;
  right: -0.5rem;
  background: #e74c3c;
  color: white;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  font-size: 0.75rem;
}