CSS Tutorial

CSS Lists Tutorial: list-style-type, list-style-position & Custom Markers (2026-27 Guide)

By Pramod Behera  ·  Updated: June 2026  ·  12 min read
✅ In this CSS Tutorial – CSS Lists: Complete Guide to Styling Ordered & Unordered Lists

Today we are discuss topic CSS Lists. Every bulleted or numbered list on the web starts from the humble <ul> or <ol> tag, but by default browsers apply plain round bullets or simple numerals that rarely match a site's design. CSS gives you complete control over how list markers look -their shape, their position, whether they're an image or even a fully custom ::marker style, and how list items are laid out (vertical, horizontal, or grid-based navigation). In this complete guide you will master list-style-type, list-style-position, list-style-image, the list-style shorthand, the modern ::marker pseudo-element, removing bullets for navigation menus, building horizontal nav lists, and CSS counters. Includes live code panels, an interactive list-style playground, comparison tables, common mistakes, a quiz, and FAQ -everything you need to write professional, accessible CSS list styling. This tutorial or document breaks down the process step by step, using simple language and real-world examples to help you master the skill.

📋 Table of Contents

  1. What Are CSS Lists?
  2. list-style-type
  3. list-style-position
  4. list-style-image
  5. The list-style Shorthand
  6. Removing Bullets & Indentation
  7. Styling Markers with ::marker
  8. Horizontal Lists & Navigation Menus
  9. Nested Lists
  10. CSS Counters for Custom Numbering
  11. List Properties – Reference Table
  12. Best Practices
  13. Common Mistakes to Avoid
  14. Live Code Example
  15. Try It Yourself – Interactive Editor
  16. 🎨 Interactive List-Style Playground
  17. Practice Quiz
  18. Frequently Asked Questions (FAQ)

✅ What Are CSS Lists?

A CSS list refers to styling applied to HTML's two native list elements: <ul> (unordered list, normally bulleted) and <ol> (ordered list, normally numbered), each containing one or more <li> (list item) children. Without any CSS, browsers apply default markers -round bullets for <ul> and sequential numbers for <ol> -plus a left indent. CSS lets you fully override the marker style, its position, its image, and even the entire layout direction of the list.

<!-- Unordered list -->
<ul>
  <li>HTML</li>
  <li>CSS</li>
  <li>JavaScript</li>
</ul>

<!-- Ordered list -->
<ol>
  <li>Plan the layout</li>
  <li>Write the HTML</li>
  <li>Style with CSS</li>
</ol>
🔘
list-style-type
Chooses the bullet or numbering style.
↔️
list-style-position
Marker inside or outside the content box.
🖼️
list-style-image
Replaces the marker with a custom image.
🎯
::marker
Styles the marker itself independently.
💡 Key Concept: Lists are not just for bullet points -almost every navigation menu, breadcrumb trail, tag cloud, and step-by-step wizard on the modern web is secretly built from a styled <ul> or <ol>, because lists are the most semantically correct way to group related items.

✅ list-style-type

list-style-type sets the marker shown before each list item. Unordered lists typically use shape-based markers, while ordered lists use numbering systems:

/* Unordered list markers */
ul.disc   { list-style-type: disc;   }  /* ● default */
ul.circle { list-style-type: circle; }  /* ○ hollow circle */
ul.square { list-style-type: square; }  /* ■ filled square */
ul.none   { list-style-type: none;   }  /* no marker */

/* Ordered list markers */
ol.decimal     { list-style-type: decimal;     }  /* 1. 2. 3. */
ol.lower-roman { list-style-type: lower-roman;  }  /* i. ii. iii. */
ol.upper-roman { list-style-type: upper-roman;  }  /* I. II. III. */
ol.lower-alpha { list-style-type: lower-alpha;  }  /* a. b. c. */
ol.upper-alpha { list-style-type: upper-alpha;  }  /* A. B. C. */
list-style-type – Live Preview
.disc { list-style-type: disc; }
.circle { list-style-type: circle; }
.square { list-style-type: square; }

