Here’s a question that trips up almost everyone when they start writing HTML: why do two <p> paragraphs stack on top of each other, but two <a> links sit on the same line? You didn’t write any CSS. You didn’t set any positioning. And yet the browser already made a decision about how each element should flow.
That decision comes down to one property every element has by default: it’s either block-level or inline. Once this clicks, a huge amount of HTML behavior stops feeling random. You’ll know in advance whether an element will start on a new line or tuck in next to its neighbors, and you’ll understand which elements can legally go inside which.
This article assumes you already know what tags and elements are — if you’re brand new, start with what is HTML and come back. Otherwise, let’s get into it.
Two ways an element can flow
Every visible HTML element belongs to one of two default display categories. This is set by the browser’s built-in stylesheet, and it governs the element’s natural behavior before you touch any CSS.
A block-level element behaves like a full-width box. It starts on a new line, and it pushes whatever comes after it onto the next line too. By default it stretches to fill the entire width of its container, no matter how little content is inside. Paragraphs, headings, and lists are all block elements.
An inline element is the opposite. It only takes up as much width as its content needs, and it sits within the normal flow of text — right alongside other inline elements and words, without forcing a line break. Links, bold text, and images are inline.
Here’s the contrast in one snippet:
<p>First paragraph.</p>
<p>Second paragraph.</p>
<a href="#">First link</a>
<a href="#">Second link</a>
The two paragraphs render on separate lines, each spanning the full width of the page. The two links render right next to each other on the same line. Same structure — two sibling elements — completely different layout, purely because of block versus inline.
Block-level elements: the big boxes
Block elements are the structural building blocks of a page. They carve the page into stacked sections — a header, a paragraph, a list, a section of content. Because each one claims a full line of its own, they naturally form the vertical skeleton of your layout.
Some of the block elements you’ll use constantly:
<h1>A heading</h1>
<p>A paragraph of text.</p>
<ul>
<li>A list item</li>
</ul>
<div>A generic container</div>
<section>A section of content</section>
<article>A self-contained article</article>
Every one of these starts on a new line and takes the full available width. Try putting two <div> elements one after another and you’ll see them stack vertically, even if each holds only a single word.
The most generic block element is <div> (short for “division”). It has no meaning of its own — it’s just a plain box you use to group other elements together so you can style or position the group as a unit. When no semantic element fits, <div> is the catch-all container.
Reach for a semantic element before a plain div
A <div> works anywhere, but it tells a screen reader and a search engine nothing about what’s inside it. When the content has a clear role — a page header, a navigation bar, the main content, a footer — prefer the matching semantic element (<header>, <nav>, <main>, <footer>) instead. They’re block-level too, so the layout behaves identically, but they carry meaning a bare <div> doesn’t. There’s a whole article on semantic HTML if you want to go deeper.
Inline elements: flowing within text
Inline elements live inside lines of text and wrap with that text. They don’t break the flow — they decorate or link a span of content right where it sits. This is exactly what you want for marking up words and phrases inside a sentence.
<p>
Visit <a href="https://acy-partner.com">our site</a> to read more.
This word is <strong>important</strong>, and this one is
<em>emphasized</em>. Here's some <code>inline code</code> too.
</p>
Notice how <a>, <strong>, <em>, and <code> all sit inside the paragraph, flowing with the words around them. None of them forces a line break. They take up only the width of their own text.
Common inline elements include:
<a>— links<strong>and<b>— bold text<em>and<i>— italic / emphasized text<span>— a generic inline container (the inline twin of<div>)<code>— inline code<img>— images<br>— a line break<input>,<label>,<button>— form controls
Just as <div> is the meaningless block container, <span> is the meaningless inline one. You use <span> to wrap a few words so you can style or target them — for example, coloring a single word in a sentence — without affecting the layout around them.
Images are inline, and that surprises people
<img> is an inline element, which catches a lot of beginners off guard. It means an image flows along with text and sits on the text baseline, which is why you sometimes see a mysterious little gap under an image. That gap is space reserved for the descending parts of letters (like the tail of a “y”), because the browser is treating the image like a character on a line. The usual fix is CSS — display: block or vertical-align: bottom on the image — but for now, just know that the gap is normal and comes from <img> being inline.
The nesting rule that actually matters
Once you know which elements are block and which are inline, one rule prevents most invalid-HTML mistakes: inline elements should not contain block elements.
A block element can hold both block and inline children. That’s normal and expected:
<div>
<h2>Title</h2>
<p>A paragraph with a <a href="#">link</a> inside.</p>
</div>
Here a <div> (block) contains an <h2> (block) and a <p> (block), and the <p> contains an <a> (inline). All correct.
But the reverse breaks the rules. You should not put a block element inside an inline one:
<!-- Wrong: a block <div> inside an inline <span> -->
<span>
<div>This shouldn't be here</div>
</span>
<!-- Wrong: a block <p> inside an inline <a> -->
<a href="#"><p>Don't do this</p></a>
A particularly common version of this mistake is wrapping a block element in a link. Browsers are forgiving and may even render it, but it’s invalid HTML and can cause real problems — broken styling, unexpected behavior, or accessibility issues.
The one big exception: wrapping a whole block in a link
There’s a modern exception worth knowing. Since HTML5, an <a> element is allowed to wrap block-level content — for instance, making an entire card clickable by wrapping the whole thing in a link. So <a href="#"><div>...</div></a> is technically valid in HTML5. But this is the exception, not the rule: <a> is special. For every other inline element (<span>, <strong>, <em>, and friends), keep block elements out. When in doubt, nest inline inside block, never block inside inline.
A quick way to check any element
You don’t have to memorize every element’s category. Two reliable shortcuts:
First, think about its job. If an element represents a chunk or section of the page — a paragraph, a heading, a list, a container — it’s almost certainly block. If it marks up a piece of text within a line — a link, an emphasized word, a snippet of code — it’s almost certainly inline.
Second, just look at how it behaves. Drop two of the same element next to each other in a page. If they stack vertically, it’s block. If they sit side by side, it’s inline. The browser tells you immediately.
<!-- These stack -> block -->
<p>One</p>
<p>Two</p>
<!-- These sit side by side -> inline -->
<span>One</span>
<span>Two</span>
A note on CSS display
Everything we’ve covered is the element’s default behavior, set by the browser. It’s not permanent. Once you learn CSS, the display property lets you override it: you can make a block element behave inline with display: inline, or make an inline element behave block with display: block, or use display: inline-block and display: flex for layouts that blend both behaviors.
That’s an important mental model to carry forward: block versus inline is the starting point, not a cage. HTML gives every element a sensible default, and CSS lets you change it when your layout needs something different. But understanding the defaults first means you’ll always know what you’re changing from — and that makes CSS layout far less confusing later.
Wrapping up
Block versus inline is one of those small ideas that quietly explains a lot of HTML behavior:
- Every element is, by default, either block-level or inline.
- Block elements (
<div>,<p>,<h1>,<ul>,<section>) start on a new line and fill the full width — they stack vertically and form the page’s structure. - Inline elements (
<a>,<strong>,<em>,<span>,<img>) take only the width they need and flow within a line of text. <div>is the generic block container;<span>is its inline counterpart. Both are meaningless on their own and exist for grouping and styling.- The core nesting rule: don’t put block elements inside inline ones — with the single HTML5 exception that an
<a>may wrap block content. - All of this is the element’s default, which CSS
displaycan later override.
Get comfortable predicting whether an element will stack or sit inline, and HTML layout stops feeling like guesswork. Next, you’ll see how class and id let you label these elements so CSS and JavaScript can find them precisely.