Ordered list (HTML) lower-alpha with right parentheses?
Asked Answered
A

8

118

The default lower-alpha list type for ordered list uses a dot '.'. Is there a way to use a right parenthesis instead like a)... b) ..etc?

Agrarian answered 27/10, 2009 at 16:23 Comment(1)
Maybe one of the answer can be picked as correct ?...Ruffo
P
208

Here's a neat solution. (Honestly I surprised myself with this.) CSS has something called counters, where you can set, for example, automatic chapter numbers on each heading. A bit of modification gives you the below; You'll need to sort out padding etc yourself.

ol {
  counter-reset: list;
}
ol > li {
  list-style: none;
}
ol > li:before {
  content: counter(list, lower-alpha) ") ";
  counter-increment: list;
}
<span>custom list style type (v1):</span>
<ol>
  <li>Number 1</li>
  <li>Number 2</li>
  <li>Number 3</li>
  <li>Number 4</li>
  <li>Number 5</li>
  <li>Number 6</li>
</ol>

Works in all modern browsers and IE9+ (and possibly IE8 but may be buggy).

Update: I added child selector to prevent nested lists picking up the parent style. trejder also beings up a good point in the comments that the list item alignment is also messed up. An article on 456bereastreet has a good solution which involves absolutely positioning the counter.

ol {
    counter-reset: list;
}
ol > li {
    list-style: none;
    position: relative;
}
ol > li:before {
    counter-increment: list;
    content: counter(list, lower-alpha) ") ";
    position: absolute;
    left: -1.4em;
}
<span>custom list style type (v2):</span>
<ol>
  <li>Number 1</li>
  <li>Number 2</li>
  <li>Number 3</li>
  <li>Number 4</li>
  <li>Number 5</li>
  <li>Number 6</li>
</ol>

Here is a jsFiddle showing the result, including nested lists.

Prescind answered 28/10, 2009 at 11:18 Comment(12)
You are right, this doesn't work in IE6. But good news it works on Firefox 3.5.3.Style
Actually it would be better if: ol { counter-reset: list; } The original one would not work when there are multiple ols.Glennieglennis
FYI, to get a numbered list instead of alphabetical, just remove the , lower-alpha. So the content value would be counter(list) ") ";Hearn
Let me only add, that this isn't 100% real numbering. You can see the difference on multi-line items. In normal lists (using standard bullets or numbers) each line has the same indent, so bullet or number looks like standing before block of text. With above solution, each next line starts below numbering and isn't slightly inset. Which doesn't change the fact, that this is really neat solution! :>Tiliaceous
Plus: This fails completely on multi-level lists (my example at jsFiddle).Tiliaceous
Since this involves a pseudo-element, can I assume that this can't be done with inline CSS in a <style> element?Hobbyhorse
@user1269964 no, but if you're doing that you may as well just write a) b) etc in the document itselfPrescind
I think counter-increment: list; should be added to ol > li, not ol > li:before (Chrome)Patsypatt
Nice. Thank you! I'd prefer to add list-style-type: none; to the ol specifications instead of having list-style: none; in the li specs.Throughout
having tested it, I realise that this wouldn't respect start attribute of the ol elementCauvery
FYI it should be counter-reset: list-item list;. Firefox implements the default list-item counter using the UA stylesheet, so doing counter-reset: list-item list; removes the default reset and breaks any non-customized lists. More on that: github.com/w3c/csswg-drafts/issues/4244Cosine
This breaks apart when the list items are empty (the all get stacked in the same place). A fix for this would be to add an :after pseudo element to li with content \a0 (nbsp)Coh
Q
28

More than 10 years after the original question the standard (and, to some extent, implementations) seem to have caught up.

CSS now provides ::marker pseudoclass which can be used to achieve custom list markers: MDN.

Using ::marker automatically indents li's content without any hacks. According to MDN, as of Feb 2021 it's supported in Firefox, Chrome and Edge, and partially (not for this use case) in Safari.

.container {
  width: 400px;
}

ol.custom-marker {
  counter-reset: list;
}

ol.custom-marker > li {
  list-style: none;
  counter-increment: list;
}

ol.custom-marker.parens-after.decimal > li::marker {
  content: counter(list) ")\a0";
}

ol.custom-marker.parens-around.lower-roman > li::marker {
  content: "(" counter(list, lower-roman) ")\a0";
}
<div class='container'>
  <ol class='custom-marker parens-after decimal'>
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eu sem integer vitae justo eget magna fermentum. Quis varius quam quisque id diam.</li>
    <li>Another list here
      <ol class='custom-marker parens-around lower-roman'>
        <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eu sem integer vitae justo eget magna fermentum. Quis varius quam quisque id diam.</li>
        <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eu sem integer vitae justo eget magna fermentum. Quis varius quam quisque id diam.</li>
      </ol>
    </li>
    <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eu sem integer vitae justo eget magna fermentum. Quis varius quam quisque id diam.</li>
  </ol>
</div>

\a0 in content is &nbsp;, since ::marker doesn't support margins or padding.

Quintinquintina answered 1/2, 2021 at 21:47 Comment(1)
This is the most practical answer. List markers are supposed to align to the right and this method covered it correctly.Sandarac
S
14

building off of DisgruntledGoat's answer, I expanded it to support sub lists & styles as I needed. Sharing it here in case it helps someone.