.roman { list-style-type: upper-roman; }
👁 Live Output
  • Disc
  • Item two
  • Circle
  • Item two
  • Square
  • Item two
  1. Roman
  2. Item two
ℹ️ Full value list: disc · circle · square · decimal · decimal-leading-zero · lower-roman · upper-roman · lower-alpha · upper-alpha · lower-greek · none

✅ list-style-position

list-style-position controls whether the marker sits outside the content box (the default) or inside it. This becomes visible the moment a list item's text wraps onto a second line.

list-style-position: outside vs inside
.pos-outside {
  list-style-position: outside; /* default */
}

.pos-inside {
  list-style-position: inside;
}
👁 Live Output (note the wrapped line)

outside (default):

  • This is a long list item that wraps to a second line

inside:

  • This is a long list item that wraps to a second line
⚠️ Visual difference: With outside, the wrapped second line aligns with the FIRST line's text (not the marker). With inside, the marker behaves like the first inline word, so the wrapped line aligns with the marker's left edge instead -a subtle but noticeable difference in multi-line list items.

✅ list-style-image

list-style-image replaces the default bullet with a small custom image:

ul.custom-icon {
  list-style-image: url('checkmark.png');
}

/* Modern alternative with more control: */
ul.custom-icon-modern {
  list-style: none;
  padding-left: 0;
}
ul.custom-icon-modern li {
  padding-left: 28px;
  background: url('checkmark.png') no-repeat left center;
  background-size: 18px 18px;
}
⚠️ Why most developers avoid list-style-image: It offers almost no control over the image's size, vertical alignment, or spacing from the text, and behaves inconsistently across browsers. The modern alternative -list-style: none plus a background-image or an inline SVG via ::before -gives far more precise, consistent control.

✅ The list-style Shorthand

The list-style shorthand combines list-style-type, list-style-position, and list-style-image into a single declaration, in any order:

list-style Shorthand Example
/* type position image */
ul {
  list-style: square inside;
}

/* Equivalent to writing: */
ul {
  list-style-type: square;
  list-style-position: inside;
}
👁 Live Output
  • First item
  • Second item
  • Third item

✅ Removing Bullets & Indentation

The most common real-world use of CSS lists is removing the default bullet and indentation -the first step in turning a semantic list into a navigation bar, card grid, or custom layout.

Removing Bullets & Indentation
ul.clean {
  list-style: none;
  margin: 0;
  padding: 0;
}
👁 Live Output

Before (default browser styling):

  • Item one
  • Item two

After (list-style: none; margin: 0; padding: 0;):

  • Item one
  • Item two
💡 Tip: Always set both list-style: none AND margin: 0; padding: 0; together. Removing only the marker leaves the browser's default indentation in place, which is a very common partial-fix mistake.

✅ Styling Markers with ::marker

The modern ::marker pseudo-element lets you style the bullet or number itself -independently from the list item's text -without removing it and rebuilding it manually.

::marker Custom Styling
li::marker {
  color: #0EA5E9;
  font-weight: 700;
  font-size: 1.2em;
}

/* Even custom text content */
.checklist li::marker {
  content: "✅ ";
}
👁 Live Output
  •   Bold, colored marker via ::marker
  •   Marker color is independent of text
  • ✅ Custom marker content
  • ✅ Great for checklists
ℹ️ Browser support: ::marker is supported in all modern browsers (Chrome 86+, Firefox 68+, Safari 11.1+). Only a limited set of properties apply inside it: color, font-*, content, white-space, and a few text-related properties -not full box-model properties like padding or width.

✅ Horizontal Lists & Navigation Menus

Almost every horizontal navigation bar on the web is a <ul> with bullets removed and its items laid out in a row using display: flex or inline-block.

Horizontal Navigation List
nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 6px;
}

