Đếm trạng thái HTML Thay đổi Thời gian thực với CSS

Đếm là một công việc phổ biến trong các ứng dụng web. Bạn có bao nhiêu email chưa đọc? Có bao nhiêu nhiệm vụ không được chọn trong danh sách việc cần làm của bạn? Bao nhiêu miếng bánh được đóng gói trong giỏ hàng? Tất cả là những câu hỏi quan trọng mà người sử dụng xứng đáng nhận được.

Vì vậy, bài đăng này sẽ chỉ cho bạn cách đếm các phần tử được xác định hai lần, tạo thành phần lớn các kiểm soát của người dùng như checkbox và các input text , sử dụng các bộ đếm CSS.

Bạn cần nhắm mục tiêu các trạng thái đó bằng CSS đầu tiên, có thể bằng các pseudo-classes và các thuộc tính HTML cho phép chúng ta làm điều đó. Đi trước và thử nghiệm với ý tưởng và khám phá các pseudo-classes khác nhau có thể cho biết sự thay đổi trong trạng thái của một phần tử.

Chúng ta sẽ bắt đầu bằng các checkbox đơn giản nhất.

1. Checkboxes

Checkboxes đi vào trạng thái "checked" khi chúng được đánh dấu. Các :checked pseudo-class chỉ trạng thái được kiểm tra.

<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>
::root{
  counter-reset: tickedBoxCount, unTickedBoxCount;
}
input[type='checkbox']{
  counter-increment: unTickedBoxCount;
}
input[type='checkbox']:checked{
  counter-increment: tickedBoxCount;
}
#tickedBoxCount::before{
  content: counter(tickedBoxCount);
}
#unTickedBoxCount::before{
  content: counter(unTickedBoxCount);
}

Trường hợp này rất đơn giản. Chúng ta đặt hai bộ đếm tại phần tử gốc và tăng cho mỗi checkbox tương ứng với hai trạng thái của nó. Các giá trị đếm sau đó được hiển thị ở nơi được chỉ định sử dụng thuộc tính nội dung.

Dưới đây, bạn có thể xem kết quả cuối cùng. Khi bạn kiểm tra và bỏ chọn các checkbox, các giá trị của "Checked" và "Unchecked" được sửa đổi theo thời gian thực.

2. Text inputs

Chúng ta cũng có thể đếm bao nhiêu text-input đã được điền và có bao nhiêu người dùng để trống. Giải pháp này sẽ không đơn giản như trước, bởi vì, không giống như checkbox, text-input không có pseudo-classes để gắn cờ khi chúng được điền.

Vì vậy, chúng ta cần phải tìm một con đường thay thế. Có một pseudo-classes cho biết khi một phần tử có văn bản giữ chỗ; nó được gọi là: placeholder-shown.

Nếu chúng ta sử dụng các trình giữ chỗ trong phần nhập văn bản của chúng ta, chúng ta có thể biết khi trường đầu vào trống. Điều này xảy ra khi người dùng chưa nhập bất kỳ điều gì vào nó vì trình giữ chỗ sẽ biến mất khi điều đó xảy ra.

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>
::root{
  counter-reset: filledInputCount, emptyInputCount;
}
input[type='text']{
  counter-increment: filledInputCount;
}
input[type='text']:placeholder-shown{
  counter-increment: emptyInputCount;
}
#filledInputCount::before{
  content: counter(filledInputCount);
}
#emptyInputCount::before{
  content: counter(emptyInputCount);
}

Kết quả tương tự với kết quả trước - hai bộ đếm được tự động tăng và giảm khi chúng ta thêm hoặc xoá văn bản đến hoặc từ các trường đầu vào.

3. Radio buttons

Tính các radio buttons đòi hỏi một kỹ thuật khác. Chúng tôi chắc chắn có thể sử dụng :checked pseudo-class chúng ta sử dụng cho các checkbox. Tuy nhiên, các radio buttons được sử dụng khác với các checkbox.

