Replacing List Bullets with Images Using CSS

Replacing standard HTML list bullets with images can be a great way to tie them into your overall theme and make your site more visually appealing.

Note: When I originally wrote this article, it was as part of a series of posts I was writing about customizing the Thesis theme for WordPress websites. However, the information applies to any site where you have the ability to edit the CSS file. You don’t need to be using either WordPress or Thesis. Finally, if you were to look at the source code for this page, the HTML I’m using may not match what I’m showing as the code in the tutorial. That’s because I have to do some fancy footwork with the behind-the-sceens HTML and CSS to make it display correctly for you.

This is what a standard bulleted list looks like on a web page:

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines
  • List item 2
  • List item 3

The HTML code to create this list looks like the following. The <ul> stands for “unordered list” and the <li> stands for “list item.” (If you want to use numbers instead of bullets, you would use <ol>, or “ordered list”.)

<ul>
<li>I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>

Before showing you how to replace those bullets with images, I’ll add that there are some other shapes you can use built into HTML itself. These include a circle, disc (filled circle), square, and various number formats. You can see the full list on the w3schools website.

You change the style by changing the definition for <ul> in your CSS stylesheet.

ul {
list-style-type: lower-greek;
}

However, if you use the CSS definition above, it will affect every list item you have on your site. If you want to just have that style for certain lists, you’ll need to create a new class to apply to the <ul>. For example, you could create a class called “lower_greek” and change your CSS to:

ul.lower_greek {
list-style-type: lower-greek;
}

Then you’d add that class into the <ul> tag in the HTML as follows:

<ul class="lower_greek">
<li>I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>

Here’s what the list looks like now.

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines
  • List item 2
  • List item 3

NOTE: If you’re working on a site that already has CSS defined for it (e.g. WordPress themes come with a style.css file), you may need to change existing style definitions. If you just add your own, they may be overridden by the existing ones.

Now, to change the bullet to an image, you can add an attribute called list-style-image to your CSS definition. For this example, I’m using a leaf image that’s 24 x 38 pixels. The CSS code would now be:

ul.leaf {
list-style-image: url('/images/leaf_icon.jpg');
}

and the HTML would be:

<ul class="leaf">
<li>I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>

This is what the list looks like on the web page:

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines as well.
  • List item 2
  • List item 3

Now, you can see the problem with this approach is that the bullet isn’t positioned very nicely relative to the text. That’s because when you add the list-style-image attribute to the <ul> tag, it uses the same positioning and spacing between the bullet and the text, regardless of the size of the image. So that might work well if your image is about the same size as a standard bullet but not so well if it’s much bigger or smaller.

Another option is to eliminate the standard bullet altogether using the <ul> tag and then add a background image in the <li> tag so you can use further attributes to adjust the positioning exactly the way you want it.

So the CSS would now be:

ul.no_bullet {
list-style-type: none;
padding: 0;
margin: 0;
}

li.leaf {
background: url('/images/leaf_icon.jpg') no-repeat left top;
}

and the HTML would be:

<ul class="no_bullet">
<li class="leaf">I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines</li>
<li class="leaf">List item 2</li>
<li class="leaf">List item 3</li>
</ul>

The list will then look like this:

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines as well.
  • List item 2
  • List item 3

Now, obviously, we still need to do a little more work. The bullet image is being cut off on the bottom so we need to set a list item height value that is at least as big as the height of the image. We also need space between the image and the text, which we set using padding-left. I’m also using some padding-top to align the text better vertically.

Note: Padding values will change where the text appears relative to the image within an individual list item. Margin values will change where the entire line—including the bullet—appears relative to other items on the page, including the next list item. You can also control the position of the bullet image using the background declaration, replacing “left” and “top” with actual pixel values. Basically you just have to start with something and then play around with the values until you have them where you want them.

I can’t give you exact values because it will depend on a number of variables including the size of the bullet, how much spacing you want, font size, and so on. But here’s the change I’ve made to the CSS and the resulting output.

