Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

CSS CSS Foundations Advanced Selectors UI Element States Pseudo-Classes

Alex Tasioulis
Alex Tasioulis
4,950 Points

checked radio buttons css

so input[type="radio"]:checked + label selects my checked radio button's label. How do I select all but the checked one?

I'm wondering if I can do

input[type="radio"]:not(:checked + label)

I have 3 labels, they're all initially black. What I want is that when a user clicks on a button, all the other labels turn to a very light grey (but the one they picked stays black).

5 Answers

I might be wrong, but as far as I know, there's no nice way to accomplish this in CSS.

What you can do instead is add a class to all the radio buttons once one of them has been checked, and write a selector for that class + label so that its normal state (unchecked) is grey, and the checked state is black.

You can easily do this with jQuery. I made an ugly little CodePen which accomplishes this: http://codepen.io/dpskvn/pen/EFctG/

Alex Tasioulis
Alex Tasioulis
4,950 Points

Thank you, Dino (and thanks for taking the time to write the pen). Yes, yes, it's very easy with jQuery, I'm just trying to understand these finer details of CSS - and what their limitations or uses are. I'm used to never using things like that in my CSS, so I'm just trying to figure out how they could help me or how I could incorporate them in my workflow.

I understand what you were trying to accomplish, and I probably should have offered an additional explanation.

While you really can do something like this:

input[type="radio"]:not(:checked) + label {
    color: #888;
}

input[type="radio"]:checked + label {
    color: #000;
}

it would be no different from:

input[type="radio"] + label {
    color: #888;
}

input[type="radio"]:checked + label {
    color: #000;
}

The :not(:checked) pseudo-class selector makes no difference between radios that haven't been checked before a user action (user clicking on one radio button) and the unchecked radios after a user has clicked one.

While CSS can be pushed, there are limits to what you can do. I'm afraid this is one of them. Even the general sibling combinator wouldn't work here:

input[type="radio"]:checked ~ input[type="radio"] + label {
    color: #888;
}

because it would only select the radio labels after the one that was selected. So basically, it would only work as planned if the user selected the first radio button.

It's fun to think about, though. If there was a combinator which would get all the siblings of an element, even the ones that come before it, then this could be done. Or, if there was a parent selector, allowing you to get the parent element of the checked radio, then it could also be done with CSS alone.

I haven't been following the CSS Selectors Level 4 draft recently, but I've heard mentions of parent selectors in there. Ah, I found it after a quick glance. With the current proposal, !E > F would select the E element which is the parent of a F element.

Until browsers implement support for such theoretical selectors, we're stuck with doing some JavaScript. :)

I think Dino is right with the all siblings selector.

Alex,

One thing that might help you is to realize that you can't detect state changes with css. A radio button is either checked, or it's not checked. It's in a certain state. There's no such thing as "the radio button was just checked", at least in css. You can't detect a change from one state to another.

Same idea with form elements. A form element either has focus or it doesn't. Can't detect that it "just received focus" or "just lost it".

For future reference,

There might be a way to do this with the :indeterminate psuedo-class

http://dev.w3.org/csswg/selectors4/#indeterminate

Bhanu Awasthi
Bhanu Awasthi
1,780 Points

Thank You for the solution Dino and thank you for the question Alex !

Alex Tasioulis
Alex Tasioulis
4,950 Points

Thanks for your replies. I think I didn't explain this very well because it seems like you thought I wanted to do something else. What I wanted to do was actually very simple and easy and inferrable from the lesson, I don't know why I got so confused myself - it was late, and I've been working 14 hours a day past few weeks, I'm burning out a little and forgetting what I already know :P

Here's what I wanted to do.

http://codepen.io/alextas/details/xnzgp/

EDIT: (I guess I did say they're all initially black... yeah, my apologies, what I said initially was completely misleading)

Jason: One thing that might help you is to realize that you can't detect state changes with css. A radio button is either checked, or it's not checked. It's in a certain state. There's no such thing as "the radio button was just checked", at least in css. You can't detect a change from one state to another.

Same idea with form elements. A form element either has focus or it doesn't. Can't detect that it "just received focus" or "just lost it".

Thanks for the input; I'm not sure what you're trying to tell me though. I don't think I understand the difference between "has focus" and "just received focus." If you click on it right now it "just got focus" anyways and css will detect it because it's in a checked state. I think I must be misunderstanding you!

EDIT: (and now that I think about it, I think I know what you meant)

OK Sorry for all the confusion!

Hi Alex,

Changing the requirements to what you show in the pen does change the problem considerably. It went from a probably impossible css solution to a simple css solution. All it took was one selector and one property/value pair. The initial requirement of them all starting off black made it difficult.

The concept of state changes might make more sense to you if you think about what the jQuery solution would have been based on the original problem.

In jQuery we would have written an event handler for when a radio button was clicked. Inside the event handler we would have code that would change the colors of the two other radio buttons. To lightgray or white, whatever you were using.

In an event based system, you have events, and an event marks the moment when something changes from one state to another. An event handler let's us execute code in response to an event having just taken place. the moment you click on the radio button an event fires off and you're able to do something the moment that event takes place.

We do not have the equivalent of this in css. You can't detect the moment a state change takes place. It's in one state or the other. You can't do anything with the in between part.

Of course, with the new requirements, this limitation of css is no longer a problem for you.

I hope that makes more sense to you.

Alex Tasioulis
Alex Tasioulis
4,950 Points

Hi Jason, Thank you for the detailed response and explanation :D I got it now, and I also got the point you were trying to make in your initial posts. Thanks!