nav a {
  display: block;
  padding: 8px 14px;
  border-radius: 6px;
}
👁 Live Output
💡 Why use a list for navigation: Wrapping nav links in <ul>/<li> instead of plain <a> tags side-by-side is the more semantically correct approach -screen readers announce "list of 4 items" and let keyboard/assistive-tech users navigate the group more easily, which directly benefits both accessibility and SEO.

✅ Nested Lists

Lists can be nested inside one another -a common pattern for multi-level navigation menus, table-of-contents widgets, and outlines. Each nested level gets its own list-style-type automatically in many browsers, but it's best to set it explicitly:

Nested List Example
ul { list-style-type: disc; }
ul ul { list-style-type: circle; }
ul ul ul { list-style-type: square; }
👁 Live Output
  • Frontend
    • HTML
    • CSS
      • Box Model
      • Flexbox

✅ CSS Counters for Custom Numbering

For full control over numbering style -beyond what list-style-type offers -CSS counters let you generate fully custom numbering, including multi-level "1.1, 1.2, 2.1" style outlines.

CSS Counters – Custom Numbering
ol.custom-counter {
  list-style: none;
  counter-reset: step;
}
ol.custom-counter li {
  counter-increment: step;
}
ol.custom-counter li::before {
  content: "Step " counter(step) ": ";
  font-weight: 700;
  color: #0EA5E9;
}
👁 Live Output
  1. Step 1: Plan your layout
  2. Step 2: Write the HTML
  3. Step 3: Style with CSS

✅ List Properties – Reference Table

PropertyCommon ValuesWhat It Controls
list-style-typedisc · circle · square · decimal · upper-roman · noneThe marker shape or numbering system
list-style-positionoutside (default) · insideMarker placement relative to the content box
list-style-imageurl('icon.png') · noneReplaces the marker with a custom image
list-stylesquare inside · noneShorthand for type, position, and image
::markercolor · font-size · contentStyles the marker itself, independent of item text
counter-reset / counter-incrementcounter-reset: step;Creates fully custom numbering systems

✅ Best Practices

✔️ 1) Always Reset Both Marker AND Spacing Together
When removing bullets for a nav menu, set list-style: none; margin: 0; padding: 0; together -not just one of them.

✔️ 2) Keep Using Semantic List Markup for Navigation
Even when a list is visually styled to look nothing like a "list" (a horizontal nav bar, a card grid), keep it as a real <ul>/<li> structure for accessibility and SEO benefits.

✔️ 3) Use ::marker Instead of Removing and Rebuilding Markers
Before reaching for list-style: none plus a manual ::before bullet, check whether ::marker alone (for simple color/size changes) solves the need with less code.

✔️ 4) Prefer Flexbox/Grid Over Floats for Horizontal Lists
Modern horizontal nav lists should use display: flex with gap, not the older float-based techniques, for simpler and more reliable spacing and wrapping.

✔️ 5) Use list-style-position: inside Carefully
It changes text alignment on wrapped lines -test it specifically with realistic, longer list item text before shipping, not just short single-line items.

💡 Pro Tip: For a clean, fully custom checklist-style icon list, combine list-style: none with an inline SVG inserted via ::before -this gives pixel-perfect control over icon size, color (via currentColor), and spacing that list-style-image simply cannot match.

✅ Common Mistakes to Avoid

❌ Mistake 1 – Removing the Marker but Forgetting the Indentation
Setting only list-style: none; without also resetting margin and padding leaves an unexplained empty gap on the left -a very common partial-fix bug.
❌ Mistake 2 – Using Plain <div>s Instead of <ul>/<li> for Navigation
Building a nav bar from stacked <div> or <a> tags instead of a real list loses the built-in accessibility benefits -screen readers can no longer announce the group size or structure.
❌ Mistake 3 – Expecting list-style-image to Behave Like background-image
list-style-image offers no control over size or vertical alignment, leading to inconsistent results across browsers. Use list-style: none with a sized background-image on the li instead.
❌ Mistake 4 – Applying Box-Model Properties Inside ::marker
li::marker { padding-left: 10px; } has no effect -only a small set of text-related properties (color, font, content) are valid inside ::marker.
❌ Mistake 5 – Forgetting counter-reset Before Using counter-increment
A custom counter that never gets counter-reset on its parent container can produce unexpected numbering, especially when multiple separate lists share the same counter name on one page.

