Skip to content Skip to sidebar Skip to footer

Toggle Radio Input Using Css Only

The following code use a script to toggle/uncheck a radio when clicked a second time on the same. My question is how do I do this using CSS only? Edit I need a cross browser solut

Solution 1:

You can't change the functionality of radio buttons using CSS. CSS is designed for visual changes only.

That said, you can simulate this behavior with a clever hack. For your example, I'd recommend using CSS to visually replace the label for the currently selected radio button with a dummy label attached to another radio button representing a "blank" or "empty" selection. That way, clicking the dummy label would select the "blank" option, effectively clearing your prior choice:

.container {
  display: flex;
  flex-wrap: wrap;
  max-width: 660px;
}
.container > label {
  flex: 1;
  flex-basis: 33.333%;
}
.container > div {
  flex: 1;
  flex-basis: 100%;
}
.containerlabelimg {
  display: block;
  margin: 0 auto;
}
.containerinput, .containerinput ~ div {
  display: none;
  padding: 10px;
}

.container#img1:checked ~ #img1txt,
.container#img2:checked ~ #img2txt,
.container#img3:checked ~ #img3txt {
  display: block;
}

.containerlabel[for=noimg] {
  display: none;
}

.container#img1:checked ~ label[for=img1],
.container#img2:checked ~ label[for=img2],
.container#img3:checked ~ label[for=img3] {
  display: none;
}

.container#img1:checked ~ label[for=img1] + label[for=noimg],
.container#img2:checked ~ label[for=img2] + label[for=noimg],
.container#img3:checked ~ label[for=img3] + label[for=noimg] {
  display: block;
}
<divid="img-select"class="container"><inputid="noimg"type="radio"name="img-descr"><inputid="img1"type="radio"name="img-descr"><inputid="img2"type="radio"name="img-descr"><inputid="img3"type="radio"name="img-descr"><labelfor="img1"><imgsrc="http://lorempixel.com/200/200/food/1/"alt=""></label><labelfor="noimg"><imgsrc="http://lorempixel.com/200/200/food/1/"alt=""></label><labelfor="img2"><imgsrc="http://lorempixel.com/200/200/food/6/"alt=""></label><labelfor="noimg"><imgsrc="http://lorempixel.com/200/200/food/6/"alt=""></label><labelfor="img3"><imgsrc="http://lorempixel.com/200/200/food/8/"alt=""></label><labelfor="noimg"><imgsrc="http://lorempixel.com/200/200/food/8/"alt=""></label><divid="img1txt"><div>Recipe nr 1</div></div><divid="img2txt"><div>Recipe nr 2</div></div><divid="img3txt"><div>Recipe nr 3</div></div></div>

(View in JSFiddle)

Solution 2:

If the effect does not need to be persistent, you can achieve something similar playing with :focus instead of using radio buttons.

To make an element focusable, set the tabindex attribute to an integer. Use a negative one if you don't want the element to be reached via sequential focus navigation (pressing the "tab" key).

.container {
  display: flex;
  flex-wrap: wrap;
  max-width: 660px;
}
.container > .img {
  flex: 1;
  position: relative;
}
.container > .img > .unselect {
  display: none;
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}
.container > .txt {
  display: none;
  order: 1;
  flex-basis: 100%;
}
.container > .img:focus > .unselect,
.container > .img:focus + .txt {
  display: block;
}
<divid="img-select"class="container"><divclass="img"tabindex="0"><imgsrc="http://lorempixel.com/200/200/food/1/"alt=""><spanclass="unselect"tabindex="-1"></span></div><divclass="txt">Recipe nr 1</div><divclass="img"tabindex="0"><imgsrc="http://lorempixel.com/200/200/food/6/"alt=""><spanclass="unselect"tabindex="-1"></span></div><divclass="txt">Recipe nr 2</div><divclass="img"tabindex="0"><imgsrc="http://lorempixel.com/200/200/food/8/"alt=""><spanclass="unselect"tabindex="-1"></span></div><divclass="txt">Recipe nr 3</div></div>

