0

I'm working on a challenge and would like to know how I can style a radio input element such that:

  • the actual radio feature itself is not present,
  • the element will be such that when selected, its background-color changes to a color of my choosing,
  • the element can't be deselected after being selected (just like a proper radio button).

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.

Angel Umeh
  • 47
  • 12
  • 1
    I have put up an answer which I think clears up the input type radio situation, but I now realise that I am not absolutely sure what you want to happen with the input of type text as you have given it a different name. Do you want when that is clicked any other button loses its color and this input - although of a different shape as you have it - gets that background color? And do you want to ensure the user only enters up to two digits? – A Haworth Sep 01 '22 at 17:02
  • Oh, I can handle the text input element, I just copied straight out of my code without looking. On further thought yes, actually. I realize you've basically summarized what I was to do. Is it ok to edit my question to reflect the correction? – Angel Umeh Sep 01 '22 at 20:33
  • Here's the design guide for the active states: [image](https://github.com/akcumeh/09-tip-calculator-app/blob/main/design/active-states.jpg) – Angel Umeh Sep 01 '22 at 20:39

3 Answers3

1

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.

A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • This works, it's pretty much what I'm looking for. However in the ModernCSS article I referenced in my question the author enclosed the input in its label, making the connection implicit and removing the need for a for-id connection, I am interested in that style as it makes code shorter... So I want to know if that can be used in this code. – Angel Umeh Sep 01 '22 at 19:45
  • 1
    I believe you would need JavaScript if you wanted to keep that label as parent structure as there is currently no way of a child selecting a parent if you see what I mean. This is firmly stated in https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors See for example https://stackoverflow.com/questions/45338238/how-to-style-the-parent-label-of-a-checked-radio-input if you are interested in a JS solution but to my mind that makes it all more messy. – A Haworth Sep 01 '22 at 20:42
1

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.

1

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>
ZH Rifat
  • 69
  • 6
  • I didn't ask about a radio button that is deselectable, sorry. I would've gone for a checkbox in that case. [This answer](https://stackoverflow.com/a/73573084/17497724) pretty much gets me what I need. Thank you – Angel Umeh Sep 01 '22 at 19:51