Skip to the content

The CSS display property for buttons and links

Last updated: By Lukas BrandtLesson 10 of 214 min read

Three earlier lessons ended with the same note: the links ignore something. Top and bottom margin in lesson 2, vertical padding that overlaps instead of pushing in lesson 3, min-width in lesson 9. The cause is one property, display, and the fix is one line plus a helper.

The code

.btn {
  /* ...lessons 2 to 9 as before... */
  /* Lesson 10: display */
  display: inline-block;
  text-align: center;
}

Reload. The links jump to the same 160px minimum width as the button, their text centers, and all three boxes stand at the same 48px height. Narrow the window until the row wraps: the second line now keeps its distance from the first, thanks to the bottom margin you wrote in lesson 2.

text-align is set on the element whose content it aligns. An inline-block box holds its own little line of text, so text-align: center on .btn centers each label inside its button. The <button> already did that by default; now the links match it.

Outer and inner display

Every element generates a box, and display decides two things about it: how the box sits among its neighbors (its outer display) and how it lays out what is inside it (its inner display). inline-block is the combination "flows like a word on the outside, behaves like a block on the inside".

inline inline-block block
Starts on a new line No No Yes
Width when none is set Fits the content Fits the content Fills the parent
Accepts width and height No Yes Yes
Top and bottom margin Ignored Applied Applied
Top and bottom padding Painted, lines not pushed apart Painted, pushes lines apart Painted, pushes neighbors away
Typical elements <a>, <span>, <em> <button> <p>, <h1>, <ul>
Parts links can earn us a commission. As an Amazon Associate I earn from qualifying purchases.

There is also display: none, which removes the element from the layout entirely. It takes up no space, and screen readers skip it too.

Why not display: block for the buttons? Each button would then fill the full width of the row and sit on a line of its own, stacked like paragraphs. Sometimes that is exactly right, for a single full-width button at the bottom of a phone screen, for example. For a row of buttons, inline-block keeps them side by side while still giving each one a proper box.

The gap you did not write

Look between the buttons and you will find slightly more than the 0.5rem of margin. Inline-block boxes sit in a line of text, so the line breaks between the tags in your HTML render as spaces:

<a class="btn" href="#">Read the guide</a>
<a class="btn btn-light" href="#">Parts list</a>

That space is a few pixels wide and depends on the font. It is harmless here, and the next section shows a layout mode that ignores it.

A first look at flex

display: flex works differently from the values above: you set it on the parent, not on the buttons. The parent becomes a flex container, and its children line up in a row with spacing you control. Try this experiment on the row:

/* Experiment, not part of the Project 1 file */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

Three differences from inline-block are worth seeing:

  1. The spaces between the tags no longer add width, because flex ignores whitespace between its items.
  2. The buttons' own margin now adds to the gap, so the horizontal space doubles to 1rem. With flex you would usually drop the margin and let gap do the spacing.
  3. Items in a row stretch to the height of the tallest one by default, which keeps the row even when one label wraps onto two lines.

For Project 1 we stay with inline-block on the buttons and the plain margin, so the final code stays close to the box model you have built lesson by lesson. Project 2 puts flex to work when it turns a list of links into a horizontal menu, and MDN's flexbox guide covers the rest.

Questions

Is inline-block outdated now that flex exists?

No. They solve different problems. Inline-block makes a single element behave like a box inside text flow, which is what a button needs. Flex arranges a group of children inside a container. Plenty of pages use both.

Why did the links not need display: block to accept padding?

Inline elements always accept padding, they just do not let it push other lines away. What they lack is width, height and vertical margin, and inline-block adds those.

Try it: in the online HTML editor, switch .btn between inline, inline-block and block, and watch the row rebuild itself each time. Then remove the experiment rule so your file matches the final code.