The task I have is to create a tri-state radio button/ switch and change the button to an image.
I have found the following example here. Which gives the following:
Although it’s useful, I specifically need to replace the button itself with an image. So, the button(image) moves when the user toggles it on/ neutral/ off. The look and feel I’m trying to create (where the purple box is an image):
Centred:
Right toggled:
Left toggled:
I’ve used example #1 mentioned here for inspiration, and I’ve tried manipulating the code as follows…
* {
box-sizing: border-box;
}
body {
background: -webkit-linear-gradient(90deg, #00c6ff 10%, #0072ff 90%); /* Chrome 10+, Saf5.1+ */
background: -moz-linear-gradient(90deg, #00c6ff 10%, #0072ff 90%); /* FF3.6+ */
background: -ms-linear-gradient(90deg, #00c6ff 10%, #0072ff 90%); /* IE10 */
background: -o-linear-gradient(90deg, #00c6ff 10%, #0072ff 90%); /* Opera 11.10+ */
background: linear-gradient(90deg, #00c6ff 10%, #0072ff 90%); /* W3C */
}
h1 {
color: white;
font-size: 2em;
text-align: center;
font-family: 'Indie Flower', cursive;
}
.container {
position: fixed;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
.radio-wrapper {
width: 145px;
height: 50px;
display: inline-block;
vertical-align: middle;
background: rgba(0, 0, 0, 0.4);
border-radius: 30px;
position: relative;
margin-left: 1%;
p {
position: absolute;
z-index: 10;
color: white;
font-size: 1.7em;
margin: 0;
margin-top: 13px;
}
.correct {
left: 17px;
top: -5px;
}
.wrong {
right: 17px;
top: -5px;
}
.neutral-icon {
left: 69px;
top: -8px;
opacity: .5;
}
label {
z-index: 9;
}
img {
z-index: 100;
}
}
input[type="radio"] {
display: none;
}
.ion-close-round {
z-index: 99;
font-size: 18px;
}
.neutral-icon i {
font-size: 10px;
}
.neutral + img {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
left: 33%;
transition: transform 1s;
}
.neutral:checked + img {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 100%;
position: absolute;
text-align: center;
}
.yes + label {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
left: 0;
text-align: center;
}
.yes:checked + label {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 50%;
background: rgb(32, 213, 50);
background: -moz-linear-gradient(top, rgba(32, 213, 50, 1) 0%, rgba(28, 195, 1, 1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(32, 213, 50, 1)), color-stop(100%, rgba(28, 195, 1, 1)));
background: -webkit-linear-gradient(top, rgba(32, 213, 50, 1) 0%, rgba(28, 195, 1, 1) 100%);
background: -o-linear-gradient(top, rgba(32, 213, 50, 1) 0%, rgba(28, 195, 1, 1) 100%);
background: -ms-linear-gradient(top, rgba(32, 213, 50, 1) 0%, rgba(28, 195, 1, 1) 100%);
background: linear-gradient(to bottom, rgba(32, 213, 50, 1) 0%, rgba(28, 195, 1, 1) 100%);
-moz-animation-duration: 0.4s;
-moz-animation-name: slidein;
-webkit-animation-duration: 0.4s;
-webkit-animation-name: slidein;
animation-duration: 0.4s;
animation-name: slidein;
-webkit-transform: translateZ(0);
}
.no + label {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
right: 0;
text-align: center;
}
.no:checked + label {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 50%;
background: red;
-moz-animation-duration: 0.4s;
-moz-animation-name: slideno;
-webkit-animation-duration: 0.4s;
-webkit-animation-name: slideno;
animation-duration: 0.4s;
animation-name: slideno;
-webkit-transform: translateZ(0);
background: rgb(230, 108, 103);
background: -moz-linear-gradient(top, rgba(230, 108, 103, 1) 0%, rgba(221, 79, 75, 1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 108, 103, 1)), color-stop(100%, rgba(221, 79, 75, 1)));
background: -webkit-linear-gradient(top, rgba(230, 108, 103, 1) 0%, rgba(221, 79, 75, 1) 100%);
background: -o-linear-gradient(top, rgba(230, 108, 103, 1) 0%, rgba(221, 79, 75, 1) 100%);
background: -ms-linear-gradient(top, rgba(230, 108, 103, 1) 0%, rgba(221, 79, 75, 1) 100%);
background: linear-gradient(to bottom, rgba(230, 108, 103, 1) 0%, rgba(221, 79, 75, 1) 100%);
}
@keyframes slidein {
from {
transform: translate(50px, 0);
}
to {
transform: translate(0px, 0px);
}
}
@keyframes slideno {
from {
transform: translate(-50px,0);
}
to {
transform: translate( 0px, 0px);
}
}
@keyframes returnLeft {
from {
transform: translate(-50px,0);
}
to {
transform: translate(0px,0);
}
}
@keyframes returnRight {
from {
transform: translate(50px,0);
}
to {
transform: translate(0px,0);
}
}
<h1>Tri-state Toggle Button</h1>
<div class="container">
<div class="radio-wrapper">
<p class="correct"><i class="ion-checkmark-round"></i>
</p>
<p class="neutral-icon"><i class="ion-record"></i>
</p>
<p class="wrong"><i class="ion-close-round"></i></p>
<input type="radio" name="event" class="yes" id="radio-yes" />
<label for="radio-yes"></label>
<input type="radio" name="event" class="neutral" checked id="radio-neutral" img src="[link to image here]"/>
<img for="radio-neutral"></img>
<input type="radio" name="event" class="no" id="radio-no" />
<label for="radio-no"></label>
</div>
</div>
However, for some reason the button appears behind the radio button wrapper, I also can’t select the central toggle and I can’t seem to fix that…
I get something looking like this:
2
Answers
I have found an alternative that does what I'm after.
It isn't the radio button solution, but it uses a slider and offers three toggle modes.
Code here:
In HTML: If you don’t need the label on the bar, you can just remove the value of ‘One’ ‘Two’ ‘Three’ or change it but not the id.
In CSS: You may just change the background into background:url("../img/youricon.png") center center no-repeat;
in the input#one:checked/ input#two:checked/ input#three:checked property.
I found the reference from here:
https://www.sliderrevolution.com/resources/styling-radio-buttons/
hope it could help!