HTML Nested Lists
Think about a book's table of contents. It lists chapters. Under each chapter, it lists sections. Under some sections, it lists subsections. The information has a tree shape: big groups hold smaller groups, which hold even smaller ones.
A flat list cannot show that. For a tree, HTML lets you put a list inside a list. This is called a nested list, and it is how outlines, sub-menus, folder structures, and multi-level instructions are built. The idea is simple, but there is one rule that beginners get wrong again and again. This lesson makes sure you do not.
What You Will Learnβ
- What a nested list is, and when to use one
- The golden rule: where the inner list must go
- How to nest
<ul>and<ol>, and how to mix them - How browsers change the markers on each level
- Real-world patterns: outlines, sub-menus, and multi-level steps
- How to number levels as 1, 1.1, 1.2 with CSS
- Accessibility, depth limits, and common mistakes
The Golden Ruleβ
A nested list goes inside an
<li>, not beside it.
An inner list is not a separate sibling of the items. It belongs to one specific item, the one it describes. So you open an <li>, write the item's text, and then place the new list inside the same <li> before closing it.
- HTML Code
- Browser Output
<ul>
<li>Fruits
<ul>
<li>Apple</li>
<li>Mango</li>
</ul>
</li>
<li>Vegetables
<ul>
<li>Carrot</li>
<li>Spinach</li>
</ul>
</li>
</ul>
Fruits
- Apple
- Mango
Vegetables
- Carrot
- Spinach
Read the structure like a family tree:
- The outer
<ul>has two items: "Fruits" and "Vegetables." - Each of those items owns an inner
<ul>. - The inner list is a child of its
<li>, so it shows indented under its parent.
The Mistake to Avoidβ
Putting the inner list directly inside the outer <ul>, as a neighbor of the <li> items, is invalid.
- Invalid
- Valid
<ul>
<li>Fruits</li>
<ul> <!-- β a ul directly inside a ul -->
<li>Apple</li>
<li>Mango</li>
</ul>
<li>Vegetables</li>
</ul>
<ul>
<li>Fruits
<ul> <!-- β
the ul sits inside the li -->
<li>Apple</li>
<li>Mango</li>
</ul>
</li>
<li>Vegetables</li>
</ul>
Browsers usually still indent the invalid version, so it looks right. But the structure is wrong: the sub-list does not belong to any item. Screen readers may announce the levels incorrectly, CSS rules that target li > ul will not match, and validators will flag it. Fix the structure, not just the look.
Where Exactly Does the Inner List Go?β
The inner list can appear after the item's text, inside the same <li>. If you want to style or link the text, wrap it so the inner list stays separate:
<li>
<a href="/html">HTML</a> <!-- the item's own content -->
<ul> <!-- its sub-list -->
<li><a href="/html/lists">Lists</a></li>
</ul>
</li>
Always write the item's own text before the nested list. The text names the group, and the list holds its members.
Nesting Ordered Listsβ
You can nest <ol> inside <ol>. Each inner list restarts at 1 by default.
- HTML Code
- Browser Output
<h3>Launch a website</h3>
<ol>
<li>Plan
<ol>
<li>Choose a goal.</li>
<li>Sketch the pages.</li>
</ol>
</li>
<li>Build
<ol>
<li>Write the HTML.</li>
<li>Add the CSS.</li>
</ol>
</li>
<li>Publish</li>
</ol>
Launch a website
Plan
- Choose a goal.
- Sketch the pages.
Build
- Write the HTML.
- Add the CSS.
- Publish
To tell the levels apart at a glance, give each level a different style with the type attribute (or CSS). Legal documents and outlines often use 1, a, i.
- HTML Code
- Browser Output
<ol>
<li>Setup
<ol type="a">
<li>Install the editor.
<ol type="i">
<li>Download it.</li>
<li>Run the installer.</li>
</ol>
</li>
<li>Create a folder.</li>
</ol>
</li>
</ol>
Setup
Install the editor.
- Download it.
- Run the installer.
Create a folder.
Mixing List Typesβ
You can combine list types freely. The rule stays the same: the inner list goes inside an <li>.
| Outer | Inner | Good for |
|---|---|---|
<ol> | <ul> | Steps that each have unordered notes or options |
<ul> | <ol> | Groups where one group has a sequence |
<ul> | <dl> | Categories that hold term-and-meaning pairs |
| Any | Any | Whatever the content needs |
- HTML Code
- Browser Output
<h3>Set up your project</h3>
<ol>
<li>Create a folder named <code>my-site</code>.</li>
<li>Add these files:
<ul>
<li><code>index.html</code></li>
<li><code>style.css</code></li>
<li><code>script.js</code></li>
</ul>
</li>
<li>Open <code>index.html</code> in your browser.</li>
</ol>
Set up your project
- Create a folder named
my-site. Add these files:
index.htmlstyle.cssscript.js
- Open
index.htmlin your browser.
How Browsers Change the Markersβ
For nested bullet lists, browsers automatically use a different marker on each level, so you can see the depth.
| Level | Default marker | CSS name |
|---|---|---|
| 1 (top) | Solid circle β | disc |
| 2 | Hollow circle β | circle |
| 3 and deeper | Solid square β | square |
- HTML Code
- Browser Output
<ul>
<li>Level 1
<ul>
<li>Level 2
<ul>
<li>Level 3</li>
</ul>
</li>
</ul>
</li>
</ul>
Level 1
Level 2
- Level 3
You can change these with CSS, which you will learn in Styling Lists. Numbered lists do not change automatically, so use type or CSS to tell their levels apart.
Real-World Examplesβ
1. A Site Map or Course Outlineβ
- HTML Code
- Browser Output
<h3>HTML course outline</h3>
<ul>
<li>Text content
<ul>
<li>Headings</li>
<li>Paragraphs</li>
</ul>
</li>
<li>Links and navigation
<ul>
<li>Anchor element</li>
<li>Navigation menus</li>
</ul>
</li>
<li>Images</li>
</ul>
HTML course outline
Text content
- Headings
- Paragraphs
Links and navigation
- Anchor element
- Navigation menus
- Images
2. A Navigation Menu with a Sub-Menuβ
Sub-menus and dropdowns are nested lists. The HTML below is the structure only. CSS (and sometimes JavaScript) turns it into a dropdown.
<nav aria-label="Main">
<ul>
<li><a href="/">Home</a></li>
<li>
<a href="/courses">Courses</a>
<ul>
<li><a href="/courses/html">HTML</a></li>
<li><a href="/courses/css">CSS</a></li>
<li><a href="/courses/js">JavaScript</a></li>
</ul>
</li>
<li><a href="/about">About</a></li>
</ul>
</nav>
Even without any CSS, this still works as a clear, accessible outline of the site. That is the benefit of building structure first.
3. A File and Folder Treeβ
Folders contain files and other folders, which is a natural tree.
- HTML Code
- Browser Output
<ul>
<li>my-site/
<ul>
<li>index.html</li>
<li>css/
<ul>
<li>style.css</li>
</ul>
</li>
<li>images/
<ul>
<li>logo.svg</li>
</ul>
</li>
</ul>
</li>
</ul>
my-site/
- index.html
css/
- style.css
images/
- logo.svg
4. A Comment Threadβ
Replies sit under the comment they answer.
<ul>
<li>
<p><strong>Linh:</strong> Great lesson!</p>
<ul>
<li><p><strong>Mateo:</strong> Agreed. The examples helped.</p></li>
</ul>
</li>
</ul>
Numbering Levels as 1, 1.1, 1.2β
Legal documents and technical specs often number sub-items as 1.1, 1.2, and 2.1. HTML does not do this on its own, but a small CSS trick called counters does.
ol.outline {
counter-reset: item;
list-style: none;
padding-left: 0;
}
ol.outline li {
counter-increment: item;
}
ol.outline li::before {
content: counters(item, ".") " ";
font-weight: 700;
}
ol.outline ol {
counter-reset: item;
list-style: none;
padding-left: 1.5rem;
}
<ol class="outline">
<li>Introduction
<ol>
<li>Purpose</li>
<li>Scope</li>
</ol>
</li>
<li>Method</li>
</ol>
The result reads: 1 Introduction, 1.1 Purpose, 1.2 Scope, 2 Method. The counters() function joins the number of every level with a dot. You will learn more about counters in Styling Lists.
How Deep Should You Go?β
You can nest as deeply as you like, but you should not.
- Two levels is comfortable for almost everyone.
- Three levels is the practical limit for most pages.
- Four or more is a sign to rethink: break the content into separate sections with headings, or into several pages.
Deep nesting is hard to read on a small phone screen, because each level pushes the text further to the right. It is also tiring for screen reader users, who hear every level announced.
If you need to scroll sideways, or squint to see which list an item belongs to, the nesting is too deep. Flatten it with headings.
Accessibility at a Glanceβ
- Screen readers announce nesting, such as "list, 3 items, nested level 2," so people know where they are in the tree. This only works when your structure is correct. The inner list must be inside an
<li>. - Keep the level count low. Every level is more to listen to.
- Make each parent item a clear label for its children. "Fruits" works. "Other" does not.
- Do not use nested lists just for indentation. Use CSS for spacing.
- In navigation, a
<nav>with a cleararia-labelplus nested lists gives screen reader users a quick map of your site.
Common Mistakes to Avoidβ
- Placing the inner list beside the
<li>, directly inside<ul>or<ol>. It belongs inside the<li>. - Closing the
<li>before the inner list. Put the nested list before the closing</li>. - Mismatched or missing closing tags. Deep trees make this easy. Indent your code consistently so each pair lines up.
- Nesting too deep. More than three levels is hard to read.
- Using nesting for indentation only. If it is not a real hierarchy, do not nest.
- Typing manual numbers like "1.1" in the text. Use counters, so numbers update by themselves.
- Vague parent labels such as "More" or "Other."
- Forgetting that numbered levels look the same unless you set
typeor CSS.
Practice Timeβ
Try these in your editor:
- Write a bullet list of three food groups, each with two items inside.
- Write the same data as a numbered list, and set a different
typefor the inner level. - Make a three-step ordered list where step 2 has a bullet list of options.
- Build a "My project" folder tree with at least three levels.
- Build a navigation menu with one item that has a sub-menu.
- Turn the invalid example from this page into a valid one.
- Use
type="a"andtype="i"to create a three-level outline. - Add the counter CSS to get 1, 1.1, 1.2 numbering.
- Add a comment thread with one reply.
- Bonus: use your browser's developer tools to inspect the tree and confirm each inner
<ul>sits inside an<li>.
Quick Recapβ
Click a question to check your answer.
1. Where must a nested list go?
Inside an <li> element, after that item's own text, and before the closing </li>. It must not sit directly inside the outer <ul> or <ol>.
2. Can you nest an ordered list inside an unordered list?
Yes. You can mix <ul>, <ol>, and even <dl>, as long as each inner list sits inside an <li>.
3. How do browsers mark the levels of a nested bullet list?
By default they use a disc at the first level, a circle at the second, and a square at the third and deeper levels.
4. How can you number levels as 1, 1.1, 1.2?
With CSS counters: counter-reset and counter-increment, plus counters(item, ".") in a ::before rule.
5. How deep should a nested list be?
Two levels is comfortable and three is usually the limit. Beyond that, split the content with headings or separate pages.
Key Takeawaysβ
- A nested list is a list inside an
<li>. That is the golden rule. - You can nest
<ul>,<ol>, and<dl>in any combination. - Browsers change bullet markers by level. Numbered levels need
typeor CSS to look different. - Outlines, sub-menus, file trees, and comment threads are all nested lists.
- Keep nesting shallow, label parents clearly, and let CSS handle indentation and multi-level numbers.
Your lists can now hold a whole hierarchy, but they still look plain. Next, learn how to change markers, spacing, and layout in Styling Lists, or go back to the Lists overview.