Zdarza się, że stworzyliśmy ekstra formularz ankiety i chcemy poinformować użytkownika korzystającego z niego o ilości zaznaczonych odpowiedzi czy też o ilości prawidłowych odpowiedzi. A to wszystko na bieżąco. Możemy to zrobić bez użycia JavaScript. Nie będzie trzeba dodawać obsługi zdarzeń, liczyć zaznaczonych, ustawiać w jakimś elemencie obliczonej wartości.
Wykorzystamy do tego CSS-owy licznik, a dokładnie zmienną, której wartością możemy sterować przy pomocy kombinacji HTML+CSS.
Zacznijmy od przykładu wykorzystania licznika do numerowania elementów listy. Co prawda można wykorzystać natywną numerację, ale ma on jednak mniejsze możliwości stylowania. Czyli na razie checkbox'y odkładamy na bok.
<ol>
<li>Wstęp.</li>
<li>Ubrania kiedyś i dziś.</li>
<li>Rodzaje kreszu.</li>
<li>Spódnice dla mężczyzn.</li>
<li>Kapelusz nie tylko na głowę.</li>
<li>Skórzane skarpety - czy warto?</li>
<li>Zakończenie.</li>
</ol>
+
ol {
list-style: none;
padding: 0;
counter-reset: licznik;
font-size: 14px;
}
li {
position: relative;
padding-left: 25px;
margin-bottom: 5px;
}
li:before {
content: counter(licznik);
position: absolute;
left: 0;
top: 50%;
width: 16px;
height: 16px;
line-height: 16px;
color: #fff;
font-size: 10px;
transform: translateY(-50%);
background: #f80;
border-radius: 50%;
text-align: center;
counter-increment: licznik;
}
ol li:nth-child(3n+2):before {
background-color: #f44;
}
ol li:nth-child(3n+3):before {
background-color: #08f;
}
To co nas tu mniej interesuje, to usunięcie numeracji listy oraz wykorzystanie pseudoelementu :before. To jemu przekazujemy wartość licznika, ale jednocześnie pozwala on na ustalenie innej wielkości czcionki oraz wielokolorowego wypunktowania listy.
A to co nas bardziej interesuje, to:
- counter-reset - ustalamy tu nazwa_licznika oraz zerujemy jego wartość. Wartość resetujemy w elemencie OL (może to być też inny nadrzędny element, np. BODY). Domyślnie resetujemy na 0, ale możemy podać wartość startową za nazwa_licznika,
- counter-increment - zwiększamy licznik o nazwie "licznik" o 1. Możem zwiększać lub zmniejszać o inną wartość, jeśli ją podamy za nazwa_licznika,
- counter(nazwa_licznika) - funkcja zwracająca wartość licznika. Zwróconą wartość umieszczamy w elemencie :before.
Efekt jest taki:
Wróćmy teraz do checkbox'ów.
Przykład będzie mniej praktyczny, ale w prosty sposób będziesz mógł go wykorzystać do własnych, praktycznych celów.
<form>
<fieldset>
<legend>Reprezentacja bitowa bajtu</legend>
<input type="checkbox" id="bit7" /><label for="bit7">7</label>
<input type="checkbox" id="bit6" /><label for="bit6">6</label>
<input type="checkbox" id="bit5" /><label for="bit5">5</label>
<input type="checkbox" id="bit4" /><label for="bit4">4</label>
<input type="checkbox" id="bit3" /><label for="bit3">3</label>
<input type="checkbox" id="bit2" /><label for="bit2">2</label>
<input type="checkbox" id="bit1" /><label for="bit1">1</label>
<input type="checkbox" id="bit0" /><label for="bit0">0</label>
</fieldset>
<output name="bity">Bitów włączonych</output>
</form>
+
form {
counter-reset: bity;
overflow: hidden;
}
form input[type="checkbox"] {
visibility: hidden;
position: absolute;
width: 0;
height: 0;
}
form label {
float: left;
border: 1px solid #000;
width: 20px;
height: 20px;
margin-right: -1px;
text-align: center;
line-height: 20px;
cursor: pointer;
}
form input[type="checkbox"]:checked {
counter-increment: bity;
}
form input[type="checkbox"]:checked+label {
background: #000;
color: #fff;
}
form output:after {
content: ' ' counter(bity);
}
W powyższym przykładzie użyliśmy inkrementacji licznika dla selektora :checked, dzięki czemu licznik zwiększa swoją zawartość dla klikniętego checkbox'a. Odznaczenie checkbox'a powoduje zmniejszenie licznika - jest przeliczany na nowo. Niżej znajdziesz powód, dla którego nie można umieścić licznika w elemencie LEGEND (co by ładniej wyglądało). Ten kod możesz wykorzystać właśnie do wspomnianego na początku wpisu zliczania zaznaczonych odpowiedzi / opcji / produktów.
Zmodyfikujmy nieco przykład korzystając z możliwości modyfikacji licznika o dowolną wartość, a nie tylko o 1. Otrzymamy prosty konwerter bin2dec:
<form>
<input type="checkbox" id="bit7" />
<input type="checkbox" id="bit6" />
<input type="checkbox" id="bit5" />
<input type="checkbox" id="bit4" />
<input type="checkbox" id="bit3" />
<input type="checkbox" id="bit2" />
<input type="checkbox" id="bit1" />
<input type="checkbox" id="bit0" />
<fieldset>
<legend>wartość decymalna</legend>
<label for="bit7">7</label>
<label for="bit6">6</label>
<label for="bit5">5</label>
<label for="bit4">4</label>
<label for="bit3">3</label>
<label for="bit2">2</label>
<label for="bit1">1</label>
<label for="bit0">0</label>
</fieldset>
</form>
+
form {
counter-reset: bity;
overflow: hidden;
}
form input[type="checkbox"] {
visibility: hidden;
position: absolute;
width: 0;
height: 0;
}
form label {
float: left;
border: 1px solid #000;
width: 20px;
height: 20px;
margin-right: -1px;
text-align: center;
line-height: 20px;
cursor: pointer;
}
form #bit0:checked {
counter-increment: 1;
}
form #bit0:checked ~ fieldset label[for="bit0"],
form #bit1:checked ~ fieldset label[for="bit1"],
form #bit2:checked ~ fieldset label[for="bit2"],
form #bit3:checked ~ fieldset label[for="bit3"],
form #bit4:checked ~ fieldset label[for="bit4"],
form #bit5:checked ~ fieldset label[for="bit5"],
form #bit6:checked ~ fieldset label[for="bit6"],
form #bit7:checked ~ fieldset label[for="bit7"] {
background: #000;
color: #fff;
}
form #bit0:checked {
counter-increment: bity 1;
}
form #bit1:checked {
counter-increment: bity 2;
}
form #bit2:checked {
counter-increment: bity 4;
}
form #bit3:checked {
counter-increment: bity 8;
}
form #bit4:checked {
counter-increment: bity 16;
}
form #bit5:checked {
counter-increment: bity 32;
}
form #bit6:checked {
counter-increment: bity 64;
}
form #bit7:checked {
counter-increment: bity 128;
}
form legend:after {
content: ': ' counter(bity) ;
}
Tu również zliczamy licznik dla :checked, ale dla każdego checkbox'a stworzyliśmy odrębną "funkcję" inkrementującą. Jako, że każdy checkbox reprezentuje bit na danej pozycji, to kiedy jest włączony to zwiększa licznik o 2^pozycja.
A gdzie ta obiecana ankieta?
Proszę bardzo:
<form>
<fieldset>
<legend>
Ile to jest 2+2?
</legend>
<label for="o1t">4<input type="radio" class="tak" id="o1t" name="odpowiedz[1]" /></label>
<label for="o1n">13<input type="radio" class="nie" id="o1n" name="odpowiedz[1]" /></label>
</fieldset>
<fieldset>
<legend>
Którą planetą od Słońca jest Ziemia?
</legend>
<label for="o2n1">2<input type="radio" class="nie" id="o2n1" name="odpowiedz[2]" /></label>
<label for="o2n2">5<input type="radio" class="nie" id="o2n2" name="odpowiedz[2]" /></label>
<label for="o2t">3<input type="radio" class="tak" id="o2t" name="odpowiedz[2]" /></label>
</fieldset>
<fieldset>
<legend>
Czy kawalekkodu.pl to fajny blog?
</legend>
<label for="o3t">tak<input type="radio" class="tak" id="o3t" name="odpowiedz[3]" /></label>
<label for="o3n">nie<input type="radio" class="nie" id="o3n" name="odpowiedz[3]" /></label>
</fieldset>
<output name="odpowiedzi">Odpowiedzi</output>
</form>
+
form {
counter-reset: prawidlowe bledne;
}
form input[type="radio"].tak:checked {
counter-increment: prawidlowe;
}
form input[type="radio"].nie:checked {
counter-increment: bledne;
}
form output:after {
content: ' prawidłowe: ' counter(prawidlowe) ' / błedne: ' counter(bledne);
}
Korzystamy tu z dwóch liczników. Jeden będzie nam zliczał odpowiedzi prawidłowe (zaznaczone radio z klasą tak), drugi nieprawidłowe (zaznaczone radio z klasą nie). Oczywiście nie jest to przykład cwanoodporny, bo można zajrzeć w źródło kodu i sprawdzić, która odpowiedź jest prawidłowa.
Wskazówki:
- licznik może być resetowany w elemencie na tym samym poziomie lub wyżej w drzewie DOM, ale zawsze przed inkrementacją i użyciem,
- reset i inkrementacja nie działają na elementach z ustawionym stylem display:none,
- funkcji counter() i counters() nie można użyć w elemencie wcześniejszym lub wyżej w drzewie DOM przed inkrementacją,
- wartość licznika można umieścić tylko w pseudoelemencie :before i :after, a co za tym idzie nie jest ona widziana przez wszystkie screenreader'y.
Trzymam kciuki, aby powyższe przykłady natchnęły Cię do korzystania z liczników we własnych projektach. Bo na kogo można liczyć, jak nie na CSS-owy licznik!
Przydatne linki:
Dokumentacja counter-reset
Dokumentacja counter-increment
Przykłady używania licznika