Sami Dahoux Bendou
Sami Dahoux Bendou

Reputation: 1

Select a specific HTML sibling according to a common CSS class

I have the following CSS-only form that should display either form A or form B according to the value of a radio input :

<div>
  <label for="a">A</label>
  <input class="trigger" type="radio" id="a" name="formSelector" value="a" />

  <div id="a" class="hidden-content">
    <!-- Form A -->
    A
  </div>

  <label for="b">B</label>
  <input class="trigger" type="radio" id="b" name="formSelector" value="b" />

  <div id="b" class="hidden-content">
    <!-- Form B -->
    B
  </div>
</div>

Here is the corresponding CSS code :

div {
  display: flex;
  flex-direction: row;
}


.hidden-content {
  display: none;
}

.trigger:checked + .hidden-content {
  display: block; /* Anything except none */
}

Of course, this works only if eachtrigger is an adjacent sibling of its hidden-content to be displayed.

I would like to know if it is possible to make it work, only with CSS, even if the trigger and the hidden-content are not adjacent.

I imagine something like below might exist :

<div>
  <label for="a">A</label>
  <input class="a-form trigger" type="radio" id="a" name="formSelector" value="a" />

  <label for="b">B</label>
  <input class="b-form trigger" type="radio" id="b" name="formSelector" value="b" />

  <div id="a" class="a-form hidden-content" style="order: 6">
    <!-- Form A -->
    A
  </div>

  <div id="b" class="b-form hidden-content" style="order: 6">
    <!-- Form B -->
    B
  </div>
</div>

With the following CSS :

.hidden-content {
  display: none;
}

$.trigger:checked ~ $.hidden-content {
  display: flex;
}

With $ being a class common to both siblings but without specifying it (form-a respectively form-b in the above example).

I prefer doing so cause I have a flex layout that should display the radio and labels in the first row and the content of the displayed form (A or B) in subsequent rows. I might be tackling this problem the wrong way, feel free to propose any alternative, Any solution to this problem is also welcomed by the way :)

#hidden-content-a, #hidden-content-b {
  display: none;
}

#trigger-a:checked ~ #hidden-content-a {
  display: block; /* Anything except none */
}

#trigger-b:checked ~ #hidden-content-b {
  display: block; /* Anything except none */
}

Upvotes: 0

Views: 42

Answers (1)

Yukul&#233;l&#233;
Yukul&#233;l&#233;

Reputation: 17052

you can use :has() pseudo-class in your selector:

.hidden-content{
  display: none;
}

:root:has(.trigger:checked) .hidden-content {
  display: block;
}
<div>
  <div>
    <div>
      <label><input type='checkbox' class='trigger'>show content</label>
    </div>
  </div>
</div>

<div>
  <div>
    <div class="hidden-content">Secret...</div>
  </div>
</div>

Upvotes: 0

Related Questions