CSS selector for a checked radio button's label
Asked Answered
Z

6

267

Is it possible to apply a css(3) style to a label of a checked radio button?

I have the following markup:

<input type="radio" id="rad" name="radio"/>
<label for="rad">A Label</label>

What I was hoping is that

label:checked { font-weight: bold; }

would do something, but alas it does not (as I expected).

Is there a selector that can achieve this sort of functionality? You may surround with divs etc if that helps, but the best solution would be one that uses the label ''for'' attribute.

It should be noted that I am able to specify browsers for my application, so best of class css3 etc please.

Zoster answered 16/9, 2009 at 8:39 Comment(0)
Z
445

try the + symbol: It is Adjacent sibling combinator. It combines two sequences of simple selectors having the same parent and the second one must come IMMEDIATELY after the first.

As such:

input[type="radio"]:checked+label{ font-weight: bold; } 
 //a label that immediately follows an input of type radio that is checked 

works very nicely for the following markup:

<input id="rad1" type="radio" name="rad"/><label for="rad1">Radio 1</label>
<input id="rad2" type="radio" name="rad"/><label for="rad2">Radio 2</label>

... and it will work for any structure, with or without divs etc as long as the label follows the radio input.

Example:

input[type="radio"]:checked+label { font-weight: bold; }
<input id="rad1" type="radio" name="rad"/><label for="rad1">Radio 1</label>
<input id="rad2" type="radio" name="rad"/><label for="rad2">Radio 2</label>
Zoster answered 16/9, 2009 at 8:54 Comment(7)
Is there anyway to do this, but with the label being the prior element EG: <label for="rad1">Radio 1</label><input id="rad1" type="radio" name="rad">Jestude
You can use a tilda ~ to select siblings elements that aren't necessarily adjacent. css-tricks.com/child-and-sibling-selectorsScevo
Thanks, this just helped me to create "image radio buttons" with no JS.Neoimpressionism
It's worth noting that this won't work in IE 8, since the :checked selector is not supported.Gibert
@Martin Just in case you are wondering, This won't actually work in your case, since the label still needs to follow the input. The difference between '+' and '~' is whether the label is directly adjacent, or is generally adjecent: whether the label is the next element, or just one of the next elements.Seizure
Is there any way to style a radio button where there are no siblings, and the label either is an aunt or where you can style the parent which is a div?Timm
A while back I saw a way to cause the label to display in front of the input radio button, even though the input was specified before its label something to do with float left on the label, but I don't remember where or all of the details.Diseuse
F
159

I know this is an old question, but if you would like to have the <input> be a child of <label> instead of having them separate, here is a pure CSS way that you could accomplish it:

:checked + span { font-weight: bold; }

Then just wrap the text with a <span>:

<label>
   <input type="radio" name="test" />
   <span>Radio number one</span>
</label>

See it on JSFiddle.

Frere answered 20/6, 2013 at 6:27 Comment(7)
Excellent. This is very useful when dealing with the razor situation of <label>@Html.RadioButtonFor(..) someText<label>, I threw <span> around "someText" and it worked like a charm. Thank you!Noblewoman
Nice! Hadn't thought of this.Zedoary
Just what I needed! Thanks.Leandra
What if you want to style :active label with :checked? This is not really a solution.Torchier
@MaciejKrawczyk It's not a solution for you because your use case is completely different. If you want to style an :active label you can just do label:active { font-weight: bold; }. See: jsfiddle.net/Gbq8Z/608 (wow I can't believe that fiddle has been forked 608 times).Frere
how can ı do this if checked radio, change label style on your code ?Diploblastic
@MustafaUysal Can you please clarify your question. I am having trouble what exactly you are asking.Frere
S
34

I forget where I first saw it mentioned but you can actually embed your labels in a container elsewhere as long as you have the for= attribute set. So, let's check out a sample on SO:

