2

I am trying to use CSS to select some elements base on radio button state.

What I would like to do is if a certain radio button is checked I want to go down a couple levels and unhide an overlay so that the user can interact with the disabled radio buttons.

I know you can use sibling selectors like ~ and > to select siblings of the current div, but how would I select a parent element of a checked radio button and then traverse down the DOM to find my desired selector?

I can easily do this with JS but I would prefer CSS if it is possible.

Here is a CodePen

You can see that I have four radio buttons. Two of which are indented slightly.

What I would like to accomplish is if someone selects the Testing2 radio I want the .overlay that contains the opacity to be set to display: none.

I need to also maintain the same structure without reorganizing the HTML.

Using sibling selectors are relatively new to me so I am probably not using them correctly in this case.

I have tried:

 #radio-1:checked ~ .overlay {
      display: none;
    }

    #radio-1:checked > .radio-bump > .radio-group-2 ~ .overlay {
      display: none;
    }

Here is my code:

.overlay {
  background: #fff;
  z-index: 1;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  opacity: 0.7;
}
.radio-group-2 {
  position: relative;
}
.radio-bump {
  margin-left: 20px;
}
#radio-1:checked ~ .overlay {
  display: none;
}
#radio-1:checked > .radio-bump > .radio-group-2 ~ .overlay {
  display: none;
}
<div class="main-container">
  <div class="shipping-container">
    <div class="radio">
      <input type="radio" id="radio" name="radio-group-1">
      <label for="radio">Testing1</label>
    </div>
    <div class="radio-1">
      <input type="radio" id="radio-1" name="radio-group-1">
      <label for="radio-1">Testing2</label>
    </div>
    <div class="radio-bump">
      <div class="radio-group-2">
        <div class="overlay"></div>
        <div class="radios">
          <input type="radio" id="radio-2" name="radio-group-2">
          <label for="radio-2">Testing3</label>
        </div>
        <div class="radios">
          <input type="radio" id="radio-3" name="radio-group-2">
          <label for="radio-3">Testing4</label>
        </div>
      </div>
    </div>
  </div>
</div>
dippas
  • 49,171
  • 15
  • 93
  • 105
Yamaha32088
  • 3,656
  • 8
  • 36
  • 84

3 Answers3

4

This is only possible (with pure CSS) if you remove the containers from each radio/label. Also, you should consider using pointer-events instead of an overlay:

label:after { content: ""; display: block;}

.radio-group-2 {
  margin-left: 20px;
  opacity: .7;
  pointer-events: none;
}

input:checked + label + .radio-group-2 {
  opacity: 1;
  pointer-events: all;
}
<input type="radio" id="r-1" name="radio-group-1"><label for="r-1">Testing 1</label>
<input type="radio" id="r-2" name="radio-group-1"><label for="r-2">Testing 2</label>
<div class="radio-group-2">
  <input type="radio" id="r-3" name="radio-group-2"><label for="r-3">Testing 3</label>
  <input type="radio" id="r-4" name="radio-group-2"><label for="r-4">Testing 4</label>
</div>

Note the use of the adjacent sibling selector.

Noah
  • 1,139
  • 9
  • 21
  • Also consider `input:not(:checked) + label + .radio-group-2 { opacity: .7; pointer-events: none;}` – Oriol Jun 02 '16 at 21:18
  • This is the first time I have heard of `pointer-events`. We did not learn about them in my HTML5/CSS3 course. My research just now showed that they are involved in SVG. At the risk of sounding newb, how does that apply here? Thanks. – Eric Hepperle - CodeSlayer2010 Aug 24 '16 at 12:18
2

Given your condition

I need to also maintain the same structure without reorganizing the HTML.

Then the answer to your question, if this is possible to this with CSS only is NO, because CSS has no Parent selector, if you could reorganize your HTML, then CSS would be capable of achieving this, by using either the adjacent selector + or the sibling selector ~

You have more info on this question regards to parent selector in css

Community
  • 1
  • 1
dippas
  • 49,171
  • 15
  • 93
  • 105
0

Unfortunately, what you're asking for here cannot be achieved in pure CSS using your current HTML tree. #radio1 simply cannot be in the same selector as .radio-bump.

You will need to put the radio button element higher up the DOM tree in order to achieve this.

What you can do to make it look the way you want is to put the radio button higher in the tree, but keep the label where it is. Then make the radio button element display:none and add a :before or :after pseudo-element to the label styled to look like a radio button.

A similar technique is also used for creating pure CSS tabs.

Spudley
  • 157,081
  • 38
  • 222
  • 293