# CSS – Element number selector

Take a chestnut

The scene of a

Today when writing the hexo-Theme-zhaoo article table of Contents (TOC), there is a requirement that the title is not displayed when the table of contents does not exist.

Abstract the DOM structure:

<aside class="toc-wrap">
  <h3 class="toc-title">Article Contents:</h3>
  <ol class="toc">.</ol>
</aside>
Copy the code

The most straightforward idea is to match.toc and hide the.toc-title that precedes it if it doesn’t exist. But CSS does not select forward because that would cause backtracking. (See: # How to advise the W3C on Web standards? – Answer by Mr Stephen He)

You need to find a way to save the world by using their common parent element,.toc-wrap. If.toc-wrap has only one child, hide it. As follows:

.toc-wrap
  & > :only-child
    display none
Copy the code

šŸŒ° is very simple, but worth thinking about, CSS really can’t “forward choice”?

Scenario 2

Early BootStrap uses a lot of repetitive code when building rasterized layouts, like this:

@media (min-width: 768px) {
  .col-md-1 { flex: 0 0 8.33333%; max-width: 8.33333%; }
  .col-md-2 { flex: 0 0 16.6667%; max-width: 16.6667%; }
  .col-md-3 { flex: 0 0 25%; max-width: 25%; }
  .col-md-4 { flex: 0 0 33.3333%; max-width: 33.3333%; }
  .col-md-5 { flex: 0 0 41.6667%; max-width: 41.6667%; }
  .col-md-6 { flex: 0 0 50%; max-width: 50%; }
  .col-md-7 { flex: 0 0 58.3333%; max-width: 58.3333%; }
  .col-md-8 { flex: 0 0 66.6667%; max-width: 66.6667%; }
  .col-md-9 { flex: 0 0 75%; max-width: 75%; }
  .col-md-10 { flex: 0 0 83.3333%; max-width: 83.3333%; }
  .col-md-11 { flex: 0 0 91.6667%; max-width: 91.6667%; }
  .col-md-12 { flex: 0 0 100%; max-width: 100%; }}@media (min-width: 992px) {
  .col-lg-1 { flex: 0 0 8.33333%; max-width: 8.33333%; }
  .col-lg-2 { flex: 0 0 16.6667%; max-width: 16.6667%; }
  .col-lg-3 { flex: 0 0 25%; max-width: 25%; }
  .col-lg-4 { flex: 0 0 33.3333%; max-width: 33.3333%; }
  .col-lg-5 { flex: 0 0 41.6667%; max-width: 41.6667%; }
  .col-lg-6 { flex: 0 0 50%; max-width: 50%; }
  .col-lg-7 { flex: 0 0 58.3333%; max-width: 58.3333%; }
  .col-lg-8 { flex: 0 0 66.6667%; max-width: 66.6667%; }
  .col-lg-9 { flex: 0 0 75%; max-width: 75%; }
  .col-lg-10 { flex: 0 0 83.3333%; max-width: 83.3333%; }
  .col-lg-11 { flex: 0 0 91.6667%; max-width: 91.6667%; }
  .col-lg-12 { flex: 0 0 100%; max-width: 100%; }}Copy the code

This can be simplified with CSS preprocessors, but there is still a lot of repetitive code after compilation.

for $i in 1.12
  .col-{$i}
    col-attr round(($i * 100 / 12) %, 6)
@media (min-width 576px)
  for $i in 1.12
    .col-sm-{$i}
      col-attr round(($i * 100 / 12) %, 6)
@media (min-width 768px)
  for $i in 1.12
    .col-md-{$i}
      col-attr round(($i * 100 / 12) %, 6)
@media (min-width 992px)
  for $i in 1.12
    .col-lg-{$i}
      col-attr round(($i * 100 / 12) %, 6)
@media (min-width 1200px)
  for $i in 1.12
    .col-xl-{$i}
      col-attr round(($i * 100 / 12) %, 6)
Copy the code

Soul searching, is CSS really not suitable for dealing with “repeated elements” scenarios?

Front knowledge

Some CSS3 selectors:

  • >Child element selector
  • +Adjacent element selector
  • ~Sibling element selector

Some CSS3 pseudo-classes:

  • :only-childThe unique child of the parent element
  • :first-childThe first child of the parent element
  • :last-childThe last child of the parent element
  • :nth-child(n)The NTH child of the parent element
  • :nth-last-child(n)The penultimate NTH child of the parent element
  • :nth-child(xn+y)The xN + y child of the parent
  • :nth-last-child(xn+y)The penultimate xN + y child of the parent

A chemical reaction

Combining the above selectors with pseudo-classes can lead to some interesting “chemistry” that matches styles based on the number of elements.

The DOM structure is as follows:

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>.</ul>
Copy the code

AndrƩ Luƭs

Andre Luis:

/* There is only one element */
ul>li:nth-child(1):nth-last-child(1) { width: 100%; }  /* matches the first element */
ul>li:only-child { width: 100%; }  /* matches the first element */
Copy the code
/* with only two elements */
ul>li:nth-child(1):nth-last-child(2),  /* matches the first element */
ul>li:nth-child(2):nth-last-child(1) {  /* matches the second element */
	width: 50%;  /* matches all elements */
}
Copy the code
/* with three and only three elements */
ul>li:nth-child(1):nth-last-child(3),
ul>li:nth-child(2):nth-last-child(2),
ul>li:nth-child(3):nth-last-child(1) {
	width: 33.3333%;
}
Copy the code

Clever lists with CSS3 selectors

Lea Verou

One problem with the above scheme is that when there are too many elements, there are still a large number of repeat selectors. The upgraded Lea Verou solution requires only two fixed lines of selectors.

/* There is only one element */
ul>li:first-child:nth-last-child(1) {
	width: 100%;
}
Copy the code
/* with only two elements */
ul>li:first-child:nth-last-child(2),
ul>li:first-child:nth-last-child(2) ~ li {
	width: 50%;
}
Copy the code
/* with three and only three elements */
ul>li:first-child:nth-last-child(3),  /* matches the first element */
ul>li:first-child:nth-last-child(3) ~ li {  /* Matches all elements except the first */
	width: 33.3333%;
}
Copy the code

Styling elements based on sibling count

To improve

When the number of elements is not determined:

/* > three elements */
ul>li:first-child:nth-last-child(n+3),
ul>li:first-child:nth-last-child(n+3) ~ li {
  width: calc(100% / n);
}
Copy the code

conclusion

The above method can solve the problems of forward selection and repeated elements, and the parent element can be used flexibly in the actual scene.