Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS for checked radio button with multiple labels

Tags:

html

css

I'm having css issues with a second label on a radio button, when this radio button is checked. I already found out that a second (and a third) label is possible using 'for' in the label-tag. It's not possible to group everything in a single label-tag.

How can I change the background for the second label when a radio button is checked?

My (simplified) code is below, for the first label it works, second label it doesn't.

.radioclass:checked + label {
  background-color: cyan;
}
<div class="row">
  <div class="col-sm-4">
    <input class="radioclass" id="id_radiobtn1" type="radio" name="radiobtn1" value="1">
    <label for="id_radiobtn1">first label</label>
  </div>
  <div class="col-sm-4">
    <label for="id_radiobtn1">second label</label>
  </div>
</div>
like image 980
Mark van Herpen Avatar asked Feb 14 '26 19:02

Mark van Herpen


2 Answers

The + selector in css means "immediate sibling", i.e. the very next element after the input must be a label. This will only select the immediate sibling.

An alternative is ~ which means "any sibling" and targets any label after the input.

In both of these cases, the elements (input and label) are on the same dom level. There is no way to traverse up the dom, grab the sibling and then the label - which is what you are trying to do with the html supplied.

If you are able to change the html, then either place the input outside the two divs or place both labels inside the same div (after the input).

.radioclass:checked ~ div label {
  background-color: cyan;
}
<div class="row">
  <input class="radioclass" id="id_radiobtn1" type="radio" name="radiobtn1" value="1">
  <div class="col-sm-4">
    <label for="id_radiobtn1">first label</label>
  </div>
  <div class="col-sm-4">
    <label for="id_radiobtn1">second label</label>
  </div>
</div>

.radioclass:checked ~ label {
  background-color: cyan;
}
<div class="row">
  <div class="col-sm-4">
    <input class="radioclass" id="id_radiobtn1" type="radio" name="radiobtn1" value="1">
    <label for="id_radiobtn1">first label</label>
    <label for="id_radiobtn1">second label</label>
  </div>
</div>

If you cannot alter the html, then JS is the only other approach (I've changed the input to a checkbox for demonstration purposes):

$('input').on('change', function(){
  var func = 'removeClass';
  if($(this).is(':checked')) {
    func = 'addClass';
  }
  
  $('label[for="'+$(this).attr('id')+'"]')[func]('checked');
});
label.checked {
  background-color: cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="row">
  <div class="col-sm-4">
    <input class="radioclass" id="id_radiobtn1" type="checkbox" name="radiobtn1" value="1">
    <label for="id_radiobtn1">first label</label>
  </div>
  <div class="col-sm-4">
    <label for="id_radiobtn1">second label</label>
  </div>
</div>
like image 186
Richard Parnaby-King Avatar answered Feb 17 '26 11:02

Richard Parnaby-King


Using just CSS this is possible, although it does require a rearrangement of your HTML, effectively moving the radio <input> ahead of the elements in which the <label> elements are contained; this removes the (impossible in CSS) requirement of traversing to the parent of the <input> in order to style the non-sibling <label> elements.

/* selects the element with the id of 'id_radiobtn1' when it is
   checked, uses the general sibling combinator (~) to select
   all sibling <div> elements with the class of 'col-sm-4'
   and then finds the descendant <label> elements within
   that/those <div> elements whose 'for' attribute-value is
   equal to 'id_radiobtn1': */
#id_radiobtn1:checked ~ div.col-sm-4 label[for=id_radiobtn1] {
  background-color: cyan;
}
<div class="row">
  <input class="radioclass" id="id_radiobtn1" type="radio" name="radiobtn1" value="1" />
  <div class="col-sm-4">
    <label for="id_radiobtn1">first label</label>
  </div>
  <div class="col-sm-4">
    <label for="id_radiobtn1">second label</label>
  </div>
</div>

Now, if you must have a visible radio <input> besides the first of the <label> elements, you can use a pseudo-element to effectively pretend, while also hiding the real radio <input>:

*,
 ::before,
 ::after {
 /* to include border and padding in the calculated
    dimensions (width/height) of the elements: */
  box-sizing: border-box;
}

.row>input[type=radio] {
  /* hiding the radio <input> elements: */
  display: none;
}

/* selecting the <input> elements whose type is
   equal to 'radio', which is checked and then
   finding all (subsequent) sibling elements
   (using the '~' combinator) which <div>
   elements with a class of 'col-sm-4', and
   traversing to the <label> elements within: */
input[type=radio]:checked~div.col-sm-4 label {
  background-color: cyan;
}

label {
  /* in order to ensure that the descendant
     pseudo-elements are positioned relative
     to their parent element: */
  position: relative;
  /* making room for the pseudo-elements: */
  margin-left: 2em;
}

input[type=radio]+.col-sm-4 label::before {
  /* the content property is required, even
     if only an empty string, to have the
     pseudo-element show up: */
  content: '';
  display: inline-block;
  /* positioning absolutely, in relation to
     the closest ancestor with a non 'static'
     position, in this case the parent
     <label> element: */
  position: absolute;
  /* moving it outside of the <label> element's
     left border, to avoid the background-color: */
  left: -2em;
  /* purely aesthetic: */
  width: 0.8em;
  height: 0.8em;
  /* arbitrary positioning, adjust to taste: */
  top: 50%;
  transform: translateY(-40%);
  /* making the pseudo-element circular in shape: */
  border-radius: 50%;
  /* colouring the faux 'border': */
  box-shadow: 0 0 0 2px #ccc;
}

/* adjusting the colours of the faux radio: */
input[type=radio]:checked+.col-sm-4 label::before {
  box-shadow: 0 0 0 2px #000, inset 0 0 0 3px #fff;
  background-color: limegreen;
}
<div class="row">
  <input class="radioclass" id="id_radiobtn1" type="radio" name="group1" value="1" />
  <div class="col-sm-4">
    <label for="id_radiobtn1">row one first label</label>
  </div>
  <div class="col-sm-4">
    <label for="id_radiobtn1">row one second label</label>
  </div>
</div>
<div class="row">
  <input class="radioclass" id="id_radiobtn2" type="radio" name="group1" value="2" />
  <div class="col-sm-4">
    <label for="id_radiobtn2">row two first label</label>
  </div>
  <div class="col-sm-4">
    <label for="id_radiobtn2">row two second label</label>
  </div>
</div>
like image 26
David Thomas Avatar answered Feb 17 '26 11:02

David Thomas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!