Using the CSS :has selector for conditional questions
Someone asked if it was possible to show a question in a form I was making only if the answer to the previous question had been yes. I was beginning to reach for some straightforward JavaScript to spot a change in the first question and update the display of the second, when I thought to myself – could I do this now with CSS? It reminded me of the CSS-only multiple choice quiz I had written about before.
The HTML we have is something like:
<div class="questions">
<div id="r1">
<label for="q1">Do you want to see the second question?</label>
<select name="q1" id="q1">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
<div id="r2">
<label for="q2">Did you like the second question?</label>
<select name="q2" id="q2">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
</div>
I realised I could combine the :has selector, which lets you check a children selector, with :checked and [value=] in order to have CSS that hid a question by default, only showing it if the relevant previous answer was selected:
@supports(selector(:has(*))) {
#r2 {
display: none;
}
.questions:has(#q1 option[value="1"]:checked) #r2 {
display: block;
}
}
The whole block is wrapped in a @supports block, because otherwise the question would be entirely invisible to any browser that doesn't support :has.
For any supporting browser, we default to hiding the second question. Then, if the Yes answer is chosen to the first question, the contents of the :has selector now match – question 1’s option with value 1 is checked – and so the second question can now be shown.
Here is a live example: