Apply color after clicking radio input

100 views Asked by At

I am editing an already created form where I extracted this code. I wished to replace the "radio buttons" with stars. I am having difficulty applying the color to the stars once clicked. I have done some testing but I am having difficulty on how to set the:

.uk-margin > label > div > input:checked, label {
    color: #ff0000;    
}

*{
    margin: 0;
    padding: 0;
}

.uk-margin {
    float: left;
    height: 46px;
    padding: 0 10px;
}

.uk-margin:not(:checked) > label > div > input {
    position:absolute;
    top:-9999px;
}

.uk-margin:not(:checked) > label {
    float:right;
    width:1em;
    overflow:hidden;
    white-space:nowrap;
    cursor:pointer;
    font-size:30px;
    color:#ccc;
}

.uk-margin:not(:checked) > label:before {
    content: '★ ';
}

.uk-margin > label > div > input:checked, label {
    color: #ff0000;    
}

.uk-margin:not(:checked) > label:hover,
.uk-margin:not(:checked) > label:hover ~ label {
    color: #deb217;  
}
.uk-margin > input:checked + label:hover,
.uk-margin > input:checked + label:hover ~ label,
.uk-margin > input:checked ~ label:hover,
.uk-margin > input:checked ~ label:hover ~ label,
.uk-margin > label:hover ~ input:checked ~ label {
    color: #c59b08;
}
<div data-id="page#18" class="rate2 uk-margin">
   <fieldset data-yooessentials-form-field="tempi" style="border-width: 0; margin: 0; padding: 0;">
      <div class="uk-form-controls">
         <div class="uk-margin uk-grid-small uk-child-width-auto uk-grid" uk-grid="">
            <label class="uk-flex uk-margin-right uk-first-column">
               <div>
                 <input id="star1" type="radio" name="tempi" class="uk-radio" value="1">
               </div>
               <div class="uk-margin-small-left">1</div>
            </label>
            <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star2" type="radio" name="tempi" class="uk-radio" value="2">
               </div>
               <div class="uk-margin-small-left">2</div>
            </label>
            <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star3" type="radio" name="tempi" class="uk-radio" value="3">
               </div>
               <div class="uk-margin-small-left">3</div>
            </label>
            <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star4" type="radio" name="tempi" class="uk-radio" value="4">
               </div>
               <div class="uk-margin-small-left">4</div>
            </label>
            <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star5" type="radio" name="tempi" class="uk-radio" value="5">
               </div>
               <div class="uk-margin-small-left">5</div>
            </label>
         </div>
      </div>
      <div class="uk-text-danger uk-text-small" data-yooessentials-form-field-errors=""></div>
   </fieldset>
</div>

3

There are 3 answers

2
A Haworth On BEST ANSWER

This snippet has removed the CSS which appears to have nothing to do with the problem in the question (e.g. those with .rate).

It starts again on the hover and checked states, using CSS :has to select when an input is checked or there is a hover.

* {
  margin: 0;
  padding: 0;
}

.uk-margin {
  height: 46px;
  padding: 0 10px;
  display: flex;
}

.uk-margin>label>div>input {
  position: absolute;
  rtop: -9999px;
  opacity: 0;
}

.uk-margin>label {
  width: 1em;
  white-space: nowrap;
  cursor: pointer;
  font-size: 30px;
  color: #ccc;
}

.uk-margin>label::before {
  content: '★ ';
}

.uk-margin>label:hover,
.uk-margin>label:hover~label {
  color: #deb217;
}

.uk-margin:hover>label::before {
  color: #deb217;
}

.uk-margin:hover>label:hover~label::before {
  color: #c59b08;
}

.uk-margin:has(:checked)>label::before {
  color: #ff0000;
}

