The CSS display property for buttons and links
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> |
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:
- The spaces between the tags no longer add width, because flex ignores whitespace between its items.
- 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
gapdo the spacing. - 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.