* {
  padding: 0;
  margin: 0;
  background-color: #262626;
  color: white;
}

.radio-button {
  display: none;
}

#filter {
  display: flex;
  justify-content: center;
}

.filter-label {
  display: inline-block;
  border: 4px solid green;
  padding: 10px 20px;
  font-size: 1.4em;
  text-align: center;
  cursor: pointer;
}

main {
  clear: left;
}

.content {
  padding: 3% 10%;
  display: none;
}

h1 {
  font-size: 2em;
}

.date {
  padding: 5px 30px;
  font-style: italic;
}

.filter-label:hover {
  background-color: #505050;
}

#featured-radio:checked~#filter .featured,
#personal-radio:checked~#filter .personal,
#tech-radio:checked~#filter .tech {
  background-color: green;
}

#featured-radio:checked~main .featured {
  display: block;
}

#personal-radio:checked~main .personal {
  display: block;
}

#tech-radio:checked~main .tech {
  display: block;
}
<input type="radio" id="featured-radio" class="radio-button" name="content-filter" checked="checked">
<input type="radio" id="personal-radio" class="radio-button" name="content-filter" value="Personal">
<input type="radio" id="tech-radio" class="radio-button" name="content-filter" value="Tech">

<header id="filter">
  <label for="featured-radio" class="filter-label featured" id="feature-label">Featured</label>
  <label for="personal-radio" class="filter-label personal" id="personal-label">Personal</label>
  <label for="tech-radio" class="filter-label tech" id="tech-label">Tech</label>
</header>

<main>
  <article class="content featured tech">
    <header>
      <h1>Cool Stuff</h1>
      <h3 class="date">Today</h3>
    </header>

    <p>
      I'm showing cool stuff in this article!
    </p>
  </article>

  <article class="content personal">
    <header>
      <h1>Not As Cool</h1>
      <h3 class="date">Tuesday</h3>
    </header>

    <p>
      This stuff isn't nearly as cool for some reason :(;
    </p>
  </article>

  <article class="content tech">
    <header>
      <h1>Cool Tech Article</h1>
      <h3 class="date">Last Monday</h3>
    </header>

    <p>
      This article has awesome stuff all over it!
    </p>
  </article>

  <article class="content featured personal">
    <header>
      <h1>Cool Personal Article</h1>
      <h3 class="date">Two Fridays Ago</h3>
    </header>

    <p>
      This article talks about how I got a job at a cool startup because I rock!
    </p>
  </article>
</main>

Whew. That was a lot for a "sample" but I feel it really drives home the effect and point: we can certainly select a label for a checked input control without it being a sibling. The secret lies in keeping the input tags a child to only what they need to be (in this case - only the body element).

Since the label element doesn't actually utilize the :checked pseudo selector, it doesn't matter that the labels are stored in the header. It does have the added benefit that since the header is a sibling element we can use the ~ generic sibling selector to move from the input[type=radio]:checked DOM element to the header container and then use descendant/child selectors to access the labels themselves, allowing the ability to style them when their respective radio boxes/checkboxes are selected.

Not only can we style the labels, but also style other content that may be descendants of a sibling container relative to all of the inputs. And now for the moment you've all been waiting for, the JSFIDDLE! Go there, play with it, make it work for you, find out why it works, break it, do what you do!

Hopefully that all makes sense and fully answers the question and possibly any follow ups that may crop up.

Sporophore answered 31/3, 2017 at 4:21 Comment(4)
This is the answer to this question. Other ones while correct are essentially super basic. While this solves something more complicated and interesting, that one would be tempted to grab js for.Tugman
The accepted answer to this question has >30x as many upvotes despite imposing a limitation that this answer totally obviates. Unlike many similarly-hyped posts that purport mind-blowing info, this actually delivers on the claim. Amazing work, thanks so much.Schipperke
@Schipperke - this answer totally obviates the simple answer's limitation, because it explicitly defines the styles for each option. i.e. Mine constrains you to having a structure convention; this one constrains you to writing css for every radio button and result.Zoster
@Tugman simple != "super basic": this solution is more complicated, interesting and powerful - for this exact code; mine will work on all pages following 1 conventionZoster
S
10

