:checked craziness

Ryan Seddon

From Melbourne, Australia

FACT:
Melbourne is the only city in the
world founded by Batman*.

* Stolen from food bloggers twitter bio

The checkbox is pretty boring...

Incorrect

+ :checked = Awesome

Interaction without JavaScript

Stateful CSS, makes for something unexpected be extremely powerful

Custom Checkboxes/Radios

Original demo by Simurai

Quite easy

<input type="radio" name="opts" id="opts1"> 
<label for="opts1">Option</label>

Setup the styles to react to label clicks

input + label {
 background-position: 50px 0;
}
input:checked + label {
 background-position: 0 0;
}
input:checked ~ input + label {
 background-position: -50px 0;
}

Shiny dot

input + label {
    /* less interesting styles */
    background-image: radial-gradient(hsla(200, 100%, 90%, 1) 0%, 
                        hsla(200, 100%, 70%, 1) 15%, 
                        hsla(200, 100%, 60%, 0.3) 28%, 
                        hsla(200, 100%, 30%, 0) 70%);
    border-radius: 25px; 
    box-shadow: hsla(0, 0%, 100%, 0.15) 0 1px 1px, 
                inset hsla(0, 0%, 0%, 0.5) 0 0 0 1px;
    transition: background-position 0.15s cubic-bezier(0.8, 0, 1, 1);
}

Wrote an article about this technique

Tree menu

See demo

Tree markup

<ol>
  <li>
    <input type="checkbox" checked id="folder1" />
    <label for="folder1" onclick>Folder 1</label> 
    <ol>
       <li>File</li>
    </ol>
  </li>
  ... more items
</ol>

CSS, heavily simplified

.tree li input:checked ~ ol {
    height: auto;
    padding: 0 0 0 35px;
}
.tree li label:after, .tree li label:before,
.tree li input:checked ~ ol:before {
    background: url(icon-sprite.png) 0 0 no-repeat;
    content: "";
    height: 14px;
    width: 14px;
}
.tree li input ~ ol > li { display: none; }
.tree li input:checked ~ ol > li { display: block; }

Wrote an article on this too!

Snorefest

bootleg.css

A dodgy version of bootstrap plugins

Dropdowns

Dropdown markup

<ul class="nav" role="navigation">
  <li class="dropdown">
    <input type="radio" name="dropdowns" id="dropdown1">
    <label for="dropdown1" class="dropdown-toggle" onclick>
        Dropdown 
        <b class="caret"></b>
    </label>
    
    <ul class="dropdown-menu" role="menu">
      <li><a tabindex="-1" href="#">Action</a></li>
      ... more items
    </ul>
    <label for="dismissdd" class="dismiss-dd" onclick></label>
  </li>
</ul>

<input type="radio" checked id="dismissdd" name="dropdowns">

Dropdown CSS

#dropdowns input[type="radio"] ~ .dismiss-dd {
    display: none;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 999;
    padding: 0 !important;
    background: transparent !important;
    line-height: 0;
    cursor: default;
}

#dropdowns input[type="radio"]:checked ~ .dropdown-menu,
#dropdowns input[type="radio"]:checked ~ .dismiss-dd {
    display: block;
}

Collapse

Collapse markup

<input type="radio" name="accordion-group" id="collapseAll">
<div class="accordion-group">
  <input type="radio" id="collapse1" name="accordion-group" checked>
  <label for="collapseAll" class="accordion-dismiss"></label>

  <div class="accordion-heading">
    <label for="collapse1" class="accordion-toggle">Heading #1</label>
  </div>
  <div id="collapseOne" class="accordion-body collapse">
    <div class="accordion-inner">
      ...
    </div>
  </div>
</div>

Collapse CSS

#collapse .accordion input ~ .collapse {
    max-height: 0;
    height: auto;
    transition: max-height 0.2s ease 0s;
}
#collapse .accordion input:checked ~ .collapse {
    max-height: 500px;
    transition-duration: 0.7s;
}

Tabs

Tabs markup

<input type="radio" id="foo" name="tabs">
<label onclick for="foo">Foo</label>

//... more tabs

<div class="tabs-container">
    <div class="tab">...</div>
    //... more tab content
</div>

Tabs CSS

.tabs input:nth-of-type(1):checked ~ .tab-content > :nth-of-type(1),
.tabs input:nth-of-type(2):checked ~ .tab-content > :nth-of-type(2),
.tabs input:nth-of-type(3):checked ~ .tab-content > :nth-of-type(3) {
  display: block;
  opacity: 1;
}

Modals

Modals markup

<!-- Modal 1 -->
<label class="btn" for="modal1" onclick>Launch ze modal</label>
<input type="radio" id="modal1" name="modal" />

<div class="modal hide fade">
  <div class="modal-header">
    <label role="button" class="close" for="closemodal">√ó</label>
    <h3>Modal header</h3>
  </div>
  <div class="modal-body">...</div>
  <div class="modal-footer">
    <label role="button" class="close" for="closemodal">Close</label>
  </div>
</div>

<!-- Overlay and close -->
<input type="radio" id="closemodal" name="modal" />
<label for="closemodal" class="modalclose">&nbsp;</label>

Modals CSS

#modals input ~ .modal {
    left: 50%;
    margin: 0;
    top: 0;
    opacity: 0;
    transition: transform 0.3s ease-in, opacity 0.3s linear;
    transform: translate(-50%,-100%);
}
#modals input:checked ~ .modal {
    opacity: 1;
    transition-delay: 0.4s;
    transform: translate(-50%,20%);
}

Modal closing CSS

#modals input + .modalclose {
    transition: opacity 0.3s linear;      
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: -1;
    opacity: 0;
}
#modals input:not(#closemodal):checked ~ .modalclose {
    opacity: 0.8;
    z-index: 1;
    background: #000;
    margin: 0 !important;
    transition-delay: 0;
}

Carousel

There's a lot going on in this, so...

This slide deck is powered by :checked

Introducing Slideshowbob

The Carousel and slideshowbob
work almost the same

Let's jump to the editor!

Or go to github and checkout the source code.

Quirks & Bugs

WebKit couldn't handle it

// Off
input[type="checkbox"] ~ div {
    // Fancy styles
}

// On
input[type="checkbox"]:checked ~ div {
    // Fancy styles
}

Prior to Safari 5.1 & Chrome 13 this didn't work

Labels and iOS5 requires empty onclick

<input type="checkbox" id="foo">
<label onclick="" for="foo">I need an onclick in iOS</label>

<=iOS5 will not update a checkboxes state when touching a label, but adding an onclick attribute works.

Downsides

Accessibility issues

Confusing markup when consumed through a screenreader

Sometimes* require specific placement of markup

* and by sometimes I mean most of the time...

Overly complex selectors

Look at the Carousel CSS +/~ all over

Browser support

Basic:
Firefox Chrome Opera Safari IE
1+ 2+ 9.2+ 3.2+ 9+
Fancy:
16+ 22+ 12+ 6+ 10+

Future, maybe...

A proposal for toggability on any element

#modal {
    toggle-states: 2; // How many states
    display: none;
}
// An element with 2 or greater toggle states
// can react to the :checked pseudo-class
#modal:checked {
    display: block;
}
.modal-button {
    toggle-share(#modal);
}