.uk-margin:has(:checked)>label:has(:checked)~label::before {
  color: #c59b08;
}
<div data-id="page#18" class="rate2 uk-margin">
  <fieldset data-yooessentials-form-field="tempi" style="border-width: 0; margin: 0; padding: 0;">
    <div class="uk-form-controls">
      <div class="uk-margin uk-grid-small uk-child-width-auto uk-grid" uk-grid="">
        <label class="uk-flex uk-margin-right uk-first-column">
               <div>
                 <input id="star1" type="radio" name="tempi" class="uk-radio" value="1">
               </div>
               <div class="uk-margin-small-left">1</div>
            </label>
        <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star2" type="radio" name="tempi" class="uk-radio" value="2">
               </div>
               <div class="uk-margin-small-left">2</div>
            </label>
        <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star3" type="radio" name="tempi" class="uk-radio" value="3">
               </div>
               <div class="uk-margin-small-left">3</div>
            </label>
        <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star4" type="radio" name="tempi" class="uk-radio" value="4">
               </div>
               <div class="uk-margin-small-left">4</div>
            </label>
        <label class="uk-flex uk-margin-right">
               <div>
                 <input id="star5" type="radio" name="tempi" class="uk-radio" value="5">
               </div>
               <div class="uk-margin-small-left">5</div>
            </label>
      </div>
    </div>
    <div class="uk-text-danger uk-text-small" data-yooessentials-form-field-errors=""></div>
  </fieldset>
</div>

Note: flex is used to show the stars in order (without a need to change the existing HTML) rather than float.

2
Ted Whitehead On

If possible, I’d recommend updating the markup so the labels come after the inputs.

<input type="radio" name="star" id="star-5">
<label for="star-5">
  <span class="visually-hidden">5 stars</span>
</label>

This will allow you to use CSS selectors like input:checked ~ label. Here are some good resources:


Update: If you can’t change the markup you could try using the :has() selector (caniuse.com) to style labels that contain a checked input. Here’s an example https://www.smashingmagazine.com/2023/01/level-up-css-skills-has-selector/#linear-range-selection-based-on-state

2
Mehdi On

I don't think you can do this with css the way your HTML code is written, but you can easily with javascript. below the code, once you click on a star it adds the red color to the clicked star and the lower stars.

const inputLabel = document.querySelectorAll('.uk-flex input')

inputLabel.forEach((label,index)=>{
  label.addEventListener('click',(e)=>{
    target = e.target
    for(let i=0; i<inputLabel.length;i++){
      inputLabel[i].parentElement.parentElement.classList.remove('color-it')
    }
    for(let i=0; i<=index;i++){
      inputLabel[i].parentElement.parentElement.classList.add('color-it')
    }
  })
})
*{
  margin: 0;
  padding: 0;
}

.uk-margin {
  float: left;
  height: 46px;
  padding: 0 10px;
}

.uk-margin:not(:checked) > label > div > input {
  position:absolute;
  top:-9999px;
}

.uk-margin:not(:checked) > label {
  float:right;
  width:1em;
  overflow:hidden;
  white-space:nowrap;
  cursor:pointer;
  font-size:30px;
  color:#ccc;
}

.uk-margin:not(:checked) > label:before {
  content:'★';
}

/* .uk-margin:not(:checked) > label:hover,
.uk-margin:not(:checked) > label:hover ~ label {
  color: #deb217;  
} */


.uk-flex.uk-margin-right.color-it{
  color: red;
}
  <div id="wrapper">
    <div data-id="page#18" class="rate2 uk-margin">
      <fieldset data-yooessentials-form-field="tempi" style="border-width: 0; margin: 0; padding: 0;">
         <div class="uk-form-controls">
            <div class="uk-margin uk-grid-small uk-child-width-auto uk-grid" uk-grid="">
               <label class="uk-flex uk-margin-right uk-first-column">
                  <div>
                    <input id="star1" type="radio" name="tempi" class="uk-radio" value="1">
                  </div>
                  <div class="uk-margin-small-left">1</div>
               </label>
               <label class="uk-flex uk-margin-right">
                  <div>
                    <input id="star2" type="radio" name="tempi" class="uk-radio" value="2">
                  </div>
                  <div class="uk-margin-small-left">2</div>
               </label>
               <label class="uk-flex uk-margin-right">
                  <div>
                    <input id="star3" type="radio" name="tempi" class="uk-radio" value="3">
                  </div>
                  <div class="uk-margin-small-left">3</div>
               </label>
               <label class="uk-flex uk-margin-right">
                  <div>
                    <input id="star4" type="radio" name="tempi" class="uk-radio" value="4">
                  </div>
                  <div class="uk-margin-small-left">4</div>
               </label>
               <label class="uk-flex uk-margin-right">
                  <div>
                    <input id="star5" type="radio" name="tempi" class="uk-radio" value="5">
                  </div>
                  <div class="uk-margin-small-left">5</div>
               </label>
            </div>
         </div>
         <div class="uk-text-danger uk-text-small" data-yooessentials-form-field-errors=""></div>
      </fieldset>
   </div>