list-style in CSS: customize bullets without breaking accessibility

list-style controls a list's bullet symbol, position, and image, but list-style: none can silently erase its role for a screen reader.
4 min read
Believemy logo

An HTML list, <ul> or <ol>, ships with default bullets or numbers, a browser style that almost never matches a modern design. The list-style property, together with its trio of detailed sub-properties, lets you take over everything: the symbol, its position, or a custom image.

It shows up constantly in one specific case: the navigation bar. A nav is almost always built as a list, for semantic reasons, then stripped of its bullets in CSS to look like a row of links rather than a bulleted list.


Definition

list-style is a shorthand that combines three properties: list-style-type, the symbol used, list-style-position, where the symbol sits relative to the text, and list-style-image, an image instead of the default symbol. It applies to <ul>, <ol> elements, and directly to each <li> when finer control is needed.


The three properties in detail

CSS
ul {
  list-style-type: square;
  list-style-position: inside;
  list-style-image: none;
}

/* equivalent in a single line */
ul {
  list-style: square inside;
}
PropertyRoleCommon values
list-style-typeThe symbol or numbering styledisc, circle, square, decimal, none
list-style-positionThe symbol inside or outside the text boxoutside (default), inside
list-style-imageAn image used as the bulleturl(...), none

list-style-position deserves special attention: with the default outside value, the bullet sits outside the text box, which slightly offsets the alignment of a multi-line item compared to its first character. With inside, the bullet becomes part of the text flow, which changes the indentation of the following lines.


Customizing a bullet with an image or generated content

list-style-image accepts an image but offers little control over its size or alignment. In practice, many projects prefer disabling list-style and drawing the bullet themselves with the content property on a pseudo-element, which gives far more freedom.

CSS
ul.checklist {
  list-style: none;
  padding-left: 0;
}

ul.checklist li {
  padding-left: 1.5em;
  position: relative;
}

ul.checklist li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: green;
}


Classic trap: list-style: none and accessibility

Removing bullets with list-style: none is purely visual: it changes nothing about the document's structure, which is still a list. The real trap lies elsewhere. Some browsers, Safari in particular, also drop the semantic list role announced to screen readers as soon as a list has no bullet style left, which can make it read as a plain series of links instead of a navigation list.

Good to knowIf the list's accessibility matters, explicitly add role="list" on the <ul> or <ol> in question in addition to list-style: none. This forces the semantic role to stay present, regardless of the browser or screen reader in use.


Complete example: a horizontal navigation

The most common use of list-style: none remains the navigation bar. A nav built as a list keeps its meaning for accessibility, while displaying as a row of links thanks to a few lines of CSS.

CSS
nav ul {
  list-style: none;
  display: flex;
  gap: 1.5rem;
  padding-left: 0;
  margin: 0;
}

nav ul li a {
  text-decoration: none;
  font-weight: 600;
}

In a larger project, the classes for this kind of component often follow a convention like BEM, for example nav__list and nav__item, rather than generic selectors like ul and li, to avoid a style meant for this navigation accidentally applying to another list on the page.


FAQ

QuestionDoes list-style: none also remove a list's default indentation?

No, these two behaviors are independent. A list's default margin and padding come from other properties, which must be removed separately with margin: 0 and padding: 0 for a fully flat alignment.

QuestionCan emoji be used as custom bullets?

Yes, with a declaration such as list-style-type: "🚀 ", placing a quoted string directly as the value, a syntax supported by modern browsers to replace the classic symbols.

QuestionCan an ordered list resume numbering from a specific number?

Yes, but that setting goes through the HTML start attribute on the <ol> tag, or the CSS counter-reset property combined with a custom counter, rather than through list-style itself, which only controls the symbol's appearance.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.