Can you count a particular class with CSS?
Asked Answered
F

7

32

Lets say I have a simple list like so:

<ol>
    <li class="count">one</li>
    <li class="count">two</li>
    <li class="count">three</li>
    <li class="count">four</li>
    <li>blabla</li>
    <li class="count">five</li>
    <li class="count">six</li>
    <li>blabla</li>
    <li class="count">seven</li>
</ol>

Now I only want to number list items with the class 'count'

So If I add the CSS:

li {
    list-style-type: decimal;
}

and then remove the list-style-type for list items without the class:

li:not(.count) {
    list-style-type: none;
}

I get this:

FIDDLE

li {
  list-style-type: decimal;
}
li:not(.count) {
  list-style-type: none;
}
<ol>
  <li class="count">one</li>
  <li class="count">two</li>
  <li class="count">three</li>
  <li class="count">four</li>
  <li>blabla</li>
  <li class="count">five</li>
  <li class="count">six</li>
  <li>blabla</li>
  <li class="count">seven</li>
</ol>

The obvious problem here is that the list items without the class are also 'counted' here, just not shown.

So in the above example, the list should be numbered to 7 - with the numbering skipping the list items without the class. Can this be done with CSS?

Fructidor answered 10/11, 2014 at 10:39 Comment(2)
To be pedantic: if you want numbers for your list items then this might best be represented as an ordered list <ol>Ailsun
@Ailsun - thanks for pointing that out - I edited the question to use an ordered list <ol>Fructidor
F
34

This can be done with CSS-counters

If I set display:none on the generated content with the counter, the counter skips over it, and continues to the next item!

FIDDLE

(Edit: Or, alternatively - as others have pointed out - we could increment the counter only on the elements with the particular class - like so)

ol {
  counter-reset: count;
  list-style-type: none;
  padding-left: 30px;
}
li:before {
  content: counter(count)".";
  counter-increment: count;
}
li:not(.count) {
  padding-left: 13px;
}
li:not(.count):before {
  display: none;
}
<ol>
  <li class="count">one</li>
  <li class="count">two</li>
  <li class="count">three</li>
  <li class="count">four</li>
  <li>blabla</li>
  <li class="count">five</li>
  <li class="count">six</li>
  <li>blabla</li>
  <li class="count">seven</li>
</ol>

So actually, with counters, not only can we count classes, we can also count any selector combination.

Here's an example for proof of concept:

html {
  counter-reset: divs;
}
body {
  counter-reset: paragraphs;
  position: relative;
}
div {
  counter-increment: divs;
}
.wpr {
  counter-reset: count-me;
  position: relative;
}
.container {
  position: relative;
  border-bottom: 1px solid green;
}
.container .count-me {
  counter-increment: count-me;
}
.container p {
  counter-increment: paragraphs;
}
.wpr:after {
  content: "Number of count-me classes in container:" counter(count-me);
  position: absolute;
  bottom: -20px;
}
.container:after {
  content: "Number of paragraphs:" counter(paragraphs);
  position: absolute;
  bottom: -40px;
}
body:after {
  content: "Number of divs:" counter(divs);
  position: absolute;
  bottom: -60px;
}
<div class="wpr">div1
  <div class="container">div2
    <div>div3
      <span class="count-me">count-me</span>
    </div>
    <div>div4
      <span class="count-me">count-me</span>
      <p>I"m a paragragh</p>
    </div>
    <div>div5
      <p>I"m a paragragh</p>
    </div>
    <div>div6
      <span class="count-me">count-me</span>
    </div>
    <div>div7
      <span class="count-me">count-me</span>
      <p>I"m a paragragh</p>
    </div>
    <div>div8</div>
  </div>
</div>
Fructidor answered 10/11, 2014 at 10:42 Comment(2)
Alternatively, you may set the class name to nocount instead and assign it to the items without a counter. li:before would have the counter declaration and li.nocount:before the display:none declaration. Bonus points: make the UL position relative and the counter absolute: jsfiddle.net/em13s2qL/6Costplus
I really don't like to use the :not() selector. Old browsers will choke on that piece of css. Try this one instead: jsfiddle.net/q7zLz3nz which is much more compatible and oldie-friendly.Hinojosa
D
9

Giving display: block to the li elements without .count class is also working.

ul {
    list-style-type:decimal;
    padding-left: 30px;
}
li:not(.count) {
    display: block;
}

Working Fiddle

For older browsers:

ul {
    list-style-type:decimal;
    padding-left: 30px;
}
li {
    display: block;
}
li.count {
    display: list-item;
}

Working Fiddle

