HTML Elements

An HTML element is the basic building block of every web page. It’s the combination of a start tag, the content inside it, and an end tag, and it tells the browser what a piece of content is — a paragraph, a heading, a link, an image. Once you understand how elements are written, nested, and closed, the rest of HTML is just learning which element to reach for in which situation.

Overview: What Is an HTML Element?

Most HTML elements consist of three parts: an opening tag, content, and a closing tag. The opening tag is the element name wrapped in angle brackets, like <p>. The closing tag is the same name with a forward slash, like </p>. Everything between the two tags is the element’s content, which can be plain text, other elements, or a mix of both.

For example, <p>Hello, world!</p> is a single paragraph element. The tag name p tells the browser “this is a paragraph,” and the browser applies its default styling and behavior for paragraphs (block-level layout, margin above and below) without you writing any CSS at all. This is the core idea behind HTML: tags describe meaning and structure, not appearance. Visual styling is the job of CSS, a separate language covered in its own course.

Nesting elements

Elements can contain other elements, forming a hierarchy known as the DOM tree (Document Object Model). When one element sits inside another, it’s called a child of that element, and the containing element is its parent. For example, a list item can contain emphasized text, and an article can contain headings, paragraphs, and lists. The browser builds this tree as it parses your HTML, and every piece of CSS or JavaScript that later manipulates the page works against that same tree.

A critical rule: nested elements must close in the reverse order they were opened. This is often described as “first opened, last closed,” like nesting boxes inside boxes. If tags cross over each other instead of nesting cleanly, the markup is invalid and browsers must guess how to fix it, which can produce inconsistent results across browsers.

Void (self-closing) elements

Not every element wraps content. Some elements are informational or represent an empty slot in the document and never have children or a closing tag. These are called void elements. Common examples include <img>, <br>, <hr>, <input>, and <meta>. You never write <br></br> — there is nothing to put between an opening and closing tag, so only the single tag exists.

Void element Purpose
<img> Embeds an image
<br> Inserts a single line break
<hr> Inserts a thematic break (horizontal rule)
<input> A form control
<meta> Document metadata
<link> Links an external resource, like a stylesheet

Syntax

The general form of a normal (non-void) element is:

<tagname attribute="value">content</tagname>
  • tagname — the element’s name, which tells the browser what role this content plays (e.g. p, h1, a, ul).
  • attribute="value" — zero or more attributes inside the opening tag that add extra information or behavior (covered in depth in the next lesson).
  • content — text, other elements, or both, placed between the tags.
  • </tagname> — the closing tag, matching the opening tag’s name exactly.

Void elements drop the content and closing tag entirely: <tagname> or, in the older self-closing style still commonly seen, <tagname />. Both are treated identically by browsers in HTML documents; the trailing slash is purely a stylistic convention carried over from XHTML.

Examples

Example 1: A basic element with nested inline elements

<p>This recipe takes <strong>20 minutes</strong> and serves <em>four people</em>.</p>

Result: A single paragraph is rendered as one block of text. Within it, “20 minutes” appears bold (from <strong>) and “four people” appears italicized (from <em>), while the rest of the sentence renders as normal text.

This shows the parent-child relationship in action: <strong> and <em> are inline child elements nested inside the block-level <p> parent. The browser renders the paragraph as a block, and the inline children flow within its text without breaking onto their own line.

Example 2: Several elements combined into a small structure

<article>
  <h2>Getting Started with Gardening</h2>
  <p>Before you plant anything, test your soil.</p>
  <ul>
    <li>Check pH level</li>
    <li>Check drainage</li>
    <li>Check sunlight exposure</li>
  </ul>
</article>

Result: The browser displays a heading reading “Getting Started with Gardening”, followed by a paragraph of text, followed by a bulleted list with three items: “Check pH level”, “Check drainage”, and “Check sunlight exposure”.

Here, <article> is the parent element, and <h2>, <p>, and <ul> are its direct children. The <li> elements are, in turn, children of <ul>, not of <article> directly — each level of nesting matters for both meaning and for how CSS selectors will later target these elements.

Example 3: Mixing normal elements with void elements

<p>
  Contact us at the address below.<br>
  123 Main Street, Springfield