Solution 3:

Bounty Challenge Accepted (without the extra noimg)

.container {
    display: flex;
    flex-wrap: wrap;
    max-width: 660px;
    overflow: hidden;
    position: relative;
}
.containerimg {
    user-select: none;
    pointer-events: none;
}
.container > label {
    flex: 1;
    flex-basis: 33.333%;
    z-index: 1;
}
.container > div {
    flex: 1;
    flex-basis: 100%;
}
.containerlabelimg { margin: 0 auto }
.containerinput,
.containerinput ~ div {
    display: none;
    padding: 10px;
}
.containerlabel[for=none] {
    position: absolute;
    bottom: 0;
    top: 0;
    left: 0;
    right: 0;
    z-index: 0;
}
.container#img1:checked ~ label[for=img1],
.container#img2:checked ~ label[for=img2],
.container#img3:checked ~ label[for=img3] {
    pointer-events: none;
    z-index: -1;
}
.container#img1:checked ~ #img1txt,
.container#img2:checked ~ #img2txt,
.container#img3:checked ~ #img3txt { display: block }
<divid="img-select"class="container"><inputid="img1"type="radio"name="img-descr"><inputid="img2"type="radio"name="img-descr"><inputid="img3"type="radio"name="img-descr"><!-- Experimental --><inputid="none"type="radio"name="img-descr"checked><labelfor="none"></label><labelfor="img1"><imgsrc="http://dummyimage.com/200/333"alt=""></label><labelfor="img2"><imgsrc="http://dummyimage.com/200/666"alt=""></label><labelfor="img3"><imgsrc="http://dummyimage.com/200/999"alt=""></label><divid="img1txt"><div>Recipe nr 1</div></div><divid="img2txt"><div>Recipe nr 2</div></div><divid="img3txt"><div>Recipe nr 3</div></div></div>

EDIT: By definition radio buttons shouldn't be toggleable (I forgot that this was an additional requirement in this task = to broke the rules). @Ajedi32 answer is probably the best, but it can be optimized (repeated images)? Bounty still in game...

EDIT 2: Now it's fully functional solution. (doing this trick https://stackoverflow.com/a/7392038/2601031)

EDIT 3: Multi-layer layout + Repaired selection.

Solution 4:

The answer is you can't unselect or uncheck a radio button in CSS only, as the radio button only becomes unchecked once you click on a different radio button. As only one radio button can be active at once, this will uncheck the previously checked radio button.

input:checked + label {
    color: green;
}

input:not(:checked) + label {
    color: red;
}

So you'll have to stick with using the JS function you posted.

Here are a couple of nice articles with further explanation :

CSS Click Events

How To Generate CSS Click Events

Solution 5:

The trick is using :target. I added two empty <a> tags in each block, and set them to cover the block completely in order to perform the click event. The first link is for the real :target event, and second link is just for undo it, with a bit help of z-index to make it happen.

jsFiddle

ul {
  padding: 0;
  margin: 0;
}
li {
  display: inline-block;
  vertical-align: top;
  position: relative;
}
a {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
div {
  display: none;
}
.target{
  z-index: 1;
}
.target:target {
  z-index: -1;
}
.target:target ~ div{
  display: block;
}
<ul><li><ahref="#link-1"id="link-1"class="target"></a><ahref="#"></a><imgsrc="//dummyimage.com/150/333"><div>a</div></li><li><ahref="#link-2"id="link-2"class="target"></a><ahref="#"></a><imgsrc="//dummyimage.com/150/666"><div>b</div></li><li><ahref="#link-3"id="link-3"class="target"></a><ahref="#"></a><imgsrc="//dummyimage.com/150/999"><div>c</div></li></ul>

Post a Comment for "Toggle Radio Input Using Css Only"