Reputation: 57
I'm working on a challenge and would like to know how I can style a radio input element such that:
background-color
changes to a color of my choosing,I have searched and found this ModernCSS article which didn't provide what I was looking for. I applied what I understood from the article like so:
<label role="radio" class="radio">
<input type="radio" name="radio">
5%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
10%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
15%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
25%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
50%
</label>
<label role="textbox">
<input type="text" name="amount" value="40%">
</label>
input[type="radio"] {
display: grid;
place-content: center;
appearance: none;
margin: 10% 0 0;
width: 2rem;
height: 1rem;
align-items: center;
background-color: #fff;
}
input[type="radio"]:checked {
background-color: hsl(172, 67%, 45%);
}
.radio {
grid-template-columns: 1rem auto;
gap: 0.5rem;
background-color: hsl(183, 100%, 15%);
}
As with many other articles I tried, such as this article from Bryntum and this from W3Schools, they show you how to style the radio itself which I don't need, since I'm trying to get rid of it altogether.
Upvotes: 0
Views: 9115
Reputation: 4867
The original request can be achieved using the new-ish has()
selector. This currently works great in Chrome, but unclear on Firefox...
According to MDN the version of FF released 3 days ago has support... but my older v115.5 (ESR) also has at least partial support. However it seems FF, at least my older version, doesn't do dynamic queries on has()
because this example only works there after the browser reloads the document (and keeps the previous selection).
Here's a CodePen version of the same code... in my FF if I click on one of the labels, then make a change in the code (just add a space or something to force a re-run), the page refreshes with the correct label highlighted.
Anyway, with that big caveat, here 'tis. The key point is just the label:has(input[type=radio]:checked)
bit.
EDIT: Instead of hiding the radio button entirely, make it transparent. Benefits:
required
attribute is preserved (perhaps more important for checkboxes).I updated the example to reflect this.
label {
padding: 4px;
}
/* Target labels that have a radio input as child. */
label:has(input[type=radio]) {
display: grid;
flex-direction: row;
align-items: center;
background: red;
}
/* Change label background when the child element is checked. */
label:has(input[type=radio]:checked) {
background: green;
}
/* Apply focus outline when the child element has focus. */
label:has(input[type=radio]:focus-visible) {
outline: 1ps solid blue;
}
/* Hide the actual radio input and place it on top of the label. */
input[type=radio] {
position:absolute;
opacity: 0;
}
<label role="radio" class="radio">
<input type="radio" name="radio">
5%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
10%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
15%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
25%
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
50%
</label>
<label role="textbox">
<input type="text" name="amount" value="40%">
</label>
Upvotes: 2
Reputation: 69
you cannot make a radio button deselectable by using only one radio-group. I used multiple radio-group to make a radio button deselectable once selected. try this:
input[type="radio"] {
appearance: none;
width:100%;
height:100%;
position:absolute;
z-index:999;
}
label{
width:100%;
min-height:100%;
display:flex;
align-items:center;
justify-content:center;
}
input[type="radio"]:checked + label {
background-color: hsl(172, 67%, 45%);
}
div {
height:200px;
}
<div>
<input type="radio" name="radio1"/>
<label role="radio1" class="radio">5%</label>
</div>
<div>
<input type="radio" name="radio2">
<label role="radio2" class="radio">10%</label>
</div>
<div>
<input type="radio" name="radio3">
<label role="radio3" class="radio">15%</label>
</div>
<div>
<input type="radio" name="radio4">
<label role="radio4" class="radio">20%</label>
</div>
<div>
<input type="radio" name="radio5">
<label role="radio5" class="radio">25%</label>
</div>
<div>
<input type="radio" name="radio6">
<label role="radio6" class="radio">50%</label>
</div>
Upvotes: 1
Reputation: 71
label{
position: relative;
}
input[type=radio]{
position:absolute;
visibility:hidden;
}
input[type=radio]:checked + div{
background: green;
}
<label role="radio" class="radio">
<input type="radio" name="radio">
<div>5%</div>
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
<div>10%</div>
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
<div>15%</div>
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
<div>20%</div>
</label>
<label role="radio" class="radio">
<input type="radio" name="radio">
<div>50%</div>
</label>
<label role="textbox">
<input type="text" name="amount" value="40%">
</label>
you can go ahead and clean it more and structure it the way you want this is how i do it or using javascript.
Upvotes: 1
Reputation: 36656
I guess you don't actually want the radio buttons to be absent, but you want them not to be seen as you'll still want their clickable qualities.
You can achieve this by setting their opacity to 0.
What you also need is the label element to be influenced by whether its associated input is checked or not. This snippet alters the order so the label comes immediately after the input and the new color (when the radio button is checked) is put onto the label, not onto the radio button.
Note also the use of the 'for' attribute which says that label is associated with that input (via id).
This snippet groups each input/label pair in a div with class choice and groups the lot into a div with class choices to make formatting easier.
.choices {
display: flex;
gap: 10px;
}
input[type="radio"] {
opacity: 0;
width: 2rem;
height: 1em;
background-color: #fff;
position: absolute;
}
input[type="radio"]:checked+label {
background-color: hsl(172, 67%, 45%);
}
.radio {
background-color: hsl(183, 100%, 15%);
color: white;
}
<div class="choices">
<div class="choice">
<input type="radio" name="radio" id="five">
<label role="radio" class="radio" for="five">
5%
</label>
</div>
<div class="choice">
<input type="radio" name="radio" id="ten">
<label role="radio" class="radio" for="ten">
10%
</label>
</div>
<div class="choice">
<input type="radio" name="radio" id="fifteen">
<label role="radio" class="radio" for="fifteen">
15%
</label>
</div>
<div class="choice">
<input type="radio" name="radio" id="twentyfive">
<label role="radio" class="radio" for="twentyfive">
25%
</label>
</div>
<div class="choice">
<input type="radio" name="radio" id="fifty">
<label role="radio" class="radio" for="fifty">
50%
</label>
</div>
<div class="choice">
<input type="text" name="amount" value="40%" id="text">
<label role="textbox" for="text">
</label>
</div>
</div>
Obviously you will want to set the formatting as you want it, and I am not clear what you want to happen with the input of type text as you've given it a different name. I'll put up a comment in order to get clarification.
Upvotes: 1