✅ Complete Live Example

A real-world pricing-feature checklist combining several list techniques together:

Pricing Checklist – Live Preview
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.feature-list li {
  padding-left: 26px;
  position: relative;
  margin-bottom: 8px;
}

.feature-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: #2e7d32;
  font-weight: 700;
}
👁 Live Output
  • Unlimited projects
  • Priority support
  • Custom integrations

✅ Try It Yourself – Interactive Editor

Edit the HTML and CSS below to experiment with list styling. Try changing marker types, building a horizontal nav, or removing bullets entirely. The preview updates automatically.

🖥 Interactive CSS Lists Editor
👁 Live Preview

✅ 🎨 Interactive List-Style Playground

Pick a list type, marker style, position, and color to instantly preview how your list will look. Copy the generated CSS with one click.

🎨 CSS List-Style Playground
  • First list item
  • Second list item
  • Third list item
Generated CSS
ul { list-style-type: disc; list-style-position: outside; } li { margin-bottom: 8px; } li::marker { color: #0EA5E9; }

✅ Practice – Yes / No Quiz

1. Does list-style-type: none; automatically also remove the list's default left indentation?

2. With list-style-position: outside (the default), does a wrapped second line of text align with the marker?

3. Can the ::marker pseudo-element change the color of a list bullet independently from the item's text color?

4. Is it acceptable to use box-model properties like padding inside a ::marker rule?

5. Is using a semantic <ul>/<li> structure for a navigation menu better for accessibility than plain stacked <a> tags?

0/5
Your Score – Keep Practising! 🎯

✅ Frequently Asked Questions (FAQ)

What is list-style-type in CSS?
list-style-type sets the marker shown before each list item -values include disc, circle, square, none for unordered lists, and decimal, lower-roman, upper-roman, lower-alpha, upper-alpha for ordered lists. Setting it to none removes the bullet or number entirely.
How do I remove bullet points from a CSS list?
Set list-style: none; on the ul or ol element to remove the bullet or number marker. You typically also set margin: 0; and padding: 0; on the same element to remove the browser's default indentation, which is the standard first step when turning a list into a navigation menu.
What is the difference between list-style-position: inside and outside?
outside (the default) places the marker to the left of the content box, outside its width, so wrapped text on a second line aligns with the first line's text, not the marker. inside places the marker inside the content box as if it were the first inline element, causing wrapped lines to align with the marker's left edge instead.
How do I style the bullet or number of a list item differently from its text?
Use the modern ::marker pseudo-element: li::marker { color: #0EA5E9; font-weight: bold; }. This lets you change the marker's color, font-size, or font-weight independently of the list item's text content, without needing to remove the marker and recreate it manually.
How do I make a CSS list display horizontally instead of vertically?
Set display: inline-block or display: inline on each li, or apply display: flex to the parent ul/ol so all list items sit in a row. Flexbox is the modern preferred approach because it also makes spacing, alignment, and wrapping behavior easy to control with gap and justify-content.
Can I use a custom image as a list bullet in CSS?
Yes, using list-style-image: url('icon.png'); on the ul or ol. However, most modern developers prefer setting list-style: none and then adding a background-image or an inline SVG/icon directly on the li via ::before, since list-style-image offers very limited control over the bullet's size and position.
✍️ About the Author – Pramod Behera

Pramod Behera is the founder of LearnToSAP.com and an experienced web development educator. He creates beginner-friendly tutorials on HTML, CSS, SAP SD/MM, and frontend development, helping thousands of learners worldwide build practical skills.