What CSS vertical-align actually does

The vertical-align property aligns an element relative to the line box it sits in. In plain English: it changes how an inline, inline-block, or table-cell element is positioned vertically compared to the text (and other inline-level elements) around it.

This is why vertical-align is perfect for things like:

  • Aligning an icon next to text
  • Aligning inline-block “chips” or badges with surrounding text
  • Aligning inline images with text
  • Vertically aligning content in display: table-cell

It is not a general “center this div vertically” button. If you’re trying to vertically center content inside a block container, you usually want Flexbox, Grid, positioning, etc. For those approaches, see: Centering With CSS Interactive Tutorial.

The baseline: why vertical-align seems weird at first

Most inline content aligns to the baseline by default. The baseline is the imaginary line your text “sits” on. Letters like g, p, and y hang below it, so the line box includes a bit of extra space for descenders.

This is why an inline-block icon often looks slightly too low next to text: it’s baseline-aligned, not “visually centered.”

vertical-align:
.icon {
  vertical-align: baseline;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.demo-line {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 22px;
  line-height: 1.4;
  padding: 14px;
  border: 2px solid #111;
  background: #f6f6f6;
}

.icon {
  display: inline-block;
  width: 34px;
  height: 34px;
  border: 2px solid #111;
  background: #fff;
  border-radius: 8px;
  position: relative;
}

.icon::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 2px dashed #111;
  border-radius: 6px;
}

.note {
  margin-top: 10px;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 14px;
  opacity: 0.85;
}
  

Text with a little icon next to it.

Tip: baseline is the default, but middle often “looks” more centered for icons.

In that playground, the icon is display: inline-block, which makes it eligible for vertical-align. Switching from baseline to middle is the classic “icon + text” fix.

CSS vertical-align: middle (center-ish)

The value people reach for most often is middle. It aligns the middle of the element with the baseline plus half the x-height of the parent’s font.

That sounds complicated, but the practical result is: it usually makes icons and inline-block UI bits look vertically centered next to text.

.icon {
  vertical-align: middle;
}
  
.icon {
  vertical-align: baseline;
}
  
.icon {
  vertical-align: top;
}
  
