Ordered Lists in HTML
Learn how ordered lists in HTML work with the ol tag, type attribute for numbers, letters, Roman numerals, start, reversed, and value attributes.
In the previous article, we went through unordered lists: bullet points, the <ul> tag, and when to reach for them. If you went through that one, you already know how <li> works and how browsers handle list rendering by default.
Now we’re adding a very important layer: ordered lists in HTML. This is the kind of list where sequence matters. Step 1 needs to happen before Step 2. The first ingredient in a process isn’t interchangeable with the fifth. When that’s the case, you need an ordered list.
And there’s a lot more here than just slapping numbers on items. The HTML <ol> element gives you full control over numbering styles, starting values, countdown lists, and number jumps. By the end of this article, you’ll know exactly how each piece works, when to use it, and how to build clean, semantic, step-by-step content.
Let’s get into it.
01What Are Ordered Lists in HTML?
An ordered list in HTML is a list where each item is automatically given a sequential marker: by default, a number (1, 2, 3…). That sequence communicates something meaningful: the order of items is intentional and matters.
The HTML element that creates an ordered list is <ol>. Each item inside it lives in an <li> tag, exactly like you used with <ul>. The only difference at this stage is the parent tag: <ul> gives bullets, <ol> gives numbers.
The browser handles the counting entirely on its own. You write the items. The browser figures out 1, 2, 3 automatically. No manual typing of numbers needed.
This matters more than it sounds. Because those numbers aren’t just visual decorations: they carry semantic meaning. Screen readers announce the list and read each numbered item. Search engines understand that the content is sequential. Swapping items changes the meaning of the page, and HTML communicates that clearly through the <ol> element.
02Writing Your First Numbered List
Here’s the most basic ordered list you can write. Same pattern as a <ul>, just swap the parent tag:
<ol>
<li>Preheat the oven to 200°C</li>
<li>Mix the dry ingredients in a bowl</li>
<li>Add butter and stir until crumbly</li>
<li>Pour into the pan and bake for 30 minutes</li>
</ol>
The browser renders that with numbers 1, 2, 3, 4. Clean, automatic, and semantically correct. You didn’t write a single number.
Every <li> inside an <ol> is technically called a list item. The <ol> tag itself is the container. You cannot put raw text directly inside <ol> without wrapping it in <li>. That would be invalid HTML.
03When an Ordered List Makes More Sense Than an Unordered One
The deciding question is simple: does the order of these items actually matter?
If you rearrange item 3 and item 1, does it break the logic or cause confusion? Yes? Use <ol>. No? Use <ul>. That’s the whole rule.
Order does not matter
- Salt
- Olive oil
- Garlic cloves
- Black pepper
Sequence is intentional
- Mince the garlic
- Heat olive oil in a pan
- Add garlic, stir for 1 minute
- Season with salt and pepper
Ingredients? Use <ul>. You can grab salt before garlic with no issue. Cooking steps? Use <ol>. Heating the pan before adding garlic matters. Reversing those steps produces a different (and worse) result.
This isn’t just about visual style. Using the correct element tells browsers, assistive technologies, and search engines what kind of content this is. Semantics matter. If you want a deeper look at why, our article on semantic HTML walks through this in full.
04The type Attribute: Five Numbering Styles Built Right In
By default, ordered lists in HTML use Arabic numerals: 1, 2, 3. But sometimes you need letters, or Roman numerals, for outlines, legal documents, academic writing, or multilevel structures.
The type attribute on <ol> handles all of that. There are five values, and each produces a completely different marker style.
- Item
- Item
- Item
- Item
Default
- Item
- Item
- Item
- Item
Uppercase
- Item
- Item
- Item
- Item
Lowercase
- Item
- Item
- Item
- Item
Roman Upper
- Item
- Item
- Item
- Item
Roman Lower
Numbers by Default: type=”1″
This is the default. You don’t even need to write it. But you can include it explicitly if you want your code to be clear about intent, especially in teams or when using mixed list types on the same page.
<ol type="1">
<li>Download the installer</li>
<li>Run it as administrator</li>
<li>Follow the setup wizard</li>
</ol>
Letters in Both Cases: type=”A” and type=”a”
Uppercase letters (A, B, C…) are common in formal outlines, legal documents, and structured reports. Lowercase letters (a, b, c…) work well for sub-items inside a larger numbered list, like sub-sections of a chapter.
<!-- Uppercase Letters -->
<ol type="A">
<li>Introduction</li>
<li>Background</li>
<li>Methodology</li>
<li>Results</li>
</ol>
<!-- Lowercase Letters -->
<ol type="a">
<li>Sub-section one</li>
<li>Sub-section two</li>
<li>Sub-section three</li>
</ol>
Roman Numerals: type=”I” and type=”i”
Roman numerals carry a formal, classic look. Great for book chapters, legal clauses, or anywhere that numbered sections feel too casual.
<!-- Uppercase Roman Numerals -->
<ol type="I">
<li>Chapter One: The Beginning</li>
<li>Chapter Two: Rising Action</li>
<li>Chapter Three: The Turning Point</li>
</ol>
<!-- Lowercase Roman Numerals -->
<ol type="i">
<li>Clause one</li>
<li>Clause two</li>
<li>Clause three</li>
</ol>
The type attribute is valid in HTML5 and it does more than visual styling: it defines the actual counting system, which assistive technologies like screen readers understand. For purely cosmetic changes, the CSS property list-style-type is recommended and takes visual precedence. We’ll touch on this in the CSS section below. If the marker type carries semantic meaning (like Roman numerals for legal sections), using the HTML attribute is the right call.
05The start Attribute: Control Where Counting Begins
By default, ordered lists start counting from 1. But what if you need to continue a numbered sequence from a previous section? Or start a “Top 10” list at 10 and count down? The start attribute is exactly what you need.
This one saved me a lot of headaches when I was building a multi-part tutorial. Part 1 covered steps 1 to 4. Part 2 needed to continue from step 5. Without start, you’d have to merge everything into one giant list or number things manually in the text, both bad options.
<!-- Part 1 -->
<ol>
<li>Install Node.js from the official website</li>
<li>Open your terminal</li>
<li>Run: node --version to confirm installation</li>
<li>Create a new project folder</li>
</ol>
<p>Continued in Part 2:</p>
<!-- Part 2 continues from step 5 -->
<ol start="5">
<li>Initialize the project with npm init</li>
<li>Install your first dependency</li>
<li>Create your entry file: index.js</li>
</ol>
- Install Node.js
- Open terminal
- Verify version
- Create folder
- Initialize project
- Install dependencies
- Create index.js
- Run your first script
There’s one important detail about the start attribute: it always takes an integer, even when you’re using letters or Roman numerals as your type.
So if you write <ol type="A" start="3">, the list starts at the third letter: C, D, E…
<!-- Starts at C (3rd letter), not A -->
<ol type="A" start="3">
<li>Third section</li>
<li>Fourth section</li>
<li>Fifth section</li>
</ol>
The same rule applies to Roman numerals. start="4" with type="I" gives you IV, V, VI… The start attribute always means “start at the Nth item of whatever type I’m using.”
06The reversed Attribute: Lists That Count Down
The reversed attribute is a boolean attribute, which means you just add the word to the tag. No value needed. It flips the direction of counting so the list counts down instead of up.
<ol reversed>
<li>The Dark Knight</li>
<li>Inception</li>
<li>Interstellar</li>
<li>Oppenheimer</li>
<li>Tenet</li>
</ol>
That list renders as: 5, 4, 3, 2, 1. The items are still written in the order you placed them in the HTML. The list does not reorder your content. Only the numbers change direction.
This is useful for Top 10 style content, countdown sequences, or any situation where the biggest number should appear first.
You can also combine reversed with start to get very specific control:
<!-- Counts down: 10, 9, 8, 7, 6 -->
<ol reversed start="10">
<li>Best in show</li>
<li>Runner-up</li>
<li>Third place</li>
<li>Fourth place</li>
<li>Fifth place</li>
</ol>
- Bronze medal
- Silver medal
- Gold medal
- Bronze medal
- Silver medal
- Gold medal
- 10th place finish
- 9th place finish
- 8th place finish
- Fifth item
- Sixth item
- Seventh item
reversed does not reorder your HTML content. Your list items stay exactly in the order you wrote them. Only the numbers on the left count down. If your Top 10 list shows #10 at the top and #1 at the bottom, that’s because the numbers count down, not because the items moved.
07The value Attribute on List Items: Jumping to Any Number
Sometimes you need to skip to a specific number in the middle of a list. Maybe you’re resuming after some items were removed, or your content has a natural gap in sequence. The value attribute on an individual <li> element lets you set the number for that specific item.
And here’s the important part: all items after that one continue counting from the new value.
<ol>
<li>Introduction to the project</li>
<li>Setting up your environment</li>
<li value="10">Advanced configuration (optional)</li>
<li>Testing and deployment</li>
<li>Going live</li>
</ol>
That renders as: 1, 2, 10, 11, 12. The third item jumps to 10, and everything after continues from there.
- Introduction
- Setup
- Configuration
- Testing
- Deployment
- Introduction
- Setup
- Configuration (jumped to 10)
- Testing (now 11)
- Deployment (now 12)
This attribute is not something you’ll use every day, but when you’re building documentation with optional or skipped sections, it’s exactly the right solution.
08Building Real Step-by-Step Content with Ordered Lists in HTML
This is honestly where ordered lists earn their place. Step-by-step content: tutorials, recipes, installation guides, process documentation, anything where the user must follow a specific sequence, is one of the most common things on the web. And <ol> is semantically built for it.
When a screen reader encounters an ordered list, it tells the user: “List with 6 items.” Then it reads each item with its number. That’s exactly the experience you want for a tutorial. The user knows there are 6 steps. They know which step they’re on. The structure communicates the process, not just the words.
Here’s a real-world example: a setup guide formatted as a proper ordered list:
<h2>How to Set Up Git on Your Computer</h2>
<ol>
<li>
<strong>Download Git</strong> from git-scm.com and run the installer.
Accept the default options unless you know what you're changing.
</li>
<li>
<strong>Open your terminal</strong> (Command Prompt on Windows, Terminal on Mac/Linux).
</li>
<li>
<strong>Confirm the installation</strong> by running:
<code>git --version</code>
You should see a version number like <code>git version 2.43.0</code>.
</li>
<li>
<strong>Set your username:</strong>
<code>git config --global user.name "Your Name"</code>
</li>
<li>
<strong>Set your email:</strong>
<code>git config --global user.email "[email protected]"</code>
</li>
<li>
<strong>You're ready.</strong> Run <code>git init</code> inside any project folder to start tracking it.
</li>
</ol>
And here’s what that structure looks like rendered:
How to Set Up Git on Your Computer
A real-world step-by-step guide using <ol>
- Download Git from git-scm.com and run the installer. Accept the default options unless you know what you’re changing.
- Open your terminal (Command Prompt on Windows, Terminal on Mac/Linux).
- Confirm the installation by running:
git --version. You should see a version number likegit version 2.43.0. - Set your username:
git config --global user.name "Your Name" - Set your email:
git config --global user.email "[email protected]" - You’re ready. Run
git initinside any project folder to start tracking it.
Notice what’s happening here: the <ol> handles all the numbering. The content inside each <li> can include other elements like <strong>, <code>, links, or even images. The list item itself is just a container for whatever belongs to that step.
09A Quick Look at Nested Ordered Lists
You can place a list inside a list. This is called nesting, and it works naturally with ordered lists just like it does with unordered ones.
<ol>
<li>
Frontend Development
<ol type="a">
<li>HTML structure</li>
<li>CSS styling</li>
<li>JavaScript interactivity</li>
</ol>
</li>
<li>
Backend Development
<ol type="a">
<li>Server setup</li>
<li>Database design</li>
<li>API creation</li>
</ol>
</li>
<li>Deployment and Hosting</li>
</ol>
And here’s how that renders:
-
Frontend Development
- HTML structure
- CSS styling
- JavaScript interactivity
-
Backend Development
- Server setup
- Database design
- API creation
- Deployment and Hosting
The inner list starts its own counter from 1 (or whatever start you set). You can mix types freely: outer numbers, inner lowercase letters, or any combination that fits your content structure.
Nesting is a complete topic on its own, covering proper hierarchy, accessibility with screen readers, combining list types, and building outlines. The next article in this series, Understanding Nested Lists, goes deep on all of it. What you see here is just the foundation.
10Giving Ordered Lists a Custom Look with CSS
The type attribute controls the numbering style in HTML. CSS gives you even more control, and for styling purposes, CSS is usually the preferred approach because it separates presentation from structure.
The key CSS property is list-style-type. It accepts a wide range of values beyond what the HTML type attribute offers:
<style>
.steps-decimal-zero {
list-style-type: decimal-leading-zero; /* 01, 02, 03 */
}
.steps-upper-roman {
list-style-type: upper-roman;
}
.steps-upper-alpha {
list-style-type: upper-alpha;
}
</style>
<ol class="steps-decimal-zero">
<li>Step one</li>
<li>Step two</li>
<li>Step three</li>
</ol>
- Section
- Section
- Section
- Clause
- Clause
- Clause
- Step
- Step
- Step
You can also control the position of the marker with list-style-position. The value outside (default) keeps the number to the left of the content. The value inside brings it inside the content box, useful when you want text wrapping to align under the first character rather than under the number.
<style>
ol {
list-style-position: outside; /* default */
padding-left: 1.5rem;
}
ol.inside-marker {
list-style-position: inside;
padding-left: 0;
}
</style>
To completely remove the default styling and build your own from scratch, you can use:
<style>
ol.custom {
list-style: none;
padding: 0;
margin: 0;
counter-reset: my-counter;
}
ol.custom li {
counter-increment: my-counter;
padding: 8px 0 8px 36px;
position: relative;
}
ol.custom li::before {
content: counter(my-counter);
position: absolute;
left: 0;
width: 24px;
height: 24px;
background: #6366f1;
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
}
</style>
That last example uses CSS counters, which are a more advanced CSS feature. We’re only introducing them here: they belong to the CSS series we’ll cover in full later. Don’t worry if that code looks unfamiliar right now.
11Ordered Lists and Screen Readers
Accessibility with ordered lists works fairly naturally because the semantic meaning is built into the element. A screen reader will announce something like: “Numbered list, 5 items” and then read each item with its number. That’s exactly the experience you want.
A few things worth keeping in mind:
First, the type attribute carries meaning for assistive technologies. If you use type="A" and the letters genuinely represent sections (A, B, C meaning something in the document), the HTML attribute is the right choice because it communicates that to screen readers. If you’re just changing the look for visual purposes, use CSS instead.
Second, each list item’s text should be understandable on its own. When a screen reader cycles through items, each one gets read in isolation. “Step 3” followed by “Add the eggs” makes sense. Just “And stir” does not.
Third, avoid using ordered lists purely for indentation or layout. If there’s no actual sequence, the list element is communicating false information to assistive technologies. Use semantic HTML that matches your content.
12Mistakes That Often Trip Up Beginners
-
Using <ol> when order doesn’t matter
If you’re listing features, team members, or navigation links, those are unordered lists. Using<ol>tells browsers and screen readers that sequence is meaningful. If it isn’t, reach for<ul>instead. -
Typing numbers manually instead of using <ol>
A lot of beginners write “1. Step one”, “2. Step two” as paragraph text. This looks the same visually, but it’s semantically meaningless, not accessible, and a maintenance nightmare (renumbering manually when you add a step is painful). Use the real<ol>element. -
Forgetting to wrap items in <li>
Text placed directly inside<ol>without an<li>tag is invalid HTML. Every item needs its wrapper. Browsers may render it anyway, but the markup is broken and behavior across browsers may differ. -
Setting start with a non-integer value
Thestartattribute only accepts integers. Writingstart="C"orstart="iii"does nothing. To start at the third letter, usetype="A" start="3". -
Thinking reversed reorders the HTML
reversedonly flips the numbering. The actual items in your HTML stay in the order you wrote them. The visual order of the numbers changes, not the content. If your Top 10 shows #10 at the top, the person at position #10 is still the first<li>in your code.
13The Complete ol Tag Reference
Here’s everything we covered, condensed into one place for quick reference:
Ordered List Attributes at a Glance
| Attribute | Goes On | Accepted Values | What It Does |
|---|---|---|---|
| type | <ol> | 1AaIi | Sets the marker style: decimal numbers, uppercase or lowercase letters, uppercase or lowercase Roman numerals. |
| start | <ol> | Any integer, e.g. 5 or 10 | Sets the starting value for the first list item. Always an integer, even when using letter or Roman numeral types. |
| reversed | <ol> | Boolean (no value needed) | Makes the list count down instead of up. The items stay in their original HTML order. Only the numbers reverse. |
| value | <li> | Any integer, e.g. 10 or 20 | Overrides the counter for that specific item. All following items continue from this new value. |
list-style-type |
CSS property | decimal upper-alpha lower-roman and more | CSS equivalent for controlling marker style. Visually overrides the HTML type attribute. Use for purely visual styling. |
list-style-position |
CSS property | outside inside | Controls whether the marker sits outside or inside the list item’s content box. Default is outside. |
14Things You Can Build Now
You now understand ordered lists in HTML well enough to use them properly. Not just slapping <ol> on some items, but controlling the numbering style, starting value, counting direction, and individual item values. You can build real step-by-step tutorials, structured outlines with letters and Roman numerals, multi-part guides that continue seamlessly across sections, and countdown content that counts down properly.
The next article in this series is on Description Lists: the <dl> element, along with <dt> and <dd>. It’s one of the most underused elements in HTML, and it’s genuinely powerful for glossaries, FAQs, and term-definition pairs. Worth knowing.
Keep writing real code. Every small element you learn properly adds up to a much stronger foundation.
Ordered Lists in HTML
Loading challenge…
Ready to Practice?
Select a difficulty level above to load your challenge.