Sven Cazier Sven Cazier - 2 months ago 18
CSS Question

CSS radiobutton slider background color

Hi I'm trying to style 3 radio buttons into a slider, everything works fine except for the background color that won't change.

I took this example to work with:
https://jsfiddle.net/tx93cpnm/



@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro);
* {
margin: 0px;
padding: 0px;
}
html {
background: #497dd0;
}
.wrapper {
margin: 100px 0;
}
.toggle_radio {
position: relative;
background: rgba(255, 255, 255, .1);
margin: 4px auto;
overflow: hidden;
padding: 0 !important;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
position: relative;
height: 26px;
width: 318px;
}
.toggle_radio > * {
float: left;
}
.toggle_radio input[type=radio] {
display: none;
/*position: fixed;*/
}
.toggle_radio label {
font: 90%/1.618"Source Sans Pro";
color: rgba(255, 255, 255, .9);
z-index: 0;
display: block;
width: 100px;
height: 20px;
margin: 3px 3px;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
cursor: pointer;
z-index: 1;
/*background: rgba(0,0,0,.1);*/
text-align: center;
/*margin: 0 2px;*/
/*background: blue;*/
/*make it blue*/
}
.toggle_option_slider {
/*display: none;*/
/*background: red;*/
width: 100px;
height: 20px;
position: absolute;
top: 3px;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
-webkit-transition: all .4s ease;
-moz-transition: all .4s ease;
-o-transition: all .4s ease;
-ms-transition: all .4s ease;
transition: all .4s ease;
}
#first_toggle:checked ~ .toggle_option_slider {
background: rgba(255, 255, 255, .3);
left: 3px;
}
#second_toggle:checked ~ .toggle_option_slider {
background: rgba(255, 255, 255, .3);
left: 109px;
}
#third_toggle:checked ~ .toggle_option_slider {
background: rgba(255, 255, 255, .3);
left: 215px;
}

<div class="wrapper">
<div class="toggle_radio">
<input type="radio" class="toggle_option" id="first_toggle" name="toggle_option">
<input type="radio" checked class="toggle_option" id="second_toggle" name="toggle_option">
<input type="radio" class="toggle_option" id="third_toggle" name="toggle_option">
<label for="first_toggle">
<p>First Button</p>
</label>
<label for="second_toggle">
<p>Second Button</p>
</label>
<label for="third_toggle">
<p>Third Button</p>
</label>
<div class="toggle_option_slider">
</div>
</div>





And turned it into this:
https://jsfiddle.net/9us6hs31/



@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro);
* {
margin: 0px;
padding: 0px;
}
html {} .wrapper {
margin: 100px 0;
}
.toggle_radio {
position: relative;
background-color: #ccc;
margin: 4px auto;
overflow: hidden;
padding: 0 !important;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
position: relative;
height: 20px;
width: 60px;
}
.toggle_radio > * {
float: left;
}
.toggle_radio input[type=radio] {
display: none;
/*position: fixed;*/
}
.toggle_radio label {
font: 90%/1.618"Source Sans Pro";
color: white;
z-index: 0;
display: block;
width: 14px;
height: 20px;
margin: 3px 3px;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
cursor: pointer;
z-index: 1;
/*background: rgba(0,0,0,.1);*/
text-align: center;
/*margin: 0 2px;*/
/*background: blue;*/
/*make it blue*/
}
.toggle_option_slider {
/*display: none;*/
/*background: red;*/
content: "";
background-color: white;
width: 14px;
height: 14px;
position: absolute;
top: 3px;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
-webkit-transition: all .4s ease;
-moz-transition: all .4s ease;
-o-transition: all .4s ease;
-ms-transition: all .4s ease;
transition: all .4s ease;
}
#first_toggle:checked ~ .toggle_option_slider {
background-color: #F32121;
left: 4px;
}
#second_toggle:checked ~ .toggle_option_slider {
background-color: white;
left: 23px;
}
#third_toggle:checked ~ .toggle_option_slider {
background-color: #21F321;
left: 42px;
}
#first_toggle:checked ~ .toggle_radio {
background: #F32121;
}
#second_toggle:checked ~ .toggle_radio {
background: #ccc;
}
#third_toggle:checked ~ .toggle_radio {
background: #21F321;
}

<div class="wrapper">
<div class="toggle_radio">
<input type="radio" class="toggle_option" id="first_toggle" name="toggle_option">
<input type="radio" checked class="toggle_option" id="second_toggle" name="toggle_option">
<input type="radio" class="toggle_option" id="third_toggle" name="toggle_option">
<label for="first_toggle"></label>
<label for="second_toggle"></label>
<label for="third_toggle"></label>
<div class="toggle_option_slider">
</div>
</div>





As you can see I can get the color of the slider to change, but not the color of the box.

I had this checkbox slider lying around:
https://jsfiddle.net/j1fw0rxv/



.switch {
position: relative;
display: inline-block;
width: 40px;
height: 20px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 4px;
bottom: 3px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(18px);
-ms-transform: translateX(18px);
transform: translateX(18px);
}
/* Rounded sliders */

