Toggle between radio values when DIV is clicked

Viewed 77

I have a 3 state radio button.

The initial state is undetermined, Then you can disable/enable it.

The problem is when you click over the DIV. It always gets the first radio button value (OFF in this case). I would like to toggle between ON/OFF. If you click on the labels it works correctly.

.element-toggle-container {
  cursor: pointer;
  display: inline-block;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.element-toggle-switch {
  display: inline-block;
  border-radius: 1.5rem;
  height: 1.5rem;
  width: 3rem;
  position: relative;
  vertical-align: middle;
  transition: background 0.25s;
  margin: .5rem;
}

.element-toggle-switch:before,
.element-toggle-switch:after {
  content: "";
}

.element-toggle-checkbox.disabled~.element-toggle-switch,
.element-toggle-checkbox:disabled~.element-toggle-switch {
  cursor: not-allowed;
  opacity: .65;
}

.element-toggle-switch:before {
  display: block;
  background: #fff;
  border-radius: 50%;
  position: absolute;
  transition: left 0.25s;
  top: 0.1875rem;
  left: 0.1875rem;
  width: 1.125rem;
  height: 1.125rem;
}

.element-toggle-container:hover .element-toggle-switch:before {
  background: #fff;
}

.element-toggle-checkbox[value="na"]:checked~.element-toggle-switch {
  background: #CCCCCC;
}

.element-toggle-checkbox[value="na"]:checked~.element-toggle-switch:before {
  left: 0.9375rem;
}

.element-toggle-checkbox[value="off"]:checked~.element-toggle-switch {
  background: #ff0f0f;
}

.element-toggle-checkbox[value="on"]:checked~.element-toggle-switch {
  background: #56c080;
}

.element-toggle-checkbox[value="on"]:checked~.element-toggle-switch:before {
  left: 1.6875rem;
}

.element-toggle-checkbox {
  position: absolute;
  visibility: hidden;
}
<label for="element-1-off">No</label>
<label class="element-toggle-container">
  <input class="element-toggle-checkbox not_uniform" id="element-1-off" value="off" name="element-1" type="radio" />
  <input class="element-toggle-checkbox not_uniform" id="element-1-na" value="na" name="element-1" type="radio" checked="checked" />
  <input class="element-toggle-checkbox not_uniform" id="element-1-on" value="on" name="element-1" type="radio"  />
  <div class="element-toggle-switch"></div>
</label>
<label for="element-1-on">Yes</label>

2 Answers

The issue is that the .element-toggle-container is a <label> element without a for specified and it has the <input> elements as children. This means it will relate to the first <input> child, which in this case is the 'off' button. Why not remove the .element-toggle-container altogether and extend the labels of the 'on' and 'off' buttons like in the example below?

label[for="element-1-off"],
label[for="element-1-on"] { 
  display: block;
  position: absolute;
  top: .1rem;
  z-index: 10;
}

label[for="element-1-off"] {
  padding-right: 1.15rem;
  left: 0;
}

label[for="element-1-on"] {
  padding-left: 1rem;
  left: 3.5rem;
}

.toggle-switch {
  position:relative;
}

.element-toggle-switch {
  display: block;
  border-radius: 1.5rem;
  height: 1.5rem;
  width: 3rem;
  position: relative;
  vertical-align: middle;
  transition: background 0.25s;
  margin: 0 1.5rem;
}

.element-toggle-switch:before,
.element-toggle-switch:after {
  content: "";
}

.element-toggle-checkbox.disabled~.element-toggle-switch,
.element-toggle-checkbox:disabled~.element-toggle-switch {
  cursor: not-allowed;
  opacity: .65;
}

.element-toggle-switch:before {
  display: block;
  background: #fff;
  border-radius: 50%;
  position: absolute;
  transition: left 0.25s;
  top: 0.1875rem;
  left: 0.1875rem;
  width: 1.125rem;
  height: 1.125rem;
}

.element-toggle-container:hover .element-toggle-switch:before {
  background: #fff;
}

.element-toggle-checkbox[value="na"]:checked~.element-toggle-switch {
  background: #CCCCCC;
}

.element-toggle-checkbox[value="na"]:checked~.element-toggle-switch:before {
  left: 0.9375rem;
}

.element-toggle-checkbox[value="off"]:checked~.element-toggle-switch {
  background: #ff0f0f;
}

.element-toggle-checkbox[value="on"]:checked~.element-toggle-switch {
  background: #56c080;
}

.element-toggle-checkbox[value="on"]:checked~.element-toggle-switch:before {
  left: 1.6875rem;
}

.element-toggle-checkbox {
  position: absolute;
  visibility: hidden;
}
<div class="toggle-switch">
  <input class="element-toggle-checkbox not_uniform" id="element-1-off" value="off" name="element-1" type="radio" />
  <input class="element-toggle-checkbox not_uniform" id="element-1-na" value="na" name="element-1" type="radio" checked="checked" />
  <input class="element-toggle-checkbox not_uniform" id="element-1-on" value="on" name="element-1" type="radio"  />
  <label for="element-1-off">No</label>
  <div class="element-toggle-switch"></div>
  <label for="element-1-on">Yes</label>
</div>

.element-toggle-container {
  cursor: pointer;
  display: inline-block;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.element-toggle-switch {
  display: inline-block;
  border-radius: 1.5rem;
  height: 1.5rem;
  width: 3rem;
  position: relative;
  vertical-align: middle;
  transition: background 0.25s;
  margin: .5rem;
}

.element-toggle-switch:before,
.element-toggle-switch:after {
  content: "";
}

.element-toggle-checkbox.disabled~.element-toggle-switch,
.element-toggle-checkbox:disabled~.element-toggle-switch {
  cursor: not-allowed;
  opacity: .65;
}

.element-toggle-switch:before {
  display: block;
  background: #fff;
  border-radius: 50%;
  position: absolute;
  transition: left 0.25s;
  top: 0.1875rem;
  left: 0.1875rem;
  width: 1.125rem;
  height: 1.125rem;
}

.element-toggle-container:hover .element-toggle-switch:before {
  background: #fff;
}

.element-toggle-checkbox[value="na"]:checked~.element-toggle-switch {
  background: #CCCCCC;
}

.element-toggle-checkbox[value="na"]:checked~.element-toggle-switch:before {
  left: 0.9375rem;
}

.element-toggle-checkbox[value="off"]:checked~.element-toggle-switch {
  background: #ff0f0f;
}
.element-toggle-checkbox[value="off"]:checked~.element-toggle-switch:before {
  left: 0.2375rem;
}

.element-toggle-checkbox[value="on"]:checked~.element-toggle-switch {
  background: #56c080;
}

.element-toggle-checkbox[value="on"]:checked~.element-toggle-switch:before {
  left: 1.6875rem;
}

.element-toggle-checkbox {
  position: absolute;
  visibility: hidden;
  
}
Related