+5

Tự động đánh số và đếm số phần tử thay đổi trạng thái bằng CSS

Đánh số chỉ mục tự động.

Việc tự động đếm số trong CSS có hai thuộc tính cơ bản là:

  • counter-reset- dùng để reset lại số đếm, bắt đầu từ một số cụ thể.
  • counter-increment- dùng để tăng số đếm, mỗi lần một đơn vị.

Kết hợp với sử dụng các pseudo-classes như :hover, active, checked... và các pseudo-elements như :before, after..., chắc các bạn cũng đã quen thuộc, có thể tìm hiểu thêm:

Cú pháp sử dụng như sau:

body {
  counter-reset: number; //Mặc định, trong body, biến number sẽ reset number về 0
}

// Đằng trước mỗi thẻ `h2`
h2::before {
  counter-increment: number; //Tăng number lên, mỗi lần tăng 1 đơn vị
  content: counter(number); //In kết quả
}

Với code như trên, các thẻ h2 trong khối body sẽ lần lượt được đánh số tăng dần, bắt đầu từ 1. Nếu muốn bắt đầu từ một số bất kỳ khác, giả sử là 2 chẳng hạn, bạn có thể thêm vào thuộc tính counter-reset như sau:

body {
  counter-reset: number 1;
}

Nếu có các mục con nhỏ hơn bên trong cũng cần đánh số, ta có thể làm hoàn toàn tương tự. Giả sử với một view html đơn giản có cả thẻ h2h3 bên trong nó như sau:

<body>
  <h1>Automatic Numbering with CSS Counter</h1>

  <h2>Header</h2>
  <p>The first h2 tag</p>

  <h2>Header</h2>
  <p>The second h2 tag</p>

  <h3>Sub header</h3>
  <p>The first h3 tag of the second h2 tag</p>

  <h3>Sub header</h3>
  <p>The second h3 tag of the second h2 tag</p>
</body>

Ta sẽ đánh số chỉ mục bằng CSS như sau:

body {
  counter-reset: first; //Reset biến first về 0
}
h2 {
  counter-reset: second; //Reset biến second về 0
}
h3 {
  counter-reset: third; //Reset biến third về 0
}
h2:before {
  counter-increment: first; //Tăng biến first lên 1 đơn vị
  content: counter(first, upper-roman) " "; //Đánh chỉ mục bằng số la mã
}
h3:before {
  counter-increment: second; //Tăng biến second lên 1 đơn vị
  content: counter(first) "." counter(second) ": ";
}

Kết quả:

Code demo

Khi đã nắm được cách dùng các thuộc tính counter-resetcounter-increment trong CSS, ta hãy cùng đi sang một phần nâng cao hơn một chút nhé.

Đếm số thành phần HTML thay đổi trạng thái theo thời gian thực bằng CSS.

Thực ra, bạn hoàn toàn có thể dùng JS để thực hiện việc này, tuy nhiên trong bài viết này, mình xin đề cập đến cách sử dụng chính CSS, đảm bảo nó sẽ đơn giản hơn nhiều.

Mình xin trình bày thông qua ví dụ với các loại thành phần phổ biến có thể thay đổi trạng thái trong HTML.

1. Checkbox.

Đặt ra bài toán là đếm số checkbox đã được click chọn và không được click chọn trong page, ta làm như sau:

<body>
  <input type='checkbox'> checkbox #1<br>
  <input type='checkbox'> checkbox #2<br>
  <input type='checkbox'> checkbox #3<br>
 
  <br>Checked: <b id='tickedBoxCount'></b>
  <br>Unchecked: <b id='unTickedBoxCount'></b>
</body>
body {
  counter-reset: tickedBoxCount, unTickedBoxCount;
}
input[type='checkbox'] {
  counter-increment: unTickedBoxCount; //Với checkbox không được click thì tăng unTickedBoxCount lên 1 đơn vị
}
//Dùng pseudo-class :checked
input[type='checkbox']:checked {
  counter-increment: tickedBoxCount; //Với checkbox được click thì tăng tickedBoxCount lên 1 đơn vị
}
#tickedBoxCount::before {
  content: counter(tickedBoxCount);
}
#unTickedBoxCount::before {
  content: counter(unTickedBoxCount);
}

Cũng đơn giản thôi nhỉ.

Kết quả:

Code demo

2. Text input.

Đặt ra bài toán là đếm được số text box người dùng đã điền và đang để trống theo thời gian thực.

Với thẻ <input> hay là <textarea>, có :placeholder-shown là một pseudo-class để nhận ra việc người dùng đã điền text vào ô trống hay chưa. Tham khảo thêm ở đây.

Code như sau:

<body>
    <input type=text placeholder='placeholder text'><br>
    <input type=text placeholder='placeholder text'><br>
    <input type=text placeholder='placeholder text'><br>

    <br> Filled: <b id=filledInputCount></b>
    <br> Empty: <b id=emptyInputCount></b>
</body>
body{
  counter-reset: filledInputCount, emptyInputCount;
}
input[type='text']{
  counter-increment: filledInputCount; //Khi đã điền text thì tăng biến filledInputCount lên
}
input[type='text']:placeholder-shown{
  counter-increment: emptyInputCount; //Khi vẫn còn placeholder, nghĩa là chưa điền text thì tăng biến emptyInputCount lên
}
#filledInputCount::before{
  content: counter(filledInputCount);
}
#emptyInputCount::before{
  content: counter(emptyInputCount);
}
b{
  color: red;
}

Kết quả:

Code

3. Details.

Việc đếm số phần tử thay đổi trạng thái không phải bao giờ cũng thông qua các pseudo-classes mà các thuộc tính HTML cũng có thể làm được việc đó. Đó là trường hợp của phần tử <details>.

Phần từ <details> sẽ chứa các phần tử con <summary> ở bên trong nó, và khi người dùng click vào <details> thì nội dung chi tiết trong <summary> sẽ được hiển thị ra. Do đó, <details> sẽ có thể ở hai trạng thái: đóng và mở.

Chú ý là phần tử <summary> luôn phải là con đầu tiên trong các con của <details>.

Xem ví dụ sau:

<details>
  <summary>Q1: question #1</summary>
  <p>answer #1</p>
</details>
<details>
  <summary>Q2: question #2</summary>
  <p>answer #2</p>
</details>
<details>
  <summary>Q3: question #3</summary>
  <p>answer #3</p>
</details>
<br>
<br> Open: <b id='openDetailCount'></b>
<br> Closed: <b id='closedDetailCount'></b>
{
  counter-reset: openDetailCount, closedDetailCount;
}
details{
  counter-increment: closedDetailCount;
}
details[open]{
  counter-increment: openDetailCount; //Khi click vào details, tức là chuyển nó về open thì tăng biến openDetailCount lên
}
#closedDetailCount::before{
  content: counter(closedDetailCount);
}
#openDetailCount::before{
  content: counter(openDetailCount);
}

Kết quả:

Code


Tham khảo:


Hi vọng sẽ có ích với bạn. Cám ơn bạn đã dành thời gian đọc bài viết!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí