0

I am trying to build a radio survey question with 5 square radio buttons, but I am having trouble getting it to change color while the radio is checked or focused

I am also using Vue so it is recommended to put the input inside the label https://codepen.io/phongoli0/pen/qBbXmoe?editors=1100

.squareRadios {
  margin: 10px;
}

.squareRadios input[type="radio"] {
  opacity: 0;
  position: fixed;
  width: 0;
}

.squareRadios label {
  display: inline-block;
  background-color: #ddd;
  padding: 10px 20px;
  font-family: sans-serif, Arial;
  font-size: 16px;
  border: 2px solid #444;
  border-radius: 4px;
}

.squareRadios label:hover {
  background-color: red;
}

.squareRadios input[type="radio"]:focus+label {
  border: 2px dashed green;
}

.squareRadios input[type="radio"]:checked+label {
  background-color: blue;
  border-color: #4c4;
}
<div class="squareRadios">
  <label>
        0
        <input type="radio" value="0" /></label>
  <label>
        1
        <input type="radio" value="1" /></label>
  <label>
        2
        <input type="radio" value="2" /></label>
  <label>
        3
        <input type="radio" value="3" /></label>
  <label>
        4
        <input type="radio" value="4" /></label>
  <label>
        5
        <input type="radio" value="5" /></label>
</div>
Alessio
  • 3,404
  • 19
  • 35
  • 48
yaackti
  • 5
  • 3

4 Answers4

2

This is because you have the <input type="radio"> inside your <label>, not next to it and the :focus property has to be on the <label> not on the <input type="radio"> radio which is hidden.

The dashed green border on :focus disappears after clicking on the label because the input will hold the :focus after clicking on it.

Here a working live Codepen (case: input and label are siblings)

.squareRadios {
  margin: 10px;
}

.squareRadios input[type="radio"] {
  opacity: 0;
  position: fixed;
  width: 0;
}

.squareRadios label {
  display: inline-block;
  background-color: #ddd;
  padding: 10px 20px;
  font-family: sans-serif, Arial;
  font-size: 16px;
  border: 2px solid #444;
  border-radius: 4px;
}

.squareRadios label:hover {
  background-color: red;
}

.squareRadios input[type="radio"]:checked + label {
  background-color: blue;
  border-color: #4c4;
}

.squareRadios label:focus {
  border: 2px dashed green;
  outline: none;
}
<div class="squareRadios">
  <input id="radio0" type="radio" value="0" name="squareradios" />
  <label tabindex="1" for="radio0">
    0
  </label>

  <input id="radio1" type="radio" value="1" name="squareradios" />
  <label tabindex="1" for="radio1">
    1
  </label>

  <input id="radio2" type="radio" value="2" name="squareradios" />
  <label tabindex="1" for="radio2">
    2
  </label>

  <input id="radio3" type="radio" value="3" name="squareradios" />
  <label tabindex="1" for="radio3">
    3
  </label>

  <input id="radio4" type="radio" value="4" name="squareradios" />
  <label tabindex="1" for="radio4">
    4
  </label>

  <input id="radio5" type="radio" value="5" name="squareradios" />
  <label tabindex="1" for="radio5">
    5
  </label>

</div>

EDIT New Request:

I am also using Vue so it is recommended to put the input inside the label.

I would use JavaScript to handle this situation: toggle a class (I used a class called "checked") on the label to add the style.

var labels = document.querySelectorAll("label");

for (var i = 0; i < labels.length; i++) {
    labels[i].addEventListener(
        "click",
        function (e) {
            e.preventDefault();
            e.stopPropagation();

            if (this.classList.contains("checked")) {
                this.classList.remove("checked");
                this.firstElementChild.checked = false;
            } else {
                var checked = document.querySelector("label.checked");
                if (checked) {
                    checked.classList.remove("checked");
                    checked.firstElementChild.checked = false;
                }
                this.classList.add("checked");
                this.firstElementChild.checked = true;
            }
        },
        false
    );
}
.squareRadios {
  margin: 10px;
}

.squareRadios input[type="radio"] {
  opacity: 0;
  position: fixed;
  width: 0;
}

.squareRadios label {
  display: inline-block;
  background-color: #ddd;
  padding: 10px 20px;
  font-family: sans-serif, Arial;
  font-size: 16px;
  border: 2px solid #444;
  border-radius: 4px;
}

.squareRadios label:hover {
  background-color: red;
}

.squareRadios label.checked {
  background-color: blue;
  border-color: #4c4;
}

