Latency-friendly customized bullets using Unicode characters

Technologies: HTML 4+, CSS 2+, Modern web browser

CSS defines only three bullet shapes: disc, circle, and square. To get custom bullets, web designers use small bullet images. The network latency cost for these images is high, slowing down the web site. Instead, avoid bullet images and use Unicode symbol characters as bullets. Unicode bullets require nothing extra to download and provide thousands of bullet shapes to choose from.

Bullet methods

Let's look at a few typical ways to control bullets on a list, and then a latency-friendly way using Unicode characters.

A typical bullet list using standard bullets

The default bullet is a filled circle. In CSS, set the list-style on the <li> tag to select between bullet shapes and numbering schemes (not discussed here). The three available shapes are usable, but uninspired.

  • Disc
  • Circle
  • Square
Standard bullets
HTML <ul>
  <li style="list-style: disc">Disc</li>
  <li style="list-style: circle">Circle</li>
  <li style="list-style: square">Square</li>

A typical bullet list using image bullets

To use a custom bullet image, set the list-style to an image URL. Keep the image about the same size as the font.

  • Small square
  • Med-small square
  • Medium square
  • Large square
  • Small empty square
  • Med-small empty square
  • Medium empty square
  • Large empty square
  • Small double-square
  • Medium double-square
  • Large double-square
  • Large triple-square
  • Four dots
  • Sixteen dots
  • Twenty-five dots
  • Chat balloon
  • Yellow sphere
  • Orange sphere
  • Red sphere
  • Purple sphere
  • Blue sphere
  • Green sphere
  • Gray sphere
  • Right arrow
Image bullets using list-style
HTML <ul>
  <li style="list-style: url(square_10x10_small.gif)">Small square</li>

Alternatively, disable the list-style bullet and add a CSS background image to each list item. Background image bullets can use CSS sprites to combine multiple bullets into one image file, but they don't print if the visitor has disabled background printing (the default in most browsers).

  • Plus square
  • Minus square
  • Right-pointing triangle
  • Ddown-pointing triangle
  • White document
  • Gray document
  • White folder
  • Gray folder
  • Yellow folder
  • Orange folder
  • Blue folder
  • White open folder
  • Gray open folder
  • Yellow open folder
  • Orange open folder
  • Blue open folder
Image bullets using background
HTML <ul>
  <li style="list-style: none; padding-left: 20px; background: url(squareplus_10x10_large.gif) left center no-repeat;">Plus square</li>

Custom bullet images are usually small, so the download time is negligable. But every image has a network latency cost as the browser asks for and waits to get the image from the web server. Typical latencies range from 1/10 to 1/2 second. While these seem small, they add up quickly. If you have a dozen different custom bullets, the latency alone can add several seconds to your page's load time. That's very expensive for a few little bullets. To help the page load faster, use Unicode bullets instead of images.

A latency-friendly bullet list using Unicode symbol characters

Unicode has over 100,000 characters for letters, numbers, punctuation, and symbols that span the world's languages. In HTML, use &#x0000; to insert a Unicode character, replacing 0000 with its unique hex number. For example, &#x2713; is a check mark symbol ✓, &#x2736; is a six-pointed star ✶, and &#x2794; is a right arrow ➔. There are thousands of symbols to choose from. has excellent pages listing Unicode characters. A sampling of bullets is shown below and at the end of this article.

To use a Unicode bullet symbol, add it within a <span> in each list item. Float the span left and give it a 2em width (to make bullet spacing uniform). Disable normal bullets with list-style: none; and set the line-height a bit taller than the bullets or the floats will stair-step the bullet list.

  • Filled circle
  • Unfilled circle
  • Filled square
  • Filled diamond
  • Unfilled diamond
  • Unfilled star
  • 4-point florette
  • Up triangle
  • Right triangle
  • Down triangle
  • Check
  • X mark
  • Filled right hand
  • Smiley face
  • Right arrow
  • Musical notes
  • Rook
  • Hearts
  • Sun
  • Radioactive
  • 5-point flourette
  • Texas star
  • 3D right arrow
  • Check in box
  • X in box
  • Ying-yang
  • Recycle
  • Filled flag
  • Lightening
  • Airplane
Unicode bullets in HTML
HTML <ul class="unilist">
  <li><span class="unibull">&#x25CF;</span> Filled circle</li>
CSS .unilist li { list-style: none; line-height: 1.5em; }
.unibull { float: left; width: 2em; }

