HTML Paragraphs

The paragraph element, written <p>, is the workhorse of text content in HTML. Every block of prose on the web — an article’s opening line, a product description, a footer note — is typically wrapped in a <p> element. It tells the browser “this is a self-contained block of text,” which affects how it’s laid out, how assistive technology announces it, and how search engines parse the page’s structure.

Overview: How the Paragraph Element Works

The <p> element is a block-level element. In the browser’s default rendering (defined by the user-agent stylesheet, not by HTML itself), block-level elements start on a new line and stretch to fill the available width of their parent container. Browsers also apply default top and bottom margins to <p> elements — typically around 1em — which is why paragraphs visually appear separated by vertical space even before any CSS is written. This spacing is presentation, not semantics: HTML says “this text is a paragraph,” and the browser’s default stylesheet decides how much space to put around it. A CSS course covers how to override that spacing; this lesson focuses purely on the markup and its meaning.

Semantically, a paragraph represents a distinct unit of thought or text, not merely “some text with a line break after it.” This distinction matters for accessibility: screen readers announce paragraph boundaries, letting users jump from paragraph to paragraph with a single keystroke. It also matters for maintainability — a document built from real paragraphs is far easier to restyle, translate, or restructure than one held together with manual line breaks.

Whitespace Collapsing

One of the most important browser behaviors to understand is whitespace collapsing. Inside a paragraph’s content, the HTML parser treats any sequence of spaces, tabs, and newlines as a single space when rendering. This means you can format your source code with line breaks and indentation for readability, and the browser will still render the text as one continuous flowing paragraph. This is a deliberate design choice: HTML source formatting is for developers, not for controlling visual output.

What a Paragraph Can Contain

A <p> element can contain text and inline-level elements — things like <a>, <strong>, <em>, and <code>. It cannot validly contain other block-level elements, such as <div>, <ul>, <table>, or another <p>. The HTML parser actually enforces this at the parsing stage: if it encounters a block-level start tag while inside an open <p>, it automatically closes the paragraph first. This “auto-closing” behavior is covered in detail below.

Syntax

<p>Your text content goes here.</p>

The paragraph element uses an opening and closing tag pair. It has no required attributes of its own — only the global attributes shared by all HTML elements apply to it.

Part Description
<p> Opening tag that begins the paragraph.
Content Text and permitted inline elements (<a>, <strong>, <em>, <code>, <br>, etc.).
</p> Closing tag. Technically optional in some contexts (see below), but always include it.
Global attributes id, class, lang, title, dir, and other attributes available on every HTML element.

Examples

Example 1: Basic Paragraphs

<p>HTML stands for HyperText Markup Language.</p>
<p>It describes the structure of a web page using elements.</p>

Result: Two distinct blocks of text stack vertically, each on its own line, with visible space between them from the browser’s default paragraph margins. Even though the two <p> tags sit right next to each other in the source, they never run together.

This is the simplest and most common use of the element: each idea gets its own paragraph, and the browser handles the visual separation automatically.

Example 2: Whitespace Collapsing in Action

<p>
   This   paragraph has     extra spaces,
   tabs, and
   line breaks in the source code.
</p>

Result: The browser renders this as a single line of flowing text reading “This paragraph has extra spaces, tabs, and line breaks in the source code.” — every run of whitespace is collapsed into one single space, and the line breaks in the source produce no visible break at all.

This example demonstrates why you can indent your HTML source however you like for readability without affecting the rendered output. If you want a visible line break inside a paragraph, you must insert an explicit <br> element — plain newlines in the source are not enough.

Example 3: A Realistic Paragraph with Inline Markup

<p>
  <strong>Note:</strong> the <code>fetch()</code> API is
  covered in our JavaScript course. For now, focus on how content is
  <em>structured</em>. Read more in the
  <a href="/learn/html-links">links lesson</a>.
</p>

Result: A single paragraph renders with “Note:” in bold, “fetch()” in a monospace inline code style, “structured” in italics, and “links lesson” rendered as a clickable, typically underlined link — all flowing together as one continuous block of text, exactly as whitespace collapsing predicts.

This shows that a paragraph is rarely just plain text in real pages — it commonly mixes emphasis, inline code references, and links while still counting as a single semantic unit.