Another way, if you are planning to change the display state of all li elements, use :after/:before pseudo classes with display as list-item.

Working Fiddle

Discreditable answered 10/11, 2014 at 10:52 Comment(1)
Hey @Mr_Green, I decided to award you a bounty since your solution worked well too :)Fructidor
E
3

You can use HTML to set the value of a list item specifically:

<ul>
    <li class="count">one</li>
    <li class="count">two</li>
    <li class="count">three</li>
    <li class="count">four</li>
    <li>blabla</li>
    <li value="5" class="count">five</li>
    <li class="count">six</li>
    <li>blabla</li>
    <li value="7" class="count">seven</li>
</ul>

http://jsfiddle.net/03bu5sct/1/

You may also want to look at CSS3 counters if you want a pure CSS solution.

Emblements answered 10/11, 2014 at 10:49 Comment(1)
How about this css instead: li.count{list-style-type: decimal;}li{list-style-type: none;}?Hinojosa
B
3

The counters section in CSS 2.1 specifications contains various examples of how to implement your custom counter. Here is a very simple example where you:

  1. Define a counter variable
  2. Increment it for specific elements (in your case it would be .count elements)
  3. Display it inside pseudo elements

.custom-counter {
  /* define a counter variable */
  counter-reset: clumsycount 0;
  /* style */
  list-style-type: none;
}
.custom-counter .count {
  /* increment the counter variable */
  counter-increment: clumsycount 1;
  /* style */
  position: relative;
  background-color: #EEE;
}
.custom-counter .count:before {
  /* display the counter variable */
  content: counter(clumsycount) ".";
  /* style */
  position: absolute;
  top: 0;
  right: 100%;
  padding-right: .25em;
  background-color: #CCC;
}
<ul class="custom-counter">
  <li class="count">one</li>
  <li class="count">two</li>
  <li class="count">three</li>
  <li class="count">four</li>
  <li>blabla</li>
  <li class="count">five</li>
  <li class="count">six</li>
  <li>blabla</li>
  <li class="count">seven</li>
</ul>
Beichner answered 10/11, 2014 at 17:22 Comment(0)
S
3
li {
    list-style-type: decimal;
}

li:not(.count) {
      -webkit-appearance: textfield;
      -moz-appearance: textfield;
      appearance: textfield;
}

this is a simple hack http://jsfiddle.net/9w9vkcf3/1/

The appearance property is used to display an element using a platform-native styling based on the users' operating system's theme. source

Spleeny answered 25/4, 2015 at 15:55 Comment(0)
S
1

One solution could be to use CSS counters and apply it using pseudo-element :before taking advance of content property with counter,

Counters may be specified with two different functions: 'counter()' or 'counters()'. The former has two forms: 'counter(name)' or 'counter(name, style)'. The generated text is the value of the innermost counter of the given name in scope at this pseudo-element; it is formatted in the indicated style ('decimal' by default). The latter function also has two forms: 'counters(name, string)' or 'counters(name, string, style)'. The generated text is the value of all counters with the given name in scope at this pseudo-element, from outermost to innermost separated by the specified string. The counters are rendered in the indicated style ('decimal' by default). See the section on automatic counters and numbering for more information. The name must not be 'none', 'inherit' or 'initial'. Such a name causes the declaration to be ignored.

only in li elements with class count:

body {
  counter-reset: section;/* Set the section counter to 0 */
}
ol {
  list-style-type: none;
}
li.count::before {
  counter-increment: section;/* Increment the section counter*/
  content: counter(section)". ";/* Display the counter */
}
<ol>
  <li class="count">one</li>
  <li class="count">two</li>
  <li class="count">three</li>
  <li class="count">four</li>
  <li>blabla</li>
  <li class="count">five</li>
  <li class="count">six</li>
  <li>blabla</li>
  <li class="count">seven</li>
</ol>

References

counter-increment

counter-reset

Scrutator answered 24/4, 2015 at 14:23 Comment(0)
C
0

Here you go:

https://jsfiddle.net/Cheese1991/qnmhvvxj/

HTML:

<ul>
<li>One</li>
<li>Two</li>
<li class="skip">Skip</li>
<li>Three</li>
<li>Four</li>
</ul>

CSS:

ul {
    counter-reset:yourCounter;
    list-style:none;
}
ul li:not(.skip) {
    counter-increment:yourCounter;
    list-style:none;
}
ul li:not(.skip):before {
    content:counter(yourCounter) ". ";
}
ul li.skip:before {
    content:"\a0\a0\a0";
}

I hope this will help you

Conceptionconceptual answered 1/5, 2015 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.