You can also use CSS 2.0 content insertion to add bullets. Add an empty <span> for each list item, float it left and give it a 2em width. Give each bullet type its own class and use a CSS :before selector and a content value to insert the bullet symbol. Use \0000 in CSS to select a Unicode character. This will work in current Safari, Opera, and Firefox browsers, but not Internet Explorer 7 and earlier. In older browsers, and IE, the bullets won't be shown.

  • Double circle
  • Double box
  • Double diamond
  • Double pentagon
  • Four point star
  • Five point star
  • Six point star
  • Eight point star
  • Twelve point star
  • Sixteen point star
  • Shadowed circle
  • Shadowed box
  • Shadowed star
  • Up hand
  • Down hand
  • Clover leaf
  • Unfilled flag
  • Warning/alert
  • Letter
  • Pawn
  • Dotted arrow
  • Double arrow
  • Unfilled arrow
  • Pointer
  • Pointer 2
  • Filled pointer
  • Curve arrow
  • Curve arrow 2
  • Short arrow
  • Long arrow
Unicode bullets with CSS text insertion
HTML <ul class="unilist">
  <li><span class="unibull u1"></span> Double circle</li>
CSS .unilist li { list-style: none; line-height: 1.5em; }
.unibull { float: left; width: 2em; }
.u1:before { content: "\25C9"; }

Alternatively, use a bit of Javascript to scan the DOM and insert bullets for <span> tags with specific class names. Use \u0000 in Javascript to select a Unicode symbol character. Of course, if the visitor's browser doesn't have Javascript enabled, the bullets won't show up. But according to browser statistics, 94% of web visitors now enable Javascript.

  • Up triangle
  • Right triangle
  • Down triangle
  • Left triangle
  • Unfilled square
  • Filled square
  • Star
  • Diamonds
  • Clubs
  • Spades
  • Left-filled circle
  • Right-filled circle
  • Bottom-filled circle
  • Top-filled circle
  • Left-filled diamond
  • Right-filled diamond
  • Top-filled diamond
  • Bottom-filled diamond
  • Top-filled square
  • Bottom-filled square
  • Filled circle
  • Unfilled circle
  • Square & circle
  • Empt diamond
  • Six-point florette
  • Gray star
  • Plus & square
  • X mark
  • Plus
  • Bold check
Unicode bullets with Javascript text insertion
HTML <ul class="unilist">
  <li><span class="unibull ju1"></span> Up triangle</li>