How It Works Step by Step

When the browser’s HTML parser reaches a <p> start tag, it does the following:

  • It creates a new paragraph node in the DOM tree and makes it the current insertion point.
  • It reads subsequent text and inline elements as children of that node, collapsing whitespace runs into single spaces as it goes.
  • If it encounters a tag for a block-level element (like <div>, <p>, <ul>, or <table>) while the paragraph is still open, the HTML parsing algorithm automatically closes the current <p> element before processing that tag — even if you never wrote a closing </p> yourself.
  • When it reaches an explicit </p> tag, it closes the paragraph node normally.
  • Once parsing is complete, the layout engine applies the default block-level rendering rules and margins, then paints each paragraph on its own line.

The auto-closing behavior exists because the HTML specification defines <p>‘s closing tag as technically optional in certain situations. Relying on this is legal but discouraged, since it makes documents harder to read and easy to break during edits.

Common Mistakes

Mistake 1: Using Line Breaks Instead of Paragraphs

A very common mistake is faking paragraph spacing with repeated <br> tags instead of actually using separate paragraphs:

<p>First idea goes here.<br><br>Second idea goes here.</p>

This is valid markup, but it’s semantically wrong: both ideas are stuck inside one paragraph, so a screen reader announces them as a single block, and there is no structural boundary a browser or search engine can use. The fix is to use two real paragraphs:

<p>First idea goes here.</p>
<p>Second idea goes here.</p>

Now each idea is its own addressable, semantically distinct unit, and the visual spacing comes from the browser’s normal paragraph margins rather than manually inserted breaks.

Mistake 2: Nesting Block-Level Elements Inside a Paragraph

Another frequent error is placing a block-level element, such as a list, inside a paragraph:

<p>
  Here are the steps:
  <ul>
    <li>Open the file</li>
    <li>Edit the content</li>
  </ul>
</p>

This looks reasonable in the source, but it is invalid: <p> cannot contain a <ul>. As explained above, the parser will actually auto-close the <p> right before the <ul> starts, so the trailing </p> in the source ends up creating a stray, empty paragraph in the DOM — not what the author intended. The fix is to close the paragraph before the list begins:

<p>Here are the steps:</p>
<ul>
  <li>Open the file</li>
  <li>Edit the content</li>
</ul>

This produces the exact DOM structure you’d expect: one paragraph followed by one list, with no invalid nesting or parser-generated surprises.

Best Practices

  • Use one <p> per distinct idea or thought — don’t cram multiple ideas into a single paragraph with <br> tags.
  • Always write the closing </p> tag explicitly, even though it’s sometimes optional — it keeps your markup readable and prevents accidental auto-closing bugs.
  • Never nest block-level elements (<div>, <ul>, <table>, another <p>) inside a <p>; the parser will silently restructure your DOM if you try.
  • Control spacing between paragraphs with CSS margins, not with extra empty <p>&nbsp;</p> elements or stacked <br> tags.
  • Use inline elements like <strong>, <em>, <a>, and <code> freely inside paragraphs — that’s exactly what they’re for.
  • Don’t rely on multiple spaces or line breaks in your source to create visual spacing in the rendered text; whitespace collapsing will undo it.

Practice Exercises

  • Write a short bio (three separate paragraphs) about a fictional person, using at least one <strong> and one <a> element somewhere in the text.
  • Take a block of text written with several <br><br> pairs separating ideas and rewrite it as properly separated <p> elements instead.
  • Predict what the DOM will look like if you write a <p> containing a nested <table>, then check your understanding against the parsing rules explained in this lesson.

Summary

  • The <p> element defines a block-level paragraph of text and is one of the most frequently used elements in HTML.
  • Browsers add default top/bottom margins to paragraphs and start each one on a new line, but this spacing is presentation, controlled by CSS, not by the element itself.
  • Whitespace (spaces, tabs, newlines) inside a paragraph’s source is collapsed into single spaces when rendered.
  • A <p> may contain text and inline elements, but never other block-level elements — the parser auto-closes an open <p> when it meets one.
  • Use real paragraphs instead of stacked <br> tags to keep documents semantically correct and accessible.