Count HTML State Changes Real-Time with CSS

Counting is a entire task in web applications. How many unread emails do we have? How many tasks are left violent on your to-do list? How many donut flavors are bagged in a selling cart? All are essential questions users merit answers for.

So, this post will uncover we how to count bi-stated elements, that consecrate a infancy of user controls such as checkboxes and content inputs, using CSS counters.

You need to target those states with CSS first, that is probable by means of pseudo-classes and HTML attributes that concede us to do usually that. Go forward and examination with a thought and try a opposite pseudo-classes that can prove a change in a state of an element, dynamically.

We’ll start with a simplest, checkboxes.

1. Checkboxes

Checkboxes go into “checked” state when they’re ticked. The :checked pseudo-class indicates a checked state.

input type=checkbox checkbox #1br
input type=checkbox checkbox #2br
input type=checkbox checkbox #3br

brChecked: b id=tickedBoxCount/b
brUnchecked: 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);
}

Like we pronounced before, this box is really simple. We set dual counters during a base element and increment any for any checkbox for a dual states, respectively. The opposite values are afterwards displayed in a designated place regulating content property.

If we wish to know improved how CSS counters work, have a demeanour during our prior post.

Below, we can see a final result. When we check and uncheck a checkboxes, a values of a “Checked” and “Unchecked” counters are modified real-time.

Counting checkboxes real-timeCounting checkboxes real-time

2. Text inputs

We can also count how many content inputs have been filled and how many have been left empty by a user. This resolution won’t be as candid as a prior one, because, distinct checkboxes, text inputs don’t have pseudo-classes to dwindle when they’re filled.

So, we need to find an swap route. There’s a pseudo-class that indicates when an component has placeholder text; it’s called :placeholder-shown.

If we use placeholders in a content input, we can know when a submit margin is empty. This happens when a user has not nonetheless typed anything into it since a placeholder will disappear when that happens.

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);
}

The outcome is identical to a prior one—the dual counters are automatically incremented and decremented as we supplement or mislay content to or from a submit fields.

Counting content inputs real-timeCounting content inputs real-time

3. Details

Alternate states of an component don’t always have to be indicated usually by pseudo-classes. There competence be HTML attributes doing that job, like in a box of a details element.

The details component displays a essence of a summary child element. When a user clicks that, other essence of a details component become visible. Note that summary component always needs to come first among a children of details.

So, details has dual states: open and closed. The open state is indicated by a presence of a open HTML charge in a element. This charge can be targeted in CSS using a charge selector.

details
  summaryQ1: doubt #1/summary
  panswer #1/p
/details
details
  summaryQ2: doubt #2/summary
  panswer #2/p
/details
details
  summaryQ3: doubt #3/summary
  panswer #3/p
/details
br
br Open: b id=openDetailCount/b
br Closed: b id=closedDetailCount/b
::root{
  counter-reset: openDetailCount, closedDetailCount;
}
details{
  counter-increment: closedDetailCount;
}
details[open]{
  counter-increment: openDetailCount;
}
#closedDetailCount::before{
  content: counter(closedDetailCount);
}
#openDetailCount::before{
  content: counter(openDetailCount);
}

The outcome is two real-time CSS-counters again: Open and Closed.

Counting sum real-timeCounting sum real-time

4. Radio buttons

Counting radio buttons need a opposite technique. We could positively use a :checked pseudo-class we used for checkboxes. However, radio buttons are used differently than checkboxes.

Radio buttons are meant to be in groups. The user can name usually one inside a group. Each organisation acts as a singular unit. The dual states a radio symbol organisation can have is possibly one of a buttons is selected or none of them are selected.

Thus, we shouldn’t count radio buttons by particular buttons, though by symbol groups. To grasp that, we make use of a :nth-of-type selector. I’ll explain it later; let’s see a formula first.

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

We need to assign a same name to a radio buttons in a same group. Each organisation in a formula above has 3 radio buttons inside.

::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);
}

The initial 3 character manners in a above dash are a same as a ones we practical to checkboxes, except, instead of targeting every radio button, we aim a final radio symbol in any group, that is a third one in a box (:nth-of-type(3n)). So, we don’t count all a radio buttons though only one per group.

However, that won’t give us a scold real-time result, as we have not nonetheless given any sequence for counting a other dual radio buttons in a group. If one of them is checked it should be counted a violent outcome should diminution during a same time.

This is because we add a -1 value after unSelectedRadioCount in a final character sequence that targets a other dual radio buttons in a group. When one of them is checked, -1 will decrease a violent result.

Counting radio symbol real-timeCounting radio symbol real-time

The Placement of Counts

You can usually see a scold outcome after a counting has been finished, i.e. after all a elements that are to be counted have been processed. This is because we need to place a component inside that we’ll arrangement a counters only after a elements to be counted in a HTML source code.

You might not wish to uncover a counters subsequent a elements though somewhere else on a page. In this case, we need to reposition a counters regulating CSS properties such as translate, margin, or position.

But, my idea would be to use a CSS Grid so that we can emanate a blueprint of your page independent of a sequence of a elements in a HTML source code. For instance, we can simply emanate a grid that places a counters above or subsequent to a submit fields.

Add Comment