Kawałek Kodu

Element SELECT był poruszany (fizycznie też) na tym blogu kilkukrotnie. Dziś przyszedł czas na jego kolejne wykorzystanie. W zależności od tego jakie oblicze ukaże, będziemy chcieli schować lub ukryć inny element. Jeśli SELECT będzie świecił pustką, to inny element schowa się również w pustce, jeśli wybierzemy jakąś opcję, to element wyskoczy zza krzaków z radością.

Jak sparować?

W hodowców psich ras nie będziemy się bawić. Oczywiście wykorzystamy podstawowe narzędzia, czyli HTML i CSS. W jednym z ostatnich wpisów wspominałem o selektorze dotyczącym wybranej opcji. A przecież właśnie o to chodzi - jeśli wybierzemy jakąś opcję, to chcemy pokazać inny element (np. inny SELECT).
Spróbujmy więc:

<select>
<option value="">---</option>
<option value="1">Opcja 1</option>
<option value="2">Opcja 2</option>
<option value="3">Opcja 3</option>
</select>

<div>
  Pokaż lub ukryj mnie!
</div>

+

div {
  display: none;
}

select option:checked + div {
  display: block;
}

I prawie jest ok. Prawie, bo nie działa. Oczywiście selektor wyboru zaznaczonej opcji jest jak najbardziej ok, ale przecież DIV nie jest bezpośrednim sąsiadem wybranej opcji. Nawet nie jest dalszym. Po prostu opcja jest poziom niżej niż DIV i jej rodzicem jest SELECT.

Chwila! Wiemy z JavaScript, że wartość wybranej opcji można pobrać bezpośrednio z SELECT. W ten sposób:
 

document.querySelector('select').addEventListener('change', function() {
  alert(this.value);
});

Skoro wartość mamy w SELECT, to czy da się to przenieść bezpośrednio do CSS? Spróbujmy:
 

div {
  display: none;
}

select:not([value=""]) + div {
  display: block;
}

Też nic. I prawidłowo, bo przecież w tym przypadku negacja dotyczy atrybutu SELECT, a ten nie ma atrybutu. W tym przypadku atrybut to co innego niż wartość elementu w JavaScript.

Hmm... A gdyby potraktować SELECT jako element formularza, czyli jego natywne przeznaczenie? Przecież elementy mogą mieć prawidłowy lub nieprawidłowy stan walidacji. Żeby nasza lista podlegała walidacji musimy nadać jej atrybut required. A kiedy będziemy wiedzieć czy ma prawidłową wartość (jest poprawnie zwalidowana)? Od tego mamy pseudoklasy :valid oraz :invalid.

Nasz kod po modyfikacji:

<select required>
<option value="">---</option>
<option value="1">Opcja 1</option>
<option value="2">Opcja 2</option>
<option value="3">Opcja 3</option>
</select>

<div>
  Pokaż lub ukryj mnie!
</div>

+

div {
  display: none;
}

select:valid + div {
  display: block;
}

lub prościej:

select:invalid + div {
  display: none;
}

I żeby się przekonać:

I chyba bardziej oczekiwany, a przynajmniej praktyczniejszy przykład. Zależne listy, a właściwie zależna widoczność list. Nie będziemy modyfikować ich zawartości - to już kwestia użycia JavaScript, a w tym wpisie nie zajmujemy się tym.

Potrzebujemy HTML:

<select required>
<option value="">---</option>
<option value="1">Opcja a1</option>
<option value="2">Opcja a2</option>
<option value="3">Opcja a3</option>
</select>

<select required>
<option value="">---</option>
<option value="1">Opcja b1</option>
<option value="2">Opcja b2</option>
<option value="3">Opcja b3</option>
</select>

<select required>
<option value="">---</option>
<option value="1">Opcja c1</option>
<option value="2">Opcja c2</option>
<option value="3">Opcja c3</option>
</select>

+ ukochany CSS:

select:invalid ~ select{
  display: none;
}

Powyższy selektor powoduje wyłączenie z pokazywania następnych list po liście, która nie jest wypełniona. Proste i działa:

Mam dla Ciebie propozycję. Przy kolejnym wpisie ja się pojawię. Dobrze by było, gdybyś Ty również! A jeśli Ty się pokażesz, to może za Tobą ktoś inny.

 

Przydatne linki:
Tylko dla wybrańców, czyli zaznaczone opcje elementu SELECT
Pseudoklasa :valid
Pseudoklasa :invalid