In the previous section, we used some properties without explaining them; they are counter-reset
and counter-increment
. Plus, we used a function-like command called
counter()
. In this section, we'll explain these properties by creating a mechanism to display the number of invalid fields. A counter is basically a variable we can name and whose value can be incremented using counter-increment
. Next, this counter can be displayed by using the
counter(variable name)
declaration within a
content
property.
Let's see a small example:
<ul> <li>element</li> <li>element</li> <li>element</li> </ul> <p></p> <style> ul{ counter-reset: elements; } li{ counter-increment: elements; } p:after{ content: counter(elements) ' elements'; } </style>
Trying this small bit of code results in a p
element containing the sentence 3 elements:
We can combine these powerful properties with the new form pseudo-selector to obtain a way to display valid and invalid fields.
Let's start by creating two counters, invalid
and fields
, and resetting them at each fieldset
element because we want to display the invalid fields for each fieldset
element. Then, we increment both counters when we find an invalid field and only the
fields
counter when we find a valid field.
fieldset{ counter-reset: invalid fields; } input:not([type=submit]):not([type=radio]):invalid, input[type=radio]:required:invalid{ counter-increment: invalid fields; border-left: 5px solid #ff4900; } input:not([type=submit]):not([type=radio]):valid, input[type=radio]:required{ counter-increment: fields; border-left: 5px solid #116300; }
The :not
pseudo-selector is pretty straightforward. It subtracts the elements matching the selector within the parentheses from the elements matching the leftmost selector. If this seems a bit confusing, let's try to read the last selector: match all the input
elements, whose type
value is not submit
and not radio
, that respond to the :valid
pseudo-selector.
Almost there! Now that we have the counters, let's display them using the
footer
element we have:
fieldset footer{ clear: both; position: relative; } fieldset:not([fake]) footer:after{ content: 'yay, section completed, move on!'; text-align: right; display: block; font-size: 13px; padding-top: 10px; } /* the value of the content property must be on one single line */ fieldset > input:invalid ~ footer:after{ content: counter(invalid) '/' counter(fields) " fields with problems; move the mouse over the fields with red marks to see details.\a Fields with * are required."; white-space: pre; }
The :not([fake])
selector is used like the media query shown earlier. We just want to ensure that only the browsers that support the :valid
and :invalid
pseudo-selectors can interpret this selector.
This last addition has some drawbacks, though; mixing presentation with content is generally something to avoid.