Các radio buttons được đặt trong các nhóm. Người dùng chỉ có thể chọn một trong một nhóm. Mỗi nhóm hoạt động như một đơn vị duy nhất. Hai trạng thái một nhóm radio buttons có thể có là một trong hai nút được chọn hoặc không có nút nào được chọn.

Do đó, chúng ta không nên đếm các radio buttons theo các nút riêng lẻ, nhưng bằng các nhóm nút. Để đạt được điều đó, chúng ta sử dụng :nth-of-type.

<input type=radio name='radio-1'>radio-1.1
<input type=radio name='radio-1'>radio-1.2
<input type=radio name='radio-1'>radio-1.3
<br>
<input type=radio name='radio-2'>radio-2.1
<input type=radio name='radio-2'>radio-2.2
<input type=radio name='radio-2'>radio-2.3
<br>
<input type=radio name='radio-3'>radio-2.1
<input type=radio name='radio-3'>radio-2.2
<input type=radio name='radio-3'>radio-2.3
<br>
<br> Selected: <b id=selectedRadioCount></b>
<br> Unselected: <b id=unSelectedRadioCount></b>

Chúng ta cần gán cùng tên cho các radio buttons trong cùng một nhóm. Mỗi nhóm trong mã ở trên có ba radio buttons bên trong.

::root{
  counter-reset: selectedRadioCount, unSelectedRadioCount;
}
input[type='radio']:nth-of-type(3n){
  counter-increment: unSelectedRadioCount;
}
input[type='radio']:nth-of-type(3n):checked{
  counter-increment: selectedRadioCount;
}
input[type='radio']:not(:nth-of-type(3n)):checked{
  counter-increment: unSelectedRadioCount -1 selectedRadioCount;
}
#selectedRadioCount::before{
  content: counter(selectedRadioCount);
}
#unSelectedRadioCount::before{
  content: counter(unSelectedRadioCount);
}

Quy tắc ba kiểu đầu tiên trong đoạn mã trên tương tự với những quy tắc mà chúng ta áp dụng cho các checkbox, ngoại trừ thay vì nhắm mục tiêu mỗi radio buttons, chúng ta nhắm mục tiêu radio buttons cuối cùng trong mỗi nhóm, đây là thứ ba trong trường hợp của chúng ta (:nth-of-type(3n)). Vì vậy, chúng ta không tính tất cả các radio buttons nhưng chỉ có một cho mỗi nhóm.

Tuy nhiên, điều này sẽ không cho kết quả thời gian thực chính xác vì chúng ta chưa đưa ra bất kỳ quy tắc nào để tính hai radio buttons khác trong nhóm. Nếu một trong số đó được kiểm tra, nó nên được tính và kết quả không được kiểm soát sẽ giảm cùng một lúc.

Đây là lý do tại sao chúng ta thêm một giá trị -1 sau unSelectedRadioCount trong quy tắc kiểu cuối cùng nhằm vào hai radio buttons khác trong một nhóm. Khi một trong số chúng được kiểm tra, -1 sẽ giảm kết quả không được kiểm tra.

Vị trí của Counts

Bạn chỉ có thể nhìn thấy kết quả chính xác sau khi tính xong, nghĩa là sau khi tất cả các phần tử được đếm đã được xử lý. Đây là lý do tại sao chúng ta cần đặt phần tử bên trong mà chúng ta sẽ hiển thị các counts sau khi các phần tử được đếm trong mã nguồn HTML.

Bạn có thể không muốn hiển thị các counts bên dưới các phần tử nhưng ở một nơi khác trên trang. Trong trường hợp này, bạn cần định vị lại các counts bằng các thuộc tính CSS như translate, margin, hoặc position..

Tuy nhiên, đề xuất của tôi là sử dụng CSS Grid để bạn có thể tạo bố cục trang của bạn độc lập với thứ tự các phần tử của nó trong mã nguồn HTML. Ví dụ, bạn có thể dễ dàng tạo ra một lưới đặt các counts ở trên hoặc bên cạnh các trường đầu vào.