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: