[css] Reducing the gap between a bullet and text in a list item

How can I reduce default gap between bullet and text in an <li>?

  • Item 1
  • Item 2
  • Item 3

I want to reduce gap between the bullet and "I".

This question is related to css html-lists

The answer is


To achieve the look I wanted, I made a div containing a basic UL and several LIs. I couldn't easily adjust the indent between the bullet and text with any of the suggested ideas above (technically possible, but not simple.) I just left the UL and LI without any listing feature (list-style-type: none) then adding a &bull; to the beginning of each line. It did give me a bit of trouble at first, it only displayed the first bullet, so I added a bullet character to the end of the first line, refreshed, then removed it and they all popped up. Just manually add a bullet HTML entity if you don't want a huge indent, add space HTML entities if you want more space :o I know it isn't the best method, but it worked for me.


You could achieve this by setting the list-style-type to none, and setting the background-image of a list element to a generic bullet, like so:

ul {
    list-style-type: none;
}

li {
    background-image: url(bullet.jpg);
    background-repeat: no-repeat;
    background-position: 0px 50%;
    padding-left: 7px;
}

The outcome would look a little something like this:

alt text

With this approach, you aren't adding unnecessary span (or other) elements to your lists, which is arguably more practical (for later extendibility and other semantic reasons).


This is one way.

    li span {
        margin-left: -11px;
    }

<ul>
    <li><span>1</span></li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

I needed to do this inline, and combined a few of the above to make it work right for me. I'm working inside a div and wanted to use an image:

The padding under the UL told the bullet where to start from the left margin of the div it's in. I use em for better accessibility/flexibility, but you could use px too. If it doesn't seem to move much with px, use a much larger px value (for me, just moving it in a cm was 60px!).

The text-indent tells the bullet how close to get to the text it's next to.

Hope it works for you! :)


Here's how to do it.

Multi-line works perfectly if you do it this way. Bullet will automatically size with text. Indent is straight-forward: it's just the padding-left on the li. Minimal CSS required.

_x000D_
_x000D_
ul {_x000D_
  margin: 0;_x000D_
  padding: 0;_x000D_
  list-style-type: none;_x000D_
}_x000D_
ul > li {_x000D_
  position: relative;_x000D_
  padding-left: 12px;_x000D_
}_x000D_
ul > li:before {_x000D_
  content: "•";_x000D_
  position: absolute;_x000D_
  left: 0;_x000D_
}_x000D_
div {_x000D_
  border: 1px solid #ccc;_x000D_
}
_x000D_
<div>_x000D_
  <ul>_x000D_
    <li>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore, explicabo iste numquam dolorem harum natus! Voluptate magni expedita, eaque voluptates, aliquam maiores vel quia repellat a ipsum possimus eveniet, blanditiis.</li>_x000D_
    <li>Repudiandae repellendus laboriosam, odio vero debitis non quisquam provident deserunt, ratione facilis suscipit delectus sunt aliquid, in maxime autem optio, exercitationem iusto fugiat itaque omnis assumenda est a praesentium? Natus?</li>_x000D_
    <li>Voluptatem, distinctio, eius, soluta, atque laboriosam tempora magnam sequi saepe architecto accusamus hic facilis! Tenetur, necessitatibus. Ut ipsam, officia omnis obcaecati vero consectetur vel similique nam consequatur quidem at doloremque.</li>_x000D_
  </ul>_x000D_
</div>
_x000D_
_x000D_
_x000D_


I'm not sure whether this is the best way to do it, but you could specify a negative text-indent:

li {
    text-indent: -4px;
}

...where your HTML code looks like:

<ul>
    <li>Item 1</li>
    <li>Item 2</li>
</ul>

(Tested in Safari 4.0.4 and Firefox 3.0.11.)


I've tried these and other solutions offered, which don't actually work, but I seem to have found a way to do this, and that is to remove the bullet and use the :before pseudo-element to put a Unicode bullet in its place. Then you can adjust the the space between the list item and bullet. You have to use Unicode to insert an entity into the content property of :before or :after - HTML entities don't work.

There's some sizing and positioning code needed too, because the Unicode bullet by default displays the size of a pinhead. So the bullet has to be enlarged and absolutely positioned to get it into place. Note the use of ems for the bullet's sizing and positioning so that the bullet's relationship to the list item stays constant when your change the font size of the list item. The comments in the code explain how it all works. If you want to use a different entity, you can find a list of the Unicode entities here:

http://www.evotech.net/blog/2007/04/named-html-entities-in-numeric-order/

Use a value from the far right column (octal) from the table on this page - you just need the \ and number. You should be able to trash everying except the content property from the :before rule when using the other entities as they seem to display at a useable size. Email me: charles at stylinwithcss dot com with any thoughts/comments. I tested it Firefox, Chrome and Safari and it works nicely.

    body {
      font-family:"Trebuchet MS", sans-serif;
      }
    li  {
      font-size:14px;        /* set font size of list item and bullet here */
      list-style-type:none; /* removes default bullet */
      position:relative;      /* positioning context for bullet */
      }
      li:before  {
        content:"\2219";    /* escaped unicode character */
        font-size:2.5em;    /* the default unicode bullet size is very small */
        line-height:0;        /* kills huge line height on resized bullet */
        position:absolute;  /* position bullet relative to list item */
        top:.23em;           /* vertical align bullet position relative to list item */
        left:-.5em;            /* position the bullet L- R relative to list item */
       }