.icon {
  vertical-align: bottom;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.demo {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 24px;
  line-height: 1.5;
  padding: 16px;
  border: 2px solid #111;
  background: #f6f6f6;
}

.icon {
  display: inline-block;
  width: 40px;
  height: 40px;
  border: 2px solid #111;
  border-radius: 10px;
  background: #fff;
  margin: 0 6px;
}

.icon::after {
  content: "★";
  display: grid;
  place-items: center;
  font-size: 22px;
}
  

Save to favorites

Notice how “center” is not an actual value for vertical-align. If you mean “center next to text,” you almost always mean middle.

CSS vertical-align: top

top aligns the top of the element with the top of the line box. This can be useful when you have inline-block elements with different heights and you want their tops to line up.

.box {
  vertical-align: top;
}
  
.box {
  vertical-align: baseline;
}
  
.box {
  vertical-align: bottom;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.line {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 18px;
  line-height: 1.3;
  padding: 16px;
  border: 2px solid #111;
  background: #f6f6f6;
}

.box {
  display: inline-block;
  width: 90px;
  border: 2px solid #111;
  background: #fff;
  padding: 10px;
  border-radius: 10px;
  margin-right: 10px;
}

.tall {
  padding-block: 24px;
}
  
Tall Short Short

CSS vertical-align: bottom

bottom aligns the bottom of the element with the bottom of the line box. This is useful when you want inline elements to “sit” on the same bottom edge visually.

In practice, if you’re aligning UI blocks of different heights, you’ll often compare top and bottom to see which one looks best for your layout.

Text-specific values: text-top, text-bottom, sub, super

There are a few values that are designed for aligning elements relative to text metrics:

  • text-top: aligns with the top of the parent’s text
  • text-bottom: aligns with the bottom of the parent’s text
  • sub: a subscript-like alignment
  • super: a superscript-like alignment
.unit {
  vertical-align: super;
}
  
.unit {
  vertical-align: sub;
}
  
.unit {
  vertical-align: text-top;
}
  
.unit {
  vertical-align: text-bottom;
}
  
.unit {
  vertical-align: baseline;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.demo-text {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 28px;
  line-height: 1.4;
  padding: 18px;
  border: 2px solid #111;
  background: #f6f6f6;
}

.unit {
  display: inline-block;
  padding: 2px 8px;
  border: 2px solid #111;
  border-radius: 10px;
  background: #fff;
  font-size: 14px;
}
  

Temperature: 23°C

Real subscripts/superscripts are also commonly done with semantic HTML like <sub> and <sup>. But the property values sub and super can be handy when your element isn’t literally a sub/sup tag.

Lengths and percentages: fine-tuning vertical-align

vertical-align can also accept a length (like 6px) or a percentage. This shifts the element up or down relative to the baseline.

  • Positive values move the element up
  • Negative values move the element down

This is great for those “it’s almost perfect, but not quite” icon alignment moments.

.icon {
  vertical-align: 0px;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.row {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 24px;
  line-height: 1.6;
  padding: 18px;
  border: 2px solid #111;
  background: #f6f6f6;
}

.icon {
  display: inline-block;
  width: 42px;
  height: 42px;
  border: 2px solid #111;
  border-radius: 12px;
  background: #fff;
  margin-inline: 8px;
  position: relative;
}

.icon::before {
  content: "";
  position: absolute;
  inset: 10px;
  border-radius: 999px;
  border: 2px dashed #111;
}
  

Download file.zip

This kind of micro-adjustment is especially common for icon fonts, SVG icons, and inline badges. Try to keep these tweaks small, though. If you find yourself pushing vertical-align: 18px, it’s usually a sign that the layout method should change.

CSS vertical-align with images (and the gap under images)

Inline images behave like text characters: they sit on the baseline. That means browsers often leave a tiny gap under an inline <img> to make room for descenders.

One common fix is:

  • Set the image to display: block, or
  • Keep it inline and set vertical-align: middle (or bottom)
.avatar {
  vertical-align: middle;
}
  
.avatar {
  vertical-align: baseline;
}
  
.avatar {
  vertical-align: bottom;
}
  
.avatar {
  vertical-align: top;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 18px;
  line-height: 1.5;
  padding: 16px;
  border: 2px solid #111;
  background: #f6f6f6;
  max-width: 520px;
}

.avatar {
  display: inline-block;
  width: 56px;
  height: 56px;
  border: 2px solid #111;
  border-radius: 14px;
  margin-right: 10px;
}

.caption {
  margin-top: 10px;
  font-size: 14px;
  opacity: 0.85;
}
  
Random avatar Monospace Penguin posted a new update.

Switch vertical-align values and watch how the image sits in the text line.

If your goal is “no baseline gap under the image,” another super common fix is simply: img { display: block; }. That’s not vertical-align, but it’s often the cleanest way when the image doesn’t need to behave like text.

CSS vertical-align div, text, image (what people really mean)

Searches like “CSS vertical align div” usually mean one of these:

  • “Align an icon/image with text” (yes, vertical-align is perfect for that)
  • “Vertically center content inside a box” (that’s usually Flexbox/Grid/positioning)
  • “Align columns in a layout” (again, not vertical-align, usually Flex/Grid)

So here’s the rule of thumb:

  • If your element is inline or inline-block (or inside a table-cell), use vertical-align.
  • If your element is a normal block-level div in a layout, you probably want to look at the Centering With CSS Interactive Tutorial.

Table-cells: where vertical-align feels most straightforward

In tables (or elements behaving like table cells), vertical-align is wonderfully literal: it aligns content to the top/middle/bottom of the cell.

vertical-align:
.cell {
  vertical-align: middle;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.table {
  display: table;
  width: 100%;
  border-collapse: collapse;
  font-family: ui-monospace, SFMono-Regular, monospace;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  border: 2px solid #111;
  padding: 14px;
  background: #f6f6f6;
  height: 140px;
  width: 50%;
}

.box {
  border: 2px solid #111;
  background: #fff;
  border-radius: 14px;
  padding: 10px 12px;
  display: inline-block;
}
  
Short content
Taller content
with a second line
to show alignment.

If you’ve ever thought “vertical-align is easy in tables but weird elsewhere,” that’s because the table-cell case matches our mental model: top/middle/bottom of a rectangle. Inline formatting is based on baselines and line boxes.

Vertical-align not working: a checklist

If vertical-align seems to do nothing, it’s usually one of these:

  1. The element isn’t eligible. vertical-align applies to inline, inline-block, and table-cell. If your element is display: block, it won’t respond the way you expect.
  2. You’re trying to align a whole block layout. For real vertical centering inside containers, use Flexbox/Grid (see the Centering With CSS Interactive Tutorial).
  3. There’s no meaningful “neighbor” in the same line. vertical-align aligns relative to the line box and other inline-level items. If your element is alone or on its own line, you may not notice changes.
  4. Line-height is doing most of the visual work. Sometimes adjusting line-height (on the parent text) is the real fix.
  5. You’re inside a Flexbox or Grid item and expecting vertical-align to center things. Flex/Grid have their own alignment systems (again: use the centering tutorial).

Vertical-align cheat sheet

  • Use case: icon/badge/image next to text
    • Try vertical-align: middle first
  • Use case: align tops of mixed-height inline-block elements
    • Use vertical-align: top
  • Use case: align bottoms of mixed-height inline-block elements
    • Use vertical-align: bottom
  • Use case: table cells
    • top, middle, bottom behave very intuitively
  • Not the right tool: vertically centering content inside a normal block div

Wrap-up: vertical-align in one sentence

vertical-align is for aligning inline-ish things (inline, inline-block, table-cell) relative to the line box or cell, not for globally centering block layouts. Once you think “baseline,” it stops feeling like magic and starts feeling like a very specific (and very useful) wrench.