Use CSS to alternate ul bullet point styles
Asked Answered
K

6

13

I would like to alternate list-style-type properties for ul lists, so that the outer is a disc, then one inner ul list is a circle, than one more inner is a disc, and so on.

Essentially, what I want is this:

<ul><!-- use disc -->
  <li>Lorem ipsum</li>
  <li>
    <ul><!-- use circle -->
      <li>Lorem ipsum</li>
      <li>
        <ul><!-- use disc -->
          <li>Lorem ipsum</li>
        </ul>
      </li>
      <li>Lorem ipsum</li>
    </ul>
  </li>
  <li>Lorem ipsum</li>
</ul>

How would I accomplish this using CSS?

Kisung answered 28/3, 2011 at 3:34 Comment(2)
Is the number of nesting levels fixed? Because if not, it will be pretty difficult to accomplish this with CSS alone.Erato
No, I am attempting to repeat list-style-type for an list that can be as long as possible, though if need be, I may manually code-in indenting levels, if there is other solution. If a JavaScript solution works, that is acceptable as well.Kisung
T
20

Like this...

li { list-style: circle; }
li li { list-style: disc; }
li li li { list-style: square; }

And so on...

The first level of list items will have the "circle" type marker. The second (embedded) will use "discs". The third level will use squares.

Simply take the above CSS and change the list-style to suit your needs. You can find a list of list-style types here: http://www.w3schools.com/cssref/pr_list-style-type.asp

Torin answered 28/3, 2011 at 3:41 Comment(1)
That doesn't work; you get two bullets after the first li, with my example code. In addition, your bullet styles don't continue repeating the same pattern of list-style.Kisung
K
4

You could use separate styles by adding class or id to the ul tags:

<ul class="disk"><!-- use disk -->
  <li>Lorem ipsum</li>
  <li>
    <ul class="circle"><!-- use circle -->
      <li>Lorem ipsum</li>
      <li>
        <ul class="disk"><!-- use disk -->
          <li>Lorem ipsum</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
.disk
{
    list-style-type: disc;
}

.circle
{
    list-style-type: circle;
}

Or you could add styles to uls depending on how they are nested:

ul
{
    list-style-type:disc;
}

ul li ul
{
    list-style-type:circle;
}

ul li ul li ul
{
    list-style-type:disc;
}

Off the top of my head, so there might be some minor errors, but both these examples should basically work.

Kamilahkamillah answered 28/3, 2011 at 3:47 Comment(0)
C
2

It's best to give each element with different bullet type a class name.

<ul>
    <li class="disk">test</li>
    <li class="circle">test</li>
    <li class="sq">test</li>
    <li class="sq">test</li>
</ul>
.disk {    
    list-style-type: disc;
}
.circle {
    list-style-type: circle;
}
.sq {
    list-style-type: square;
}

Check working example at http://jsfiddle.net/LWQrh/

Champignon answered 28/3, 2011 at 3:46 Comment(6)
What I need, though, is for bullets to switch while being embedded within other li elements.Kisung
You can't do that. you need to reference each level of your ul or li's with a class name. Otherwise you will have double or triple bullets depending on how deep your tree is.Champignon
Is it possible to use CSS3 selectors for browsers that support them, and use ids for browsers that don't support them?Kisung
That's being redundant, No reason to use css3 if you are using id's.Champignon
Would it be possible using PHP or JavaScript to automatically generate lists with the correct ids?Kisung
Downvoted - you should not name CSS styles based on visual appearance.Epiphenomenon
K
0

I have found the reason why I get double bullets. My lists are not semantically correct, so they are creating multiple bullets.

This is the proper HTML:

<ul><!-- use disc -->
  <li>Lorem ipsum
    <ul><!-- use circle -->
      <li>Lorem ipsum
        <ul><!-- use disc -->
          <li>Lorem ipsum</li>
        </ul>
      </li>
      <li>Lorem ipsum</li>
    </ul>
  </li>
  <li>Lorem ipsum</li>
</ul>

With the fixed code, the solutions above work.

Kisung answered 21/4, 2011 at 19:15 Comment(0)
B
0

The simple answer to this one is no, it cannot be accomplished through CSS in a consistent manner.

You could write some javascript to parse through the page and basically maintain a stack of ULs, but it would be kind of sloppy and hackish. It'd have to be something like this.

function doStyle(htmlBlock, depth)
    var returnHtml = '';

    // While the HTML block presented has UL tags within it
    while(htmlBlock.indexOf('<ul>') > 0) {

        // Take all the content up to the next/first <UL>
        returnHtml += htmlBlock.substring(0, htmlBlock.indexOf('<ul>'));

        // Add a styled <UL>, alternating on depth
        returnHtml += '<ul class="' + (depth % 2 == 0 ? 'square' : 'circle') + '">';

        // Recurse on the content inside that UL, using depth + 1
        returnHtml += doStyle(htmlBlock.substring(htmlBlock.indexOf('<ul>'), htmlBlock.indexOf('</ul>')), depth + 1);

        // Close the <UL>
        returnHtml += '</ul>';

        // Pull the whole UL block out of the remaining string
        htmlBlock = htmlBlock.substring(htmlBlock.indexOf('</ul>') + 5);
    }

    // Return the built up string, 
    // And whatever is left of the original HTML block
    return returnHtml + htmlBlock;
}
Banker answered 23/4, 2012 at 16:54 Comment(0)
M
0

Modern CSS features mean that alternating bulleted list styles can now be styled so that they recur infinitely without needing to deeply nest selectors.

This technique relies on container style queries to check the nearest parent's bullet type, and change to a different type.

⚠ at time of writing, browser support is limited, and those that do support style queries only support style queries on custom properties. So a custom --type property is used in lieu of list-style-type. In the future list-style-type will be able to be queried directly.

First we set up the default list styles. A container name is used to ensure that the queries only apply to list containers. You can update container-name to whatever name you prefer.

ul {
  --type: disc;
  container-name: list;
  list-style-type: var(--type);
}

Then we query for list containers that have a --type of disc, and apply a new --type to lists within those containers.

@container list style(--type: disc) {
  ul {
    --type: circle;
  }
}

If we stop here, the topmost ul (level 1: ul) will have a list-style-type of disc because the container query doesn't apply.

Any ul (level 2: ul ul) within it will have a list-style-type of circle because the container query applies.

A ul nested within those uls (level 3: ul ul ul) will have a list-style -type of disc again because the container query doesn't apply.

This will continue alternating infinitely.

Additional steps can be added to the cycle by adding additional container queries:

@container list style(--type: circle) {
  ul {
    --type: square;
  }
}

Lastly it's worth noting that CSS nesting allows us to nest the container queries to reduce some of the redundant selectors.

ul {
  --type: disc;
  container-name: list;
  list-style-type: var(--type, disc);
  
  @container list style(--type: disc) {
    --type: circle;
  }
  
  @container list style(--type: circle) {
    --type: square;
  }
}
<ul>
  <li>
    <p>1</p>
    <ul>
      <li>
        <p>1.1</p>
        <ul>
          <li>
            <p>1.1.1</p>
            <ul>
              <li>
                <p>1.1.1.1</p>
                <ul>
                  <li>
                    <p>1.1.1.1.1</p>
                    <ul>
                      <li>
                        <p>1.1.1.1.1.1</p>
                      </li>
                    </ul>
                  </li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
Marquetry answered 31/7 at 17:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.