CSS .unilist li { list-style: none; line-height: 1.5em; }
.unibull { float: left; width: 2em; }
JavaScript <script type="text/javascript">
var tags = document.getElementsByTagName("span");
for ( var i = 0; i < tags.length; i++ ) {
  if ( tags[i].className == "unibull ju1" )
    tags[i].appendChild( document.createTextNode( "\u25B2" ) );


Comparing features

Standard bullets and image bullets work in all web browsers on all platforms. Unicode works in all modern browsers, but no browser supports all of Unicode's 100,000+ characters yet. Most browsers support all of the "dingbats" and other common symbols that make interesting bullets.

The standard bullets method is, well, standard. It's what all HTML authoring tools know how to do. The other methods require hand-coding.

Custom image bullets are obviously the most flexible. Graphic designers can create anything they like. But for simpler bullets, the Unicode approach gets thousands of bullet symbols cheaply without any images.

Image bullets can use multiple colors, but standard and Unicode bullets have a single color. Standard bullets take on the color of the list text. Unicode bullet colors are set by CSS and can differ from the list text. Image bullet colors are set once in the image, so if you need multiple bullets of different colors, you need multiple bullet images.

Image bullet sizes are fixed when the images are created. Standard bullet sizes match that of the list text. Unicode bullet sizes are set in CSS and can be larger or smaller than the neighboring text.

Since standard bullets and Unicode bullets are symbol characters in a font, they scale up and down smoothly. They are all anti-aliased and are crisp at any size. Image bullets, however, don't scale, and won't print as crisply.

Comparing sizes

The table below summarizes the size of a list with one bullet for each method. Image bullets add an image, of course, plus about 250 bytes for a HTTP response header sent by the web server along with the image file. Not surprisingly, image bullets have a bigger total size. But a few hundred bytes is too little to worry about.

Additional page size (bytes)
Type of data Standard bullet Image bullet Unicode bullet
Compressed HTML 86 91 104
Compressed CSS 0 0 119
Compressed PNG (7 x 7) 0 100 0
HTTP response for image 0 250 0
TOTAL 86 441 223

Comparing load times

To load a web page, the browser asks for the page's files, waits for a response, then reads their bytes off the network. Network latency increases the wait time, while low bandwidth increases the read time. The ideal network has zero latency and infinite bandwidth. In the real world, latencies are about 1/10th of a second between a US home and a US web site. Overseas visitors to the same site may see 1/5th of a second in latency, and a cell phone may pause for 1/2 second or more. Bandwidths vary from about 500 kilobytes/second for a US home, down to just 30 kilobytes/second for a cell phone.

The table below uses these numbers to estimate the load time impact of a list with just one bullet.

Additional page load time (seconds)
  Standard bullet Image bullet Unicode bullet
Connection Latency + Download Latency + Download Latency + Download
US home to US server
500 KB/s, 100ms latency
none + 0.0002 = 0.0002 0.1 + 0.0011 = 0.1011 none + 0.0005 = 0.0005
International home to US server
100 KB/s, 200ms latency
none + 0.0009 = 0.0009 0.2 + 0.0054 = 0.2054 none + 0.0022 = 0.0022
Cell phone to US server
30 KB/s, 500ms latency
none + 0.0029 = 0.0029 0.5 + 0.0178 = 0.5178 none + 0.0074 = 0.0074

Since the number of bytes for each method is tiny, the time spent reading them is trivial. It's the latency part of the load time that matters here, not the download time.

Custom image bullets require an external image file, while the other methods do not. The time spent waiting for the network to deliver that file is 100 times longer than it takes to read the file's bytes. If the page has lots of custom bullet images, this can have a noticable impact on the total page load time. Because Unicode bullets do not have external files to load, they have no latency delays. This makes them hundreds of times faster than image bullets.

These load times are just estimates. The real world is more complicated. Bandwidths and latencies vary from moment to moment based upon network and web server load. The latency on a cell phone can vary from 1/2 second to 3 seconds or more, depending upon signal strength. Pipelining, keep alives, caches, and parallel downloads also affect the results.


For today's Internet connections, latency is a bigger problem than bandwidth. Latency-friendly design reduces page load times by reducing the number of files required by a page. Pages load faster and demand less of the visitor's network connection and the web site's server.

Unicode bullets are less flexible than image bullets. But there are still thousands of Unicode bullet symbols to choose from, the method is simple, it avoids latency costs to download bullet images, and it has faster page load times.

Clearly, the bullet images can be cached. But recent performance studies by Yahoo! found that visitors rarely arrive with your content already in their cache. Instead, they have to download it again on every visit. For that initial download, the Unicode bullets are much faster. For subsequent page loads, the methods are all about the same.

Appendix: Gallery of bullets

There are literally thousands of Unicode symbol characters that could be used as bullets. Here are a few:

Unicode symbols to use as bullets
Circles Stars Triangles Arrows Chess pieces
&#x25C9; ◉ &#x2605; ★ &#x25B2; ▲ &#x219D; ↝ &#x2654; ♔
&#x25CB; ○ &#x2606; ☆ &#x25B3; △ &#x21C9; ⇉ &#x2655; ♕
&#x25CC; ◌ &#x2699; ⚙ &#x25B4; ▴ &#x21DD; ⇝ &#x2656; ♖
&#x25CE; ◎ &#x2721; ✡ &#x25B5; ▵ &#x21E2; ⇢ &#x2657; ♗
&#x25CF; ● &#x2722; ✢ &#x25B6; ▶ &#x21E8; ⇨ &#x2658; ♘
&#x25D0; ◐ &#x2723; ✣ &#x25B8; ▸ &#x21F0; ⇰ &#x2659; ♙
&#x25D1; ◑ &#x2724; ✤ &#x25B9; ▹ &#x2794; ➔ &#x265A; ♚
&#x25D2; ◒ &#x2725; ✥ &#x25BA; ► &#x2799; ➙ &#x265B; ♛
&#x25D3; ◓ &#x2726; ✦ &#x25BB; ▻ &#x279B; ➛ &#x265C; ♜
&#x25E6; ◦ &#x2727; ✧ &#x25BC; ▼ &#x279C; ➜ &#x265D; ♝
&#x25EF; ◯ &#x2729; ✩ &#x25BD; ▽ &#x279D; ➝ &#x265E; ♞
&#x25F4; ◴ &#x272A; ✪ &#x25BE; ▾ &#x279E; ➞ &#x265F; ♟
&#x25F5; ◵ &#x272B; ✫ &#x25BF; ▿ &#x279F; ➟  
&#x25F6; ◶ &#x272C; ✬ &#x25C0; ◀ &#x27A0; ➠ Card suits
&#x25F7; ◷ &#x272D; ✭ &#x25C2; ◂ &#x27A1; ➡ &#x2660; ♠
&#x2609; ☉ &#x272E; ✮ &#x25C3; ◃ &#x27A2; ➢ &#x2663; ♣
&#x2641; ♁ &#x272F; ✯ &#x25C4; ◄ &#x27A3; ➣ &#x2665; ♥
&#x2686; ⚆ &#x2730; ✰ &#x25C5; ◅ &#x27A4; ➤ &#x2666; ♦
&#x2687; ⚇ &#x2731; ✱ &#x25E2; ◢ &#x27A5; ➥ &#x2664; ♤
&#x2688; ⚈ &#x2732; ✲ &#x25E3; ◣ &#x27A6; ➦ &#x2667; ♧
&#x2689; ⚉ &#x2733; ✳ &#x25E4; ◤ &#x27A7; ➧ &#x2661; ♡
&#x26AA; ⚪ &#x2734; ✴ &#x25E5; ◥ &#x27A8; ➨ &#x2662; ♢
&#x26AB; ⚫ &#x2735; ✵ &#x25ED; ◭ &#x27A9; ➩  
&#x26AC; ⚬ &#x2736; ✶ &#x25EE; ◮ &#x27AA; ➪ Weather
&#x274D; ❍ &#x2737; ✷   &#x27AB; ➫ &#x2600; ☀
&#xFFEE; ○ &#x2738; ✸ Checks &#x27AC; ➬ &#x263C; ☼
  &#x2739; ✹ &#x23B7; ⎷ &#x27AD; ➭ &#x263D; ☽
Squares &#x273A; ✺ &#x237B; ⍻ &#x27AE; ➮ &#x263E; ☾
&#x2311; ⌑ &#x273B; ✻ &#x2611; ☑ &#x27AF; ➯ &#x2601; ☁
&#x25A0; ■ &#x273C; ✼ &#x2713; ✓ &#x27B1; ➱ &#x2602; ☂
&#x25A1; □ &#x273D; ✽ &#x2714; ✔ &#x27B2; ➲ &#x2603; ☃
&#x25A2; ▢ &#x273E; ✾   &#x27B3; ➳  
&#x25A3; ▣ &#x273F; ✿ X marks &#x27B5; ➵ Fun
&#x25AA; ▪ &#x2740; ❀ &#x2612; ☒ &#x27B8; ➸ &#x231A; ⌚
&#x25AB; ▫ &#x2741; ❁ &#x2715; ✕ &#x27BA; ➺ &#x231B; ⌛
&#x25D8; ◘ &#x2742; ❂ &#x2716; ✖ &#x27BB; ➻ &#x2388; ⎈
&#x25D9; ◙ &#x2743; ❃ &#x2717; ✗ &#x27BC; ➼ &#x2604; ☄
&#x25E7; ◧ &#x2744; ❄ &#x2718; ✘ &#x27BD; ➽ &#x260E; ☎
&#x25E8; ◨ &#x2745; ❅   &#x27BE; ➾ &#x260F; ☏
&#x25E9; ◩ &#x2746; ❆ Hands   &#x2614; ☔
&#x25EA; ◪ &#x2747; ❇ &#x261A; ☚ Music &#x2615; ☕
&#x25F0; ◰ &#x2748; ❈ &#x261B; ☛ &#x2669; ♩ &#x2618; ☘
&#x25F1; ◱ &#x2749; ❉ &#x261C; ☜ &#x266A; ♪ &#x2620; ☠
&#x25F2; ◲ &#x274A; ❊ &#x261D; ☝ &#x266B; ♫ &#x2622; ☢
&#x25F3; ◳ &#x274B; ❋ &#x261E; ☞ &#x266C; ♬ &#x2623; ☣
&#x274F; ❏ &#x2756; ❖ &#x261F; ☟ &#x266D; ♭ &#x2624; ☤
&#x2750; ❐   &#x270D; ✍ &#x266E; ♮ &#x2625; ☥
&#x2751; ❑ Diamonds     &#x262E; ☮
&#x2752; ❒ &#x25C6; ◆ Crosses Dice &#x262F; ☯
&#x2B12; ⬓ &#x25C7; ◇ &#x2670; ♰ &#x2680; ⚀ &#x2638; ☸
&#x2B13; ⬓ &#x25C8; ◈ &#x2671; ♱ &#x2681; ⚁ &#x2668; ♨
&#x2B14; ⬔ &#x25CA; ◊ &#x2719; ✙ &#x2682; ⚂ &#x267B; ♻
&#x2B15; ⬕ &#x2B16; ⬖ &#x271A; ✚ &#x2683; ⚃ &#x267C; ♼
&#x2B1A; ⬚ &#x2B17; ⬗ &#x271B; ✛ &#x2684; ⚄ &#x267D; ♽
&#xFFED; ■ &#x2B18; ⬘ &#x271C; ✜ &#x2685; ⚅ &#x2690; ⚐
  &#x2B19; ⬙ &#x271D; ✝   &#x2691; ⚑
Hexagons   &#x271E; ✞ Faces &#x269B; ⚛
&#x2B21; ⬡   &#x271F; ✟ &#x2639; ☹ &#x26A0; ⚠
&#x2B22; ⬢   &#x2720; ✠ &#x263A; ☺ &#x26A1; ⚡
&#x2B23; ⬣     &#x263B; ☻ &#x2708; ✈
        &#x2709; ✉

Not all browsers or operating systems support all of these symbols. When a symbol isn't supported, a browser may show an empty box (Safari and Opera), a question mark (Firefox), or an incorrect character (Firefox). Currently, Safari has the best Unicode support, followed by Opera, Firefox, and Internet Explorer. Macs and Windows Vista have more complete Unicode fonts than Windows XP or Linux. But this improves with each new software update.

Further reading


Some chars does not work!

Thanks a lot for this informations... but I still with one question...

- Why some chars, like "checks" does not work?

There any solution?


Why some characters don't work

Unicode has about 100,000 characters defined. That's a lot for fonts, browsers, and operating systems to support. Right now, nobody supports them all, but support is improving quickly.

Until all OSes and browsers support all Unicode characters, web designers will need to do browser testing. As usual, Internet Explorer is one of the worst and Opera, Firefox, and Safari are the best. Windows Vista has large Unicode fonts, but Windows XP does not. So, IE on Windows XP does worse than the same version of IE on Windows Vista.

Symbols found in standard "ding-bats" fonts are widely supported, but more obscure math, astrology, and dentistry (!) symbols are not as well supported. Since Windows XP doesn't have its own Unicode fonts, it's usually the problem. None of the check marks are supported by IE7 or earlier on XP. Firefox 2 and Safari 3 on XP support half of the check marks. All of the browsers do better on Windows Vista, and better still on Linux and Mac OS X.

Have you looked at this page using Internet Explorer?

Have you looked at this page using Internet Explorer? Most of the bullets, which are interesting shapes in Firefox, are just empty squares, because Internet Explorer doesn't know how to display them.

I am trying to find empty *and* checked boxes that will display as such in multiple browsers including IE.

Re: Have you looked at this page using Internet Explorer?

Well, as I noted earlier, Unicode support varies from browser to browser and OS to OS. Windows XP doesn't include a Unicode font, and Internet Explorer's Unicode support lags behind that of the other browsers. There is no master table of what does and doesn't work. With 100,000+ Unicode characters and dozens of different OS-browser combinations, such a table would be enormous and perpetually out of date as browsers and OSes evolve.

Perhaps think differently. The Unicode check and check-in-a-box characters don't work in IE 7 and earlier on Windows XP. But there are other characters you can use. Try the &radic; = √ character as a check. Technically it's a radical (as in a square root), but it looks check-ish and it is supported on all browsers and OSes. Or use &bull; = •, or a capital X. You're safe for all browsers if you stick to HTML entities and Latin-1 characters. And, instead of an empty box for an unchecked state, try underlining an &nbsp;. Use fixed-width font to make sure the checked and unchecked widths are the same. This gives you:

 √  Checked
 •  Checked
 X  Checked

Whether using Unicode bullets, or any other HTML/CSS feature, always test test test. Install all current and recent browsers and have Windows, Mac OS X, and Linux platforms at hand. I recommend browsing in its Unicode characters section. Use the "UTF-8 browser test" pages to see what the characters look like in different browsers.

Excellent Post!!

Excellent Post!!


Brilliant work - keep it up, thanks.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

Nadeau software consulting
Nadeau software consulting