</p>
<hr>
<p>
  <img src="logo.png" alt="Company logo">
</p>

Result: The browser shows a paragraph of text with a manual line break splitting it into two visual lines, then a horizontal rule (a thin divider line) across the page, then a second paragraph containing an image of the company logo.

Notice that <br>, <hr>, and <img> never have closing tags or content between tags — they are void elements that exist purely to insert something at that point in the document.

How It Works Step by Step: Parsing and the DOM

When a browser receives an HTML document, it doesn’t treat it as a flat string of text. It runs the markup through an HTML parser that builds a tree of elements, called the DOM. The process works roughly like this:

1. The parser reads the byte stream and tokenizes it, recognizing start tags, end tags, attributes, text, and comments as distinct tokens.

2. Each start tag creates a new node in the tree. If the parser is currently “inside” another element, the new node becomes a child of it.

3. Text between tags becomes text nodes, which are also children of the current element.

4. An end tag closes the most recently opened matching element, popping it off the parser’s internal stack and returning focus to its parent.

5. Void elements never get pushed onto that stack in a way that expects a closing tag — the parser creates the node and immediately moves on.

6. If tags are malformed (missing an end tag, or closed out of order), the parser follows error-recovery rules defined in the HTML specification to guess a “best effort” tree — but the result can differ from what you intended, and can even differ subtly between browsers for unusual cases.

The end result of this whole process is the DOM tree that CSS selectors match against and that JavaScript can traverse and modify. Understanding that every element you write becomes a real node in this tree — with a definite parent, and a definite set of children — is the key mental model for everything else in HTML.

Common Mistakes

Mistake 1: Overlapping tags instead of proper nesting

<p>This is <strong>very <em>important</strong> text</em>.</p>

This is invalid because <em> opens after <strong> but closes after it — the tags overlap instead of nesting cleanly. The closing order must mirror the opening order.

<p>This is <strong>very <em>important</em></strong> text.</p>

Here <em> is fully closed before <strong> is closed, so the elements nest correctly: <em> is entirely a child of <strong>.

Mistake 2: Forgetting to close a non-void element

<ul>
  <li>First item
  <li>Second item</li>
</ul>

The first <li> is never explicitly closed. Browsers will often recover by auto-closing it when the next <li> starts, but relying on this error recovery is fragile and makes the source harder to read and validate.

<ul>
  <li>First item</li>
  <li>Second item</li>
</ul>

Every element is explicitly closed, so the structure is unambiguous to both the browser and anyone reading the source.

Best Practices

  • Always close every non-void element explicitly, even in cases where the browser would recover gracefully — don’t rely on error correction.
  • Nest tags so that closing tags mirror the reverse order of opening tags; never let tags overlap.
  • Choose element names for what the content means (a heading, a list, a quotation), not for how you want it to look — save visual styling for CSS.
  • Indent nested elements consistently in your source code so the parent-child hierarchy is easy to read at a glance.
  • Use void elements (<br>, <hr>, <img>, etc.) without a matching closing tag — writing one is unnecessary and, in some cases, invalid.
  • When in doubt about how markup will be interpreted, run it through an HTML validator rather than guessing based on how one browser happens to render it.

Practice Exercises

1. Write a single <p> element containing a sentence where one word is bold (using <strong>) and a different word is italic (using <em>), making sure none of the tags overlap.

2. Build a small <section> element containing one heading, one paragraph, and an ordered list (<ol>) with three steps. Check that every element you open has a matching, correctly nested closing tag.

3. Take this incorrectly nested snippet and rewrite it so the tags close in the correct order: <p><strong>Warning: <em>read carefully</strong></em></p>.

Summary

  • An HTML element is made of an opening tag, its content, and a closing tag — the tag name tells the browser what the content means.
  • Elements can nest inside one another, forming the parent-child relationships that make up the DOM tree.
  • Closing tags must mirror opening tags in reverse order; overlapping tags produce invalid, unpredictable markup.
  • Void elements like <img>, <br>, and <hr> have no content and no closing tag.
  • The browser’s parser converts your markup into the DOM tree, which is what CSS and JavaScript actually interact with — writing well-formed HTML keeps that tree predictable.