CSS・Size and the box model

Block and inline

Parts that stack vertically, and parts that flow within text. This difference in "personality" is display. Get this, and the fog of layout lifts.

“There’s a part where, for some reason, width just won’t take effect” — as you work with CSS, you run into this mystery. The truth is, HTML parts have two personalities, and their behavior changes depending on which. What expresses that personality is display.

Block: stacks up vertically

Parts like <div>, <p>, and <h1> have the block personality. They spread to the full width and stack from top to bottom. width and height take effect obediently too. Paragraphs lining up one per line, each on its own line, is thanks to this personality.

Inline: flows within text

Meanwhile, parts like <a>, <span>, and <strong> are inline. They flow left to right within the text and line up side by side. The reason a link in the middle of a sentence just changes color without forcing a line break is this personality. But inline parts don’t respond to width or height.

Why don’t they? Because inline is treated as the same kind as characters. Just as you can’t widen the single character “a” to 300px, an inline part’s size is decided by its content.

A tip for telling which personality

Recall a tag’s role and you can usually tell them apart. Tags that make a “box” are block; tags that “decorate part of a sentence” are inline.

PersonalityRepresentative tagsImage
Block<div> <p> <h1> <ul> <li> <section>The “boxes” that divide up a page
Inline<a> <span> <strong> <em>The “decorations” you place mid-sentence

When you meet a new tag and aren’t sure, try asking: “Is this a box? Or a decoration within a sentence?”

Change the personality with display

You can switch this personality with display.

span {
  display: block;
}

Change an inline <span> into a block and it stacks vertically, and width starts taking effect. Conversely, set display: none; and the part disappears entirely and becomes invisible (this shines later when you show and hide things with JavaScript).

The difference between the three personalities is clear at a glance if you set them all the same width: 200px;.

All three say width: 200px, yet it only works on block and inline-block. Inline is the same kind as characters, so the width setting is ignored entirely, and it flows within the text at the size of its content.

display also has an “inline version” of flex, called inline-flex. Regular flex stacks vertically as a block, but inline-flex lines up within text while arranging its own contents in a horizontal row — handy for link parts that pair an icon with text.

There are two ways to “hide”

A tool similar to display: none; is visibility: hidden;. The difference is whether the space stays.

.a { display: none; }       /* disappears, space and all */
.b { visibility: hidden; }  /* becomes invisible, but the space stays */
On top, B disappears and A and C join up; on the bottom, B’s space stays empty and A and C stay apart. Even for the same “make it invisible,” whether the space stays is the difference.

With display: none;, the following parts close up and line up as if the part was never there to begin with. With visibility: hidden;, only the figure vanishes and a gap is left behind where it was. Use them by purpose: hidden if “I don’t want to break the surrounding layout when hiding it,” none if “I want to tuck it away completely.”

Summary of this lesson

  1. Parts have a block (stacks vertically) and an inline (flows within text) personality
  2. width / height don’t work on inline
  3. You can change the personality with display (block / inline-block / none)
  4. inline-flex is the best-of-both: “lines up within text, but its insides go in a horizontal row”

Let’s put class="social" on the contact section’s social links, to give them a button-like look where the icon and text are a set.

<a class="social" href="https://www.youtube.com/">▶ YouTube</a>
<a class="social" href="mailto:[email protected]">✉ Email</a>
.social {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: inherit;
  font-weight: bold;
  font-size: 14px;
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid #e9e3d9;
  background-color: #ffffff;
}

Because we made them inline-flex, the two links, YouTube and Email, line up side by side, and within each one the icon and text line up in a row too. Along with that, text-decoration: none; and color: inherit; remove the link-like underline and blue color.

Browser view. Below “Contact,” the YouTube and Email links line up side by side like rounded buttons on a white background
With the underline and blue gone, what were plain link words now look like buttons you could press.

FAQ

Why doesn't width work even though I set it?
Because that part is an inline element. Inline elements like a and span don't respond to width or height. Change it to display:block or display:inline-block and it starts working.
How is display:none different from visibility:hidden?
display:none removes the element along with the space it took up, and the parts that follow close up the gap. visibility:hidden only makes it invisible — the space stays empty and reserved.
When do I use inline-block?
When you want to keep something side by side but still set its size and margins. It suits parts like small buttons or labels placed within text.