CSSvertical-align in Layout

vertical-align in layout

vertical-align is one of CSS's most misunderstood properties. It only works on inline and inline-block elements (not block elements), and it aligns elements relative to the text baseline of their line. For block-level layout, use flexbox or grid instead. Vertical-align is useful for aligning icons with text, images in text, and inline-block elements on the same line.

What vertical-align does (and doesn't)

Works on

Does NOT work on

Aligns relative to

Inline elements

Block elements

Text baseline of line

Inline-block elements

Floats

Text baseline of line

Table cells

Positioned elements

Cell content area

(for table-cell display only)

CSS
/* vertical-align WORKS on inline/inline-block */
span {
  display: inline;
  vertical-align: middle;  /* works */
}

button {
  display: inline-block;
  vertical-align: top;  /* works */
}

/* vertical-align DOESN'T work on block */
div {
  display: block;
  vertical-align: middle;  /* ignored */
}

/* Use flexbox for block alignment instead */
div {
  display: flex;
  align-items: center;  /* this is how to vertically center blocks */
}
Baseline, top, middle, bottom

These are the main vertical-align values. They position the element relative to the line it's on.

CSS
<!-- Text line with different vertical alignments -->
Some text <span class="baseline">baseline</span> more text
Some text <span class="top">top</span> more text
Some text <span class="middle">middle</span> more text
Some text <span class="bottom">bottom</span> more text

/* Baseline — aligns to baseline of text (default) */
.baseline {
  display: inline;
  vertical-align: baseline;
  /* Aligned to bottom of lowercase letters */
}

/* Top — aligns top of element to top of line */
.top {
  display: inline;
  vertical-align: top;
  /* Element sits at the top of the line */
}

/* Middle — aligns to middle of line */
.middle {
  display: inline;
  vertical-align: middle;
  /* Roughly centers vertically (not exact) */
}

/* Bottom — aligns bottom to baseline */
.bottom {
  display: inline;
  vertical-align: bottom;
  /* Element bottom touches the baseline */
}
The baseline mystery

Baseline alignment causes gaps under images and inline elements. This is because images (like text) align to the baseline of the line, not the bottom of the line.

CSS
<!-- Image in text creates gap -->
<p>
  Text <img src="icon.png" alt="icon"> more text
</p>

img {
  /* Default: vertical-align: baseline */
  /* Image baseline aligns with text baseline */
  /* Extra space below image (the descender space) */
}

<!-- Visual -->
[Text] [Image] [More text]
              [gap here]

<!-- Solutions -->

/* Solution 1: Change vertical-align */
img {
  vertical-align: middle;  /* or top, bottom */
}

/* Solution 2: Make image block */
img {
  display: block;
  /* No longer inline, doesn't align to baseline */
}

/* Solution 3: Remove line-height */
p {
  line-height: 0;
}

/* Solution 4: Negative margin */
img {
  margin-bottom: -4px;  /* move image down */
}
Inline-block alignment

Inline-block elements align to the baseline by default. When multiple inline-block elements are on the same line, use vertical-align to align them.

CSS
<!-- Multiple inline-block elements -->
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>

.button {
  display: inline-block;
  /* Default: vertical-align: baseline */
  /* Buttons sit on same baseline */
}

<!-- Alignment options -->
.button {
  display: inline-block;
  vertical-align: top;    /* all sit at top of line */
}

/* or */
.button {
  display: inline-block;
  vertical-align: middle; /* roughly centered */
}

<!-- Better for buttons: use flex -->
.button-group {
  display: flex;
  gap: 10px;
}

.button {
  display: inline-block;
  /* flex handles alignment */
}
Icons aligned with text

A common use case: align an icon next to text.

CSS
<!-- Icon and text -->
<a href="#">
  <svg class="icon"><!-- icon --></svg>
  Link text
</a>

<!-- Problem: icon sits on baseline -->
[Icon] Link text
  [gap]

<!-- Solution: vertical-align -->
.icon {
  display: inline-block;
  vertical-align: middle;
  /* or use top, depending on preference */
  margin-right: 8px;
}

Result:
[Icon] Link text  (roughly centered)

<!-- Modern solution: flex -->
a {
  display: flex;
  align-items: center;
  gap: 8px;
}

.icon {
  width: 16px;
  height: 16px;
  /* flex handles alignment */
}
Table-cell alignment (display: table-cell)

When you set display: table-cell, vertical-align works to center content within the cell's height.

CSS
<!-- Vertically centered with table-cell (legacy approach) -->
<div class="centered">Centered content</div>

.centered {
  display: table-cell;
  width: 200px;
  height: 200px;
  vertical-align: middle;
  text-align: center;
  /* Content is vertically centered */
}

Result:
[─────────────────]
[  Centered      ]
[  content       ]
[─────────────────]

<!-- Modern solution: flex (better) -->
.centered {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 200px;
  height: 200px;
  /* Content is vertically and horizontally centered */
  /* Better browser support and more flexible */
}
When to use vertical-align

CSS
<!-- GOOD: Icon aligned with inline text -->
.icon-button {
  display: inline-block;
  vertical-align: middle;
}

<!-- GOOD: Inline elements on same baseline -->
.pill-badge {
  display: inline-block;
  vertical-align: top;
}

<!-- BAD: Use flex instead -->
.header {
  display: block;
  vertical-align: center;  /* doesn't work, use flex */
}

/* Better */
.header {
  display: flex;
  align-items: center;
}

<!-- BAD: Use grid/flex instead -->
.container {
  height: 300px;
  vertical-align: middle;  /* doesn't work on blocks */
}

/* Better */
.container {
  height: 300px;
  display: flex;
  align-items: center;
}

/* or */
.container {
  height: 300px;
  display: grid;
  place-items: center;
}
Numeric values with vertical-align

You can use pixel or percentage values to fine-tune alignment relative to the baseline.

CSS
/* Pixel offset */
.shift-up {
  display: inline-block;
  vertical-align: -5px;  /* move up 5px */
}

.shift-down {
  display: inline-block;
  vertical-align: 5px;  /* move down 5px */
}

/* Percentage of line-height */
.shift-percent {
  display: inline-block;
  vertical-align: 25%;  /* 25% of line-height up */
}

<!-- Common use: shift superscript/subscript -->
<span>x<sup class="superscript">2</sup></span>

.superscript {
  display: inline-block;
  vertical-align: 0.5em;
  font-size: 0.8em;
}
Note
Vertical-align is for inline and inline-block elements only. For block layout, use flexbox or grid. Most "vertical alignment" problems are better solved with flexbox (`align-items`) or grid (`align-items` or `place-items`).
vertical-align can be confusing
The fact that vertical-align works differently on inline vs table-cell elements, and has no effect on blocks, makes it a common source of confusion. When centering content, strongly prefer flexbox or grid. Only use vertical-align for inline text alignment edge cases.
Next
CSS layout fundamentals are complete. The next major layout systems are flexbox and grid, which provide powerful one and two-dimensional layouts.