.squareRadios label:focus {
  border: 2px dashed green;
  outline: none;
}
<div class="squareRadios">
  <label tabindex="1">
    0
    <input name="squareradios" type="radio" value="0" />
  </label>

  <label tabindex="1">
    1
    <input name="squareradios" type="radio" value="1" />
  </label>

  <label tabindex="1">
    2
    <input name="squareradios" type="radio" value="2" />
  </label>

  <label tabindex="1">
    3
    <input name="squareradios" type="radio" value="3" />
  </label>

  <label tabindex="1">
    4
    <input name="squareradios" type="radio" value="4" />
  </label>

  <label tabindex="1">
    5
    <input name="squareradios" type="radio" value="5" />
  </label>

</div>

Here a working live Codepen (case: input is inside label)

Alessio
  • 3,404
  • 19
  • 35
  • 48
1

I know there are several answers already but this is exactly what you're looking for:

.squareRadios {
    margin: 10px;
}

.squareRadios input[type="radio"] {
        opacity: 0;
    position: absolute;
    width: 100%;
    height: 100%;
}

.squareRadios input[type="radio"]:checked + label {
    background: red;
}

.squareRadios label {
    display: inline-block;
    background-color: #ddd;
    padding: 10px 20px;
    font-family: sans-serif, Arial;
    font-size: 16px;
    border: 2px solid #444;
    border-radius: 4px;
}

.squareRadios label:hover {
    background-color: red;
}

.squareRadios input[type="radio"]:focus + label {
    border: 2px dashed green;
}

.squareRadios input[type="radio"]:checked + label {
    background-color: blue;
    border-color: #4c4;
}
<div class="squareRadios">
    <input type="radio" value="0" name="my_radios"/>
    <label>0</label>
    <input type="radio" value="1" name="my_radios"/>
    <label>1</label>
    <input type="radio" value="2" name="my_radios"/>
    <label>2</label>
    <input type="radio" value="3" name="my_radios"/>
    <label>3</label>
    <input type="radio" value="4" name="my_radios">
    <label>4</label>
    <input type="radio" value="5" name="my_radios"/>
    <label>5</label>
</div>

Now here's what I've changed to make things work:

  1. Like everybody else says, you'll need to put the input and label next to each other.
  2. I changed the styling of the radio buttons. I made them absolute instead of fixed and gave them a 100% width and height so they are clickable and fill out the whole label.
  3. I gave each radio button a name so they would be grouped to gether and actually work like radio buttons (only 1 button can be selected, not multiple)
Tim Gerhard
  • 3,477
  • 2
  • 19
  • 40
0

First thing is that you are hiding the main circle of radio button, by setting opacity and width to 0, with this the radio button is not be able to checked.
Second thing *+ symbol: It is Adjacent sibling combinator. It combines two sequences of simple selectors having the same parent and the second one must come IMMEDIATELY after the first.

.squareRadios {
    margin: 10px;
}

.squareRadios input[type="radio"] {
    position: fixed;

}
 
 .squareRadios label {
    display: inline-block;
    background-color: #ddd;
    padding: 10px 20px;
    font-family: sans-serif, Arial;
    font-size: 16px;
    border: 2px solid #444;
    border-radius: 4px;
}
 
.squareRadios label:hover {
    background-color: red;
}

.squareRadios input[type="radio"]:focus + label {
    border: 2px dashed green;
}

.squareRadios input[type="radio"]:checked + label {
    background-color: blue;
    border-color: #4c4;
}
<div class="squareRadios">


        <input type="radio" value="5" />
        <label>5</label>
</div>

So, remove the opacity and width properties with that your radio button can be checked and set label adjacent to input field.

*Source: CSS selector for a checked radio button's label

Ahmed Ali
  • 1,908
  • 14
  • 28
0

Labels should be next to its thing, not wrap around it.

Second thing is that you made your radios like this:

  opacity: 0;
  position: fixed;
  width: 0;

If you set your opacity: 1; you see you where not really clicking on anything.

.squareRadios {
  margin: 10px;
}

.squareRadios input[type="radio"] {
  opacity: 1;
  position: fixed;
  width: 0;
}

.squareRadios label {
  display: inline-block;
  background-color: #ddd;
  padding: 10px 20px;
  font-family: sans-serif, Arial;
  font-size: 16px;
  border: 2px solid #444;
  border-radius: 4px;
}

.squareRadios label:hover {
  background-color: red;
}

.squareRadios input[type="radio"]:focus+label {
  border: 2px dashed green;
}

.squareRadios input[type="radio"]:checked+label {
  background-color: blue;
  border-color: #4c4;
}
<div class="squareRadios">

  <input type="radio" value="0" />
  <label>0</label>


  <input type="radio" value="1" checked />
  <label> 1</label>

  <label>
        2
        <input type="radio" value="2" /></label>
  <label>
        3
        <input type="radio" value="3" /></label>
  <label>
        4
        <input type="radio" value="4" /></label>
  <label>
        5
        <input type="radio" value="5" /></label>
</div>
ikiK
  • 6,328
  • 4
  • 20
  • 40