HTMLParagraphs (<p>)

Paragraphs (<p>)

The <p> element represents a paragraph of text — one self-contained unit of prose. It's one of the most common tags in any HTML document, and also one of the most misused, because "paragraph" in HTML has a stricter meaning than "paragraph" in everyday writing.

basic-paragraph.html

HTML
<p>HTML documents are made of elements, and the paragraph is one of the most fundamental.</p>

<p>Each new <code>&lt;p&gt;</code> starts a fresh block, separated visually from the one before it.</p>
<p> Is a Block-Level Element

By default, <p> has display: block in the browser's built-in stylesheet. That means it always starts on a new line, stretches to fill the available width, and gets margin above and below it (typically 1em by default in most browsers). You don't need extra line breaks or spacer elements between paragraphs — the block-level box model handles the separation for you.

Behavior

Description

New line

A <p> always starts on its own line, regardless of surrounding markup

Full width

By default it stretches to fill its parent's available width

Vertical margin

Browsers apply default top/bottom margin, visually separating paragraphs

One per idea

Semantically, one <p> should hold one self-contained thought

Why You Can't Put Block Elements Inside <p>

According to the HTML content model, <p> may only contain "phrasing content" — inline-level things like text, <a>, <strong>, <em>, <span>, <img>, and similar. It cannot contain other block-level elements such as <div>, <ul>, <table>, another <p>, or a <blockquote>.

The browser will silently close your <p> for you
If you nest a block element like <div> or <ul> inside a <p>, the HTML parser doesn't throw an error — it auto-closes the paragraph right before the block element starts. The result is DOM structure that looks nothing like what you typed, which can break your CSS selectors and layout in confusing ways.

invalid-nesting.html

HTML
<!-- What you write -->
<p>
  Here is a list of steps:
  <ul>
    <li>Step one</li>
    <li>Step two</li>
  </ul>
  That's everything.
</p>

The browser actually parses that as three sibling elements — a <p> containing "Here is a list of steps:", then the <ul> as its own element (closing the paragraph automatically), then a second, unclosed <p> containing "That's everything." No error is thrown, but the structure you intended is gone.

Common Invalid Nesting Mistakes

Invalid

Why

Fix

<p><div>...</div></p>

<div> is block-level, not phrasing content

Use two siblings, or use <span> if you just needed a hook for CSS

<p><ul>...</ul></p>

Lists are block-level

Put the list after the paragraph closes

<p><p>...</p></p>

A <p> can't contain another <p>

Close the first paragraph, then start a new one

<p><h2>...</h2></p>

Headings are block-level

Move the heading outside the paragraph

What <p> Can Contain

Inline-level content is fine — in fact, that's exactly what <p> is designed to hold: plain text, links, emphasis, images, line breaks, and other phrasing elements.

valid-inline-content.html

HTML
<p>
  Read the <a href="/docs">official documentation</a> for details, or check
  the <strong>quick reference</strong> below. You can also
  <em>skip ahead</em> to the examples.
</p>
Closing tags are technically optional — write them anyway
HTML5 parsing rules let you omit the closing </p> tag (a new block element auto-closes it). Relying on this makes markup fragile and hard to read. Always write the closing tag explicitly.
Empty Paragraphs Aren't Spacing

A common beginner habit is stacking empty <p>&nbsp;</p> elements to push content down the page. That's a CSS job — use margin or padding instead. Empty paragraphs add meaningless nodes for screen readers to skip past and make the markup harder to maintain.

spacing-the-right-way.html

HTML
<!-- Avoid: empty paragraphs as spacers -->
<p>First section.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Second section.</p>

<!-- Prefer: CSS margin controls spacing -->
<p class="section">First section.</p>
<p class="section">Second section.</p>
One idea per paragraph
Just like in prose writing, keep each <p> focused on a single idea. Long, multi-topic paragraphs are harder to scan for readers and harder to target individually with CSS or JavaScript.
  • Use <p> for real prose paragraphs, not as a generic spacing or layout container.

  • Never nest block-level elements (div, ul, table, another p) inside a <p>.

  • Let CSS margin/padding handle vertical spacing, not empty paragraphs.

  • Always write the closing </p> tag even though HTML parsing allows omitting it.

Whitespace Inside a Paragraph

Browsers collapse runs of whitespace — multiple spaces, tabs, and line breaks in your source code — into a single space when rendering a <p>. This is why you can indent and wrap your HTML source however is readable without affecting the rendered output.

whitespace-collapsing.html

HTML
<p>
  This      paragraph has
  irregular    spacing and
  line breaks in the source,
</p>

<!-- Renders identically to: -->
<p>This paragraph has irregular spacing and line breaks in the source,</p>
Use CSS white-space if you need to preserve formatting
If you genuinely need to preserve exact spacing and line breaks (like a snippet of code), don't rely on <p>'s default collapsing behavior — use <pre> instead, or set white-space: pre-wrap in CSS.
Paragraphs vs Line Breaks

A frequent beginner mistake is using <br> to simulate paragraph breaks instead of starting an actual new <p>. The two look similar visually once styled, but they mean very different things structurally — a paragraph is a self-contained unit of thought; a line break is just a mid-paragraph interruption.

br-vs-p.html

HTML
<!-- Wrong: using <br><br> to fake a new paragraph -->
<p>
  First idea goes here.<br><br>
  A completely different idea goes here.
</p>

<!-- Right: two real paragraphs -->
<p>First idea goes here.</p>
<p>A completely different idea goes here.</p>

Signal

Correct markup

A new, unrelated thought

Start a new <p>

A forced break mid-thought (e.g. an address line)

Use <br> inside the same <p>

Paragraphs and CSS Typography

Because <p> is such a common element, most typographic CSS — line-height, max-width for readable line length, paragraph spacing — targets it directly or through a shared class. A few defaults worth knowing when styling body text:

paragraph-typography.css

CSS
p {
  max-width: 65ch; /* keeps line length readable */
  line-height: 1.6;
  margin-bottom: 1.25em;
}

p:last-child {
  margin-bottom: 0; /* avoid trailing whitespace at the end of a section */
}
65-75 characters per line is the readability sweet spot
Typography research generally recommends limiting paragraph width to roughly 65–75 characters per line for comfortable reading — the ch CSS unit (based on the width of the "0" character) is a convenient way to express that constraint.
Paragraphs Inside Other Containers

<p> works the same wherever it's placed — inside <article>, <section>, <blockquote>, table cells, list items, and more. The content model rule stays constant: a paragraph holds phrasing content, regardless of which block-level container it lives inside.

p-in-containers.html

HTML
<blockquote>
  <p>The best time to plant a tree was twenty years ago. The second best time is now.</p>
</blockquote>

<li>
  <p>Preheat the oven to 375°F before mixing the batter.</p>
</li>

<td>
  <p>Delivered on time, in good condition.</p>
</td>
Common Mistakes Beyond Invalid Nesting

Mistake

Why it matters

Using <div> for every paragraph instead of <p>

Loses paragraph semantics for screen readers and browser default styling, and reduces the value of "paragraph navigation" some assistive tools offer

One giant <p> for an entire article

Removes the visual and semantic breathing room readers rely on to parse long-form content

Wrapping a single <img> in a <p> out of habit

Harmless if the image genuinely sits within a paragraph of text, but unnecessary and sometimes confusing if it's a standalone image — consider <figure> instead

Not every block of text needs to be a <p>
Headings, list items, table cells, and captions already have their own appropriate elements. Reach for a bare <p> specifically for prose paragraphs, not as a catch-all text container.