Block or inline?

Content

Have you ever encountered unexpected rendering issues in your HTML documents? Perhaps you've found elements behaving strangely or not displaying as intended. This common frustration often stems from incorrect nesting of HTML tags. Many people believe there are only two types of HTML tags — block and inline. However, this is a misconception. Whether you're a seasoned web developer or just starting, mastering the proper nesting of HTML elements is essential for building well-structured web pages that behave as expected. Let's get started by uncovering the root of these issues and learning how to avoid them.

Screenshots from many training videos where the authors claim that there are only two types of tags in html - block and inline.
Screenshots from many training videos where the authors claim that there are only two types of tags in html - block and inline.

This image contains around 50 screenshots from random articles and courses, where the authors state that tags in HTML are divided into two types — block and inline.

This is wrong.

HTML tags are divided into 7 types. In this article we will learn about them and how to use them correctly.

The Problem

Let's imagine that we have a task where we need to make a markup of a form. Something like this:

// src/components/sign-up/components/register-form/register-form.jsx

<form className="register-form">
  <p className="register-form__control-wrapper">
    <CustomSelect label="Type:" options={[]} />
  </p>
</form>

CustomSelect markup:

// src/components/common/custom-select/custom-select.jsx

const CustomSelect = ({ label, options }) => (
  <div className="custom-select">
    <label className="custom-select__label">
      {label}
      <select className="custom-select__control">
        {options.map((it) => (
          <option value={it.value}>{it.label}</option>
        ))}
      </select>
    </label>
  </div>
)

But when we open the browser we see this:

Wrong nesting of the div element inside the p element.
Wrong nesting of the div element inside the p element.

Hmm, the custom select component outside of the p element? An extra p appeared?

One more example:

// src/components/sign-up/components/users/users.jsx

<div className="table-wrapper">
  <CustomTable>
    {users.map((user) => (
      <tr>
        <td>{user.name}</td>
        <td>{user.role}</td>
      </tr>
    ))}
  </CustomTable>
</div>

CustomTable markup:

// src/components/common/custom-table/custom-table.jsx

const CustomTable = ({ children }) => (
  <div className="custom-table">{children}</div>
)

Let's open a browser:

Wrong nesting of the tr element inside the div element.
Wrong nesting of the tr element inside the div element.

What is going on...

This is how the browser behaves when we try to nest one element incorrectly within another.

7 types of HTML Element

Each element in HTML falls into zero or more categories that group elements with similar characteristics together and has its own content model and other nuances and features. For example, the p element:

Screenshot from the HTML document showing that there are 7 types of tags in HTML.
Screenshot from the HTML document showing that there are 7 types of tags in HTML.

HTML Element content types:

Content types in HTML and how they intersect with each other.
HTML Element content types
Content types in HTML and how they intersect with each other with some examples of tags.
HTML Element content types

When you try to nest one tag in another incorrectly, browser starts fixing errors at its discretion without asking.

Let's play. Can x be nested in y?

Open the documentation and try to find the answer yourself 😉

<li>
  <p>?</p>
</li>
Spoiler

Yes, you can!

The li element content model — flow content.

The p element categories — flow content, palpable content.

<header>
  <section>?</section>
</header>
Spoiler

Yes, you can!

The header element content model — flow content, but with no header or footer element descendants.

The section element categories — flow content, sectioning content, palpable content.

<p>
	<div>?</div>
</p>
Spoiler

No, you can't!

The p element content model — phrasing content.

The div element categories — flow content, palpable content.

How can we test ourselves and our application? One of the tools is the official W3C validator.

You can upload the file, paste the code or use the link to your application.

Let's try using one of our examples at the beginning of the article:

Invalid HTML in the input on the validator.w3.org website.
Invalid HTML in the input on the validator.w3.org website.

The result:

Output of errors of invalid HTML from the validator.w3.org website.
Output of errors of invalid HTML from the validator.w3.org website.

The validator and the browser did not know what we meant when we nested the <tr> element inside the <div> element. The browser tried to fix the errors itself (because of this, we got the wrong markup) and the validator talks about the stray start <td> tag in the markup. Which is not strange since according to the documentation, the <tr> element can only be used inside the table tags (<thead>, <tbody>, <tfoot>, <table>).

Can I Include

Of course you don’t have to memorize all types of content but sometimes you should look there when you are not sure whether something is broken.

By analogy with Can I Use, the Can Include tool has been developed that can help us with this.

The main page of the caniuse.com website.
The main page of the caniuse.com website.

With this tool, we can check if we can nest one element into another.

We can check this in the official documentation but with CanInclude we can do it faster since its interface is simpler for this than the documentation.

Conclusions

HTML may break or may not look as expected and that's okay. It's not bad HTML it just has its own rules. You just need to understand that something could break just because of incorrect nesting and know where it can be quickly checked.

In general, there are 7 types of content that expect a certain nesting into each other. Each HTML element has its own category and its own type of content that it can have. You don't have to memorize them all but sometimes when you have doubts or something is broken you can look at the documentation, check your code in the HTML validator or use the CanInclude tool to check yourself.

Webmentions

If you liked this article and think others should read it, please share it. Leave comments on platforms such as dev.to, twitter.com, etc., and they will magically appear here ✨

  • 0 reposts
  • 0 comments

These are webmentions via the IndieWeb and webmention.io. Mention this post from your site:

Not an Easter Egg (but actually it is, yes 😁)