.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}

<div class="checkbox">
<label class="switch">
<input type="checkbox" value="" id="acheck">
<div class="slider round"></div>
</label>
</div>





So I tried to fiddle around with that one...

Which gave me something like this:
https://jsfiddle.net/nd18fky6/



.switch {
position: relative;
display: inline-block;
width: 60px;
height: 20px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 23px;
bottom: 3px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
#first_toggle:checked + .slider {
background-color: #F32121;
}
#first_toggle:checked + .slider:before {
left: 4px;
}
#second_toggle:checked + .slider {
background-color: #ccc;
}
#second_toggle:checked + .slider:before {
left: 23px;
}
#third_toggle:checked + .slider {
background-color: #21F321;
}
#third_toggle:checked + .slider:before {
left: 42px;
}
/* Rounded sliders */

.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}

<div class="wrapper">
<div class="switch">
<label class="switch">
</label>
<label for="first_toggle">
<input type="radio" id="first_toggle">
<div class="slider round"></div>
</label>
<label for="second_toggle">
<input type="radio" checked id="second_toggle">
<div class="slider round"></div>
</label>
<label for="third_toggle">
<input type="radio" id="third_toggle">
<div class="slider round"></div>
</label>
</div>
</div>





So I fiddled some more and turned them into seperate sliders...
https://jsfiddle.net/txz9ceur/



.switch {
position: relative;
display: inline-block;
width: 60px;
height: 20px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 23px;
bottom: 3px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
#first_toggle:checked + .slider {
background-color: #F32121;
}
#first_toggle:checked + .slider:before {
left: 4px;
}
#second_toggle:checked + .slider {
background-color: #ccc;
}
#second_toggle:checked + .slider:before {
left: 23px;
}
#third_toggle:checked + .slider {
background-color: #21F321;
}
#third_toggle:checked + .slider:before {
left: 42px;
}
/* Rounded sliders */

.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}

<div class="wrapper">
<div class="switch">


<label class="switch" for="first_toggle">
<input type="radio" id="first_toggle">
<div class="slider round"></div>
</label>
<label class="switch" for="second_toggle">
<input type="radio" checked id="second_toggle">
<div class="slider round"></div>
</label>
<label class="switch" for="third_toggle">
<input type="radio" id="third_toggle">
<div class="slider round"></div>
</label>

</div>
</div>





Well, the colors change the way they should, but I need one slider.

What am I missing/overlooking (my guess would be because the box is the relationship between the box and the options, but I could be wrong...) to get one slider where the background in it's default starting position in the middle is grey, red when it slides to the left and green when it slides to the right?

Answer

I've played with a little but I think I have this down. The main issue was that you were trying to affect the background of the parent with CSS...and that's not possible (yet).

I've used positioning and z-index to layer in the slider 'track' and a pseudo-element as the 'button/thumb' and the labels on top.

Then applying suitable positioning to the pseudo-element via various selectors seem to do the trick.

@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro);
 * {
  margin: 0px;
  padding: 0px;
}
.wrapper {
  margin: 100px 0;
  text-align: center;
}
.toggle_radio {
  position: relative;
  background-color: pink;
  margin: 4px auto;
  overflow: hidden;
  padding: 0 !important;
  -webkit-border-radius: 50px;
  -moz-border-radius: 50px;
  border-radius: 50px;
  position: relative;
  height: 28px;
  display: inline-block;
}
.toggle_radio input[type=radio] {
  display: none;
}
.toggle_radio label {
  font: 90%/1.618"Source Sans Pro";
  color: white;
  z-index: 0;
  display: inline-block;
  width: 24px;
  height: 24px;
  margin: 2px;
  border-radius: 50%;
  cursor: pointer;
  z-index: 1;
  text-align: center;
  background: transparent;
  position: relative;
  z-index: 3;
}
.toggle_option_slider {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #ccc;
  z-index: 1;
  transition: background .35s ease;
}
.toggle_option_slider::after {
  content: '';
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: white;
  position: absolute;
  top: 2px;
  z-index: 2;
  transition: left .15s ease;
}
#first_toggle:checked ~ .toggle_option_slider {
  background: red;
}
#first_toggle:checked ~ .toggle_option_slider::after {
  left: 2px;
}
#second_toggle:checked ~ .toggle_option_slider {
  background: #ccc;
}
#second_toggle:checked ~ .toggle_option_slider::after {
  left: calc((100% - 24px)/2);
}
#third_toggle:checked ~ .toggle_option_slider {
  background: green;
}
#third_toggle:checked ~ .toggle_option_slider::after {
  left: calc((100% - 24px) - 2px);
}
<div class="wrapper">
  <div class="toggle_radio">
    <input type="radio" class="toggle_option" id="first_toggle" name="toggle_option">
    <input type="radio" checked class="toggle_option" id="second_toggle" name="toggle_option">
    <input type="radio" class="toggle_option" id="third_toggle" name="toggle_option">
    <label for="first_toggle"></label>
    <label for="second_toggle"></label>
    <label for="third_toggle"></label>
    <div class="toggle_option_slider">
    </div>
  </div>