https://jsfiddle.net/0a8992b9/ outputs:

(i)first roman
    (a)first alpha
    (b)second alpha
    (c)third alpha
    (d)fourth alpha
(ii)second roman
(iii)third roman
    (a)first alpha
    (b)second alpha
Seal answered 15/7, 2015 at 14:39 Comment(3)
+1 You did a reset for alpha. that helped me a lot. Thanks a lot. If someone doesn't have the alpha class, he can use ol[style*="list-style-type: lower-alpha;"]Phenomenalism
is there a way to have this while also having the text remain to the right of the letter used in the place of a bullet point? i.e. not having the text wrap to under the letter (e.g. a) ) but rather wrap back to the point where the text begins for a particular letter point, as the regular <li> would lookGrenadine
@Grenadine add a negative value for text-indent to the li levelDonnell
A
10

In Firefox and newer versions of Chrome/Edge/Chromium, you can define your own counter style with @counter-style and use the prefix and suffix properties to define what comes before/after the counter. According to MDN, this still isn't supported in Safari (as of Nov 2022).

@counter-style my-new-list-style {
  system: extends lower-alpha;
  suffix: ') ';
}

.container ol {
  list-style: my-new-list-style;
}
<div class="container">
  <ol>
    <li>One.</li>
    <li>Two!</li>
    <li>Three?</li>
    <li>Four...</li>
  </ol>
</div>
Abbotson answered 21/10, 2021 at 22:43 Comment(1)
It is now supported in all current versions of major browsers as of Oct 2023.Yuk
G
4

Adding this to the CSS gave some interesting results. It was close, but no cigar.

li:before {
    display: inline-block;
    width: 1em; 
    position: relative;
    left: -0.5em; 
    content: ')'
}

----- Edited to include solution from Iazel, in the comments -----

I've perfected your solution:

li {
    position: relative;
}
li:before {
    display: inline-block;
    width: 7px;
    position: absolute;
    left: -12px;
    content: ')';
    background-color: #FFF;
    text-align: center;
}

The background and position: absolute did the trick!

Gardy answered 27/10, 2009 at 18:54 Comment(1)
I've perfected your solution: li { position: relative; } li:before { display: inline-block; width: 7px; position: absolute; left: -12px; content: ')'; background-color: #FFF; text-align: center; } The background and position: absolute did the trick! :)Infante
L
0

This seems to work:

ol {
  counter-reset: list;
  margin: 0;
}

ol > li {
  list-style: none;
  position: relative;
}

ol > li:before {
  counter-increment: list;
  content: counter(list, lower-alpha) ") ";
  position: absolute;
  left: -1.4em;
}
Lancelancelet answered 28/4, 2021 at 3:23 Comment(0)
R
-1

Here's a simple yet flexible solution I sometimes use:

   <pre>
    a) Item 1
    b) Item 2
    c) Item 3       
   </pre>

You can freely choose the 'marker' you put in front of each list-element.

This works well when the list is not too long or not too frequently edited.

You may want to set font-family of <pre> to Verdana perhaps, so it is not too small.

Rondelet answered 12/12, 2023 at 3:5 Comment(3)
Doing this means you lose all of the advantages of having your list marked up semantically as, well... a list. The most obvious problem is that screen readers will no longer identify it as a list, and may have trouble working out how to read the "a)", "b)" bits.Minaret
It's great if you have the time to test all your html with all the different screen-readers out there. But not every project requires all that. Simplicity and brevity have value of their own. Many people prefer writing their stuff in Markdown because it is simpler even if it doesn't work well with screen-readers perhaps.Rondelet
Panu - not having to test your site in every screen reader is exactly the advantage of semantic mark-up. User agents know that a list is a list and can render it appropriately for their users. They don't know that your preformatted text is a list.Minaret
P
-9

This works for me in IE7, FF3.6, Opera 9.64 and Chrome 6.0.4:

<ol start="a" type="a" style="font-weight: normal;">
<li><span style="inline-block;margin-left: -9px !important; margin-left: -15px;">) &nbsp;</span> content for line number one;</li>
<li><span style="inline-block;margin-left: -9px !important; margin-left: -15px;">) &nbsp;</span>  content for line number two;</li>
<li><span style="inline-block;margin-left: -9px !important; margin-left: -15px;">) &nbsp;</span>  content for line number three;</li> 
<li><span style="inline-block;margin-left: -9px !important; margin-left: -15px;">) &nbsp;</span>  content for line number four;</li>
<li><span style="inline-block;margin-left: -9px !important; margin-left: -15px;">) &nbsp;</span>  content for line number five;</li>
<li><span style="inline-block;margin-left: -9px !important; margin-left: -15px;">) &nbsp;</span>  content for line number six;</li>
</ol>

this is inline because it is coded for an email, but the main point is that the span acts as a content block and pulls the paren into negative left territory so it lines up with the list numbers. the two margins are to compensate for IE7 and FF differences

hope this helps.

Proprioceptor answered 6/10, 2010 at 0:43 Comment(2)
Are you sure that's not supposed to be display:inline-block; ?Pulsate
This is a hack because it's dependent on the font size when trying to place the paren next to the auto-generated "a", "b", etc char. If you were going to do something like this, you should use list-style-type:none and take over rendering the entire "a)" yourself rather than trying to just render the paren.Lillylillywhite

© 2022 - 2024 — McMap. All rights reserved.