If your input is a child element of the label and you have more than one labels, you can combine @Mike's trick with Flexbox + order.

enter image description here

label.switchLabel {
  display: flex;
  justify-content: space-between;
  width: 150px;
}
.switchLabel .left   { order: 1; }
.switchLabel .switch { order: 2; }
.switchLabel .right  { order: 3; }

/* sibling selector ~ */
.switchLabel .switch:not(:checked) ~ span.left { color: lightblue }
.switchLabel .switch:checked ~ span.right { color: lightblue }



/* style the switch */

:root {
  --radio-size: 14px;
}

.switchLabel input.switch  {
  width: var(--radio-size);
  height: var(--radio-size);
  border-radius: 50%;
  border: 1px solid #999999;
  box-sizing: border-box;
  outline: none;
  -webkit-appearance: inherit;
  -moz-appearance: inherit;
  appearance: inherit;
  
  box-shadow: calc(var(--radio-size) / 2) 0 0 0 gray, calc(var(--radio-size) / 4) 0 0 0 gray;
  margin: 0 calc(5px + var(--radio-size) / 2) 0 5px;
}

.switchLabel input.switch:checked {
  box-shadow: calc(-1 * var(--radio-size) / 2) 0 0 0 gray, calc(-1 * var(--radio-size) / 4) 0 0 0 gray;
  margin: 0 5px 0 calc(5px + var(--radio-size) / 2);
}
<label class="switchLabel">
  <input type="checkbox" class="switch" />
  <span class="left">Left</span>
  <span class="right">Right</span>
</label>
asd html
<label class="switchLabel">
  <input type="checkbox" class="switch"/>
  <span class="left">Left</span>
  <span class="right">Right</span>
</label>
css
label.switchLabel {
  display: flex;
  justify-content: space-between;
  width: 150px;
}
.switchLabel .left   { order: 1; }
.switchLabel .switch { order: 2; }
.switchLabel .right  { order: 3; }

/* sibling selector ~ */
.switchLabel .switch:not(:checked) ~ span.left { color: lightblue }
.switchLabel .switch:checked ~ span.right { color: lightblue }

See it on JSFiddle.

note: Sibling selector only works within the same parent. To work around this, you can make the input hidden at top-level using @Nathan Blair hack.

Stamm answered 24/5, 2018 at 10:3 Comment(0)
H
3

For my case, where is the radio input inside the label element like the following code:

<label>
    <input type="radio">
</label>

the proper css selector is:

label:has(input[type="radio"]:checked) {
    border: 1px solid #000;
}
Holcman answered 29/1 at 13:42 Comment(0)
P
-7

UPDATE:

This only worked for me because our existing generated html was wacky, generating labels along with radios and giving them both checked attribute.

Never mind, and big ups for Brilliand for bringing it up!

If your label is a sibling of a checkbox (which is usually the case), you can use the ~ sibling selector, and a label[for=your_checkbox_id] to address it... or give the label an id if you have multiple labels (like in this example where I use labels for buttons)


Came here looking for the same - but ended up finding my answer in the docs.

a label element with checked attribute can be selected like so:

label[checked] {
  ...
}

I know it's an old question, but maybe it helps someone out there :)

Pothead answered 17/3, 2014 at 18:57 Comment(2)
And how is the label supposed to become checked?Jointless
Hey, good catch. It doesn't. Apparently we have some pretty wacky code that generates labels along with radio buttons, and adds a "checked" attribute to both when generating the html. But it's not really valid... So this is totally unusable. I'll edit the answer, I have no clue why I got the upvotes for it. Thanks!Pothead

© 2022 - 2024 — McMap. All rights reserved.