6

I just came across the switch toggle button which is created only using css. It known as the checkbox hack.

For those who doesn't know what a checkbox css hack is, Please read it here

https://css-tricks.com/the-checkbox-hack/

I tried it out and it was working perfectly fine. But I didn't understand how this is working because we are not clicking on the checkbox.

So I have 2 questions

  1. How is this working ?

  2. Instead of absolute positioning I tried it with display: none; It still worked. Does this method have any drawbacks?

Stephan Muller
  • 27,018
  • 16
  • 85
  • 126
Konza
  • 2,143
  • 17
  • 30

4 Answers4

6

The way it works is by using the <label> element. Any input element can (and usually should) have a label. You can tell the browser which label belongs to which label by using a for attribute, referring to the input's name:

<input name="myName" />
<label for="myName">Label</label>

Whenever you click the label, it focuses the input (or in case of checkboxes, toggles it).

The label and checkbox don't have to be near each other. You could add a few hidden checkboxes at the start or end of a document and place the labels anywhere on the page, and they'd still focus the input.

Hiding the checkbox through display: none could cause buggy behavior on certain browsers. Just hiding it from view by a position: absolute is safer.

Stephan Muller
  • 27,018
  • 16
  • 85
  • 126
1
  1. You can bind labels to checkboxes/radios using the for= attribute. When this is set, clicking on the label toggles the checkbox. This is a standard HTML attribute.

  2. You can hide the checkbox using display: none, but do test it to make sure that its value is still submitted with the form.

1

CSS is aware of the current checked state of a checkbox input


This awareness, in combination of siblings selectors such as + (immediate next sibling) and ~ (next sibling somewhere) allows styling different styles, for checked/unchecked states, to anything that comes after the input element. The key here is the word "after".

Basic example:

/* styles when checkbox is unchecked */
div{ border:2px solid blue; margin:10px }
div h3{ color:red; }


/* when checkbox is checked */
input:checked ~ div{ background:blue; }
input:checked ~ div h3{ color:gold; }
<input type=checkbox>

<div><h3>very<h3></div>
<div><h3>cool<h3></div>

As others have said (but is not a must) - HTML label element allows to interact with input elements, and in checkbox/radio types' case - it allows to toggle their checked state by clicking the label itself, which is "linked" to a specific input element by the for attribute:

<label for='x`>click</label>

and the id attribute no the linked input:

<input type='checkbox' id='x'>

For the method to work, the input element must to be placed before whatever element(s) it is intended to control via CSS.

In real-word use cases, one would often want to use the CSS-toggling features of a checkbox over next siblings, but to obscure the fact there is a checkbox involved. The best way is by applying the hidden attribute on the input, which only toggles off the rendering of the input, nothing else.

The example below showcase such use case for a simple accordion component:

Practical example: Accordion

.accordion{ width: 300px; border: 1px solid silver; }
.accordion label{ display:block; padding:1em; cursor:pointer; }
.accordion label:hover{ color:red; } 

.accordion > div:not(:last-child){ border-bottom:1px solid silver; }
.accordion .more{ max-height:0; transition:.5s; color:green; padding:0 1em; overflow: hidden; }

/* checked toggled */
.accordion input:checked + .content{ background:#EEE; }
.accordion input:checked + .content .more{ max-height:200px; }
<div class='accordion'>
  <div>
    <input type='checkbox' id='checkbox_item_1' hidden>
    <div class='content'>
      <label for='checkbox_item_1'>Title 1</label>
      <div class='more'>
        <p>This is cool<p>
        <p>Yes it is</p>
      </div>
    </div>
  </div>

  <div>
    <input type='checkbox' id='checkbox_item_2' hidden>
    <div class='content'>
      <label for='checkbox_item_2'>Title 2</label>
      <div class='more'>
        <p>This is also cool</p>
        <p>So much fun</p>
      </div>
    </div>
  </div>
</div>
vsync
  • 118,978
  • 58
  • 307
  • 400
0

You can hide the checkbox with visibility: hidden; or opacity: 0; besides display: none; but i'm not sure which one is better.