Here You Go with Fiddle:

FIDDLE

HTML:

<ol>
        <li>List 1          
            <ol>
                <li>Sub-Chapter</li>
                <li>Sub-Chapter</li>
            </ol>
        </li>
        <li>List 2
            <ol>
                <li>Sub-Chapter</li>
                <li>Sub-Chapter</li>
            </ol>
        </li>
        <li>List 3</li>
</ol>

CSS:

ol {counter-reset:item;}
ol li {display:block;}
li:before {content:counters(item, ".");counter-increment:item;left:-7px;position:relative;font-weight:bold;}

ul li:before {
    content: "";
    margin-left: "your negative value";
}

I have <a> inside the <li>s.

To the <ul> elements, apply the following CSS:

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

To the <a> elements, apply the following CSS:

a:before {
    content: "";
    height: 6px;
    width: 6px;
    border-radius: 50%;
    background: #000;
    display: inline-block;
    margin: 0 6px 0 0;
    vertical-align: middle;
}

This creates pseudo elements for the bullets. They can be styled just like any other elements.

I've implemented it here: http://www.cssdesk.com/R2AvX


If in every li you have only one row of text you can put text indent on li. Like this :

ul {
  list-style: disc;
}
ul li {
   text-indent: 5px;
}

or

ul {
 list-style: disc;
}
ul li {
   text-indent: -5px;
}

You might try using:

li {list-style-position: inside; }

But I can't remember if that adjusts the space, or changes where the space occurs.


Edited

The above doesn't seem to make any substantial difference. There doesn't seem to be any way to decrease the space between the list-style-type marker and the text, though it can be increased using margin-left or text-indent.

Sorry I can't be of more use.


Edited

Just out of curiosity, how about 'faking' the bullet with a background image?

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

ul li {background: #fff url(path/to/bullet-image.png) 0 50% no-repeat;
       margin: 0;
       padding: 0 0 0 10px; /* change 10px to whatever you feel best suits you */
}

It might allow for more fine-tuning.


Try this....

ul.list-group li {
     padding-left: 13px;
     position: relative;
}

ul.list-group li:before {
     left: 0 !important;
     position: absolute;
}

Reduce text-indent to a negative number to decrease the space between the list item's bullet and its text.

li {
  text-indent: -4px;
}

You can also use margin-left to adjust any space between the list-item's bullet and the edge of its surrounding element.

li {
  margin-left: 24px;
}

Both text-indent and padding-left can add space between the bullet and text, but only text-indent can reduce space to negative.

li { padding-left: -4px; } /* Doesn't work. */

Here's yet another way.

  1. Add two divs to each li, one for the bullet, one for the text.
  2. Put a bullet character (or whatever you like, Unicode has plenty) in the bullet div. Put the text in the text div.
  3. Set each li to display:flex.

Pros:

  • No extra bullet image to add.
  • No negative margins or anything, won't go outside of parent.
  • Works on any browser that supports flexbox.
  • Proper indentation of multiline items.
  • Use of bullet character means bullet will always be properly vertically aligned with text, no tweaks necessary.

Cons:

  • Requires extra elements.

Also, if you don't want to hand code all the extra divs, you can just make a normal list and then run this function to transform it, passing your ul as the parameter:

function fixList (theList) {
  theList.find('li').each(function (_, li) {
    li = $(li);
    $('<div/>').html(li.html()).appendTo(li.empty());
    $('<div/>').text('•').prependTo(li);
  });
}

Example:

_x000D_
_x000D_
li {_x000D_
  font-family: sans-serif;_x000D_
  list-style-type: none;_x000D_
  display: flex;_x000D_
}_x000D_
_x000D_
li > div:first-child {_x000D_
  margin-right: 0.75ex; /* set to desired spacing */_x000D_
}
_x000D_
<ul>_x000D_
  <li><div>•</div><div>First list item.</div>_x000D_
  <li><div>•</div><div>Second list item.<br>It's on two lines.</div>_x000D_
  <li><div>•</div><div>Third <i>list</i> item.</div>_x000D_
</ul>
_x000D_
_x000D_
_x000D_

Here's an example using the function:

_x000D_
_x000D_
fixList($('ul'));_x000D_
_x000D_
function fixList (theList) {_x000D_
  $('li', theList).each(function (_, li) {_x000D_
    li = $(li);_x000D_
    $('<div/>').html(li.html()).appendTo(li.empty());_x000D_
    $('<div/>').text('•').prependTo(li);_x000D_
  });_x000D_
}
_x000D_
li {_x000D_
  font-family: sans-serif;_x000D_
  list-style-type: none;_x000D_
  display: flex;_x000D_
}_x000D_
_x000D_
li > div:first-child {_x000D_
  margin-right: 0.75ex;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<ul>_x000D_
  <li>First list item._x000D_
  <li>Second list item.<br>It's on two lines._x000D_
  <li>Third <i>list</i> item._x000D_
</ul>
_x000D_
_x000D_
_x000D_


You could try the following. But it requires you to put a <span> element inside the <li> elements

<html>
<head>
<style type="text/css">
ul.a li span{
position:relative;
left:-0.5em;

}
</style>
</head>

<body>

<ul class="a">
  <li><span>Coffee</span></li>
  <li><span>Tea</span></li>
  <li><span>Coca Cola</span></li>
</ul>
</body>
</html>