li.leaf {
background: url('/images/leaf_icon.jpg') no-repeat left top;
height: 54px;
padding-left: 44px;
padding-top: 3px;
}
  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines as well.
  • List item 2
  • List item 3

For Smaller Bullet Images

The above works very well if your image is bigger than a standard bullet. If it’s smaller, you might end up with something that looks like this:

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines as well.
  • List item 2
  • List item 3

You can see that the text from one bullet runs into the next line. Now you could fix that by specifying a larger height value again, but that will look odd for such a small bullet, e.g.

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines as well.
  • List item 2
  • List item 3

In this instance, you’ll want to add a display attribute and adjust the top positioning in the background image (replace “top” with an actual dimension). So the CSS will now look like this:

li.red_square {
background: url('/images/red-square-4×4.jpg') no-repeat left 9px;
padding-left: 12px;
display: block;
}

And the output will be:

  • I’m writing a long list item 1 so you can see what happens when the text wraps across multiple lines as well.
  • List item 2
  • List item 3

Again, play with the values until it looks the way you want it. And note that you can also reposition larger bullet images as well if you don’t like the way it’s aligning with the text.

Note: Thanks to reader Sibley who shared the tip about needing a “display: block” attribute for smaller bullets.

Mixing Bullet Types in the Same List
Finally, by applying classes to the <li> tags instead of the <ul> tag, you can mix and match bullet types and images within the same list.

So with this HTML:

<ul class="no_bullet">
<li class="disc">List item: disc bullet</li>
<li class="square">List item: square bullet</li>
<li class="lower_greek">List item: lower greek bullet</li>
<li class="leaf">List item: leaf image bullet</li>
<li class="red_square">List item: red square image bullet</li>
</ul>

turns into this (with appropriate tweaks to the individual CSS class definitions):

  • List item: disc bullet
  • List item: square bullet
  • List item: lower greek bullet
  • List item: leaf image bullet
  • List item: red square image bullet
Elizabeth Kricfalusi

View Comments

  • Very clear... ! Your explanation is superb.

    Is it possible to:
    replace each dot with different icon-pix??? assuming they are all the same size so spacing cosmetics are not an issue.

    Essentially an Ordered list, which displays an image instead of a digit.

    Can this be done in CSS ?

    Thanks,
    ND

    • Have you read the entire post, because there is a step-by-step explanation of how to do what you're asking in it.

  • I also found it useful and very well written. I like you showed the steps leading up to the solution. Thanks!

    • Glad you found it helpful, Tom. Thanks for taking the time to let me know! - Elizabeth

  • Thank you, thank you, thank you!! You are a life saver... this was just what I was looking for. :)

  • A great summary of the issues and related solutions. It looks like you may have introduced a couple typos in a recent update:
    • Your code examples use left double quotes, rather then straight quotes, so they don't work as-is if copy pasted.
    • For the lower_greek sample, I see bullets rather than α β γ. Looking at your CSS, I believe that ul > li.lower_greek should be ul.lower_greek > li

    • Thanks for catching those, Michael! I think I've got them all fixed now, but if you see any that are still broken, please let me know. - Elizabeth

  • Hi, Thanks for very useful article with examples. I have used it on my website by following your tips. Thanks.

    • Hi Kash.

      I'm glad you found the post helpful. Thanks for taking the time to let me know!

      - Elizabeth

  • Hi.
    Thanks for providing an excellent solution to UX problems. The default list bullets in Wordpress are not aesthetic. By using your CSS code, we can make our list more appealing. I will definitely try to implement on my blog. But one thing, I'm not sure is whether will this impact the page loading speed of the site. If it doesn't I'm ready to dive in. Please throw some light. :)

1 2 3 6

Recent Posts

T4L Monthly Update: February 2019

CES 2019, FaceTime bug, streaming the Super Bowl, Wi-Fi calling for Android phones.

4 years ago

Top Tech Stocking Stuffers

Big-ticket electronics get all the attention, but these little extras are always appreciated.

5 years ago

Four Ways to Access Control Panel in Windows 10

Microsoft is doing its darndest to hide the classic Control Panel from Windows 10 users.…

5 years ago