CSS3 Interactive Interfaces

11.30.2012

This week, I'm lucky enough to speak at CSS Dev Conference in Honolulu, Hawaii. I've worked on my deck pretty substantially since SXSW. Of all the slides, I have two favorites. My first favorite slide quotes The Princess Bride. My second favorite slide has only a couple words:

Why JS?
This is CSS Dev Conference

CSS3 Interfaces

Driven by a desire to see what types of interfaces can be easily ported to CSS3, I spent some time coding up rudimentary demos. Each one of these shows functionality that is typically implemented using JavaScript.

HTML and CSS Replacing JS

HTML and CSS have evolved. This is relatively obvious. However, what is interesting is the way in which HTML and CSS evolve.

HTML and CSS are designed around marking up and displaying content better on the web. This is the heart of web standards: to create languages that can deliver information to users on all sorts of different devices around the world. Because of this, the languages evolve new features to answer common patterns.

Since early versions of HTML and CSS, these languages replace functionality that was once only possible with JavaScript, or with other client- or server-side technologies. Think about the things we can do now with HTML and CSS that wasn't available just a few years ago:

As HTML5 gets better-implemented, we see further transitions from the world of JS. HTML5 form validation, date pickers, and rich number selectors will all further extend HTML5's power.

CSS3 Psuedo Classes

CSS3 adds many selectors to CSS2.1's selector language. Here are some of the most interesting selectors (yes, some of these are CSS2.1 selectors, but they remain under-utilized):

:target

The :target psueo class is extremely handy for adding styles to elements that have been targeted by clicking on an anchor tag. Anchors that take the user to another section of the page have been widely since HTML's early days. However, the ability to style these elements offeres new possibilities.

A simple example of this could be to visually highlight a targeted seection. This could be done by adding a light background to the header, or subtly darkening the header of the text. This may help orient users if there are lots of sections in quick succession.

However, :target also holds the key to many pure-CSS implementations of interfaces that usualy require JavaScript. In two of the demos (tabs and accordions) :target is used to display the correct section, whether it is part of a tab or of an accordion.

:target can also be used in order to power CSS-based modal popovers. The contents of the modal should be hidden from view, and then displayed as soon as the anchor associated with the modal is clicked.

:checked

In a similar vein to :target is :checked. Instead of actuating on a change in the page's URI, it actuates when a checkbox or radio button is checked or highlighted.

This can give an added benefit if manipulating the URL is something that you don't want to do, or if you need to actuate more than one thing at a time. This is because multiple checkboxes can be checked at a time, or even multiple radio buttons provided they do not share the same name. :target can only affect one element at a time.

Because of this, we can use :checked in order to create accordions where more than one pane can be open at a time.

:checked powers the tray and the first two of the accordion demos.

Since form elements can be ungainly when used for UI controls, you may want to actuate the checkbox and radio buttons via a label tag. A label tag should have a for attribute that matches the form element's id attribute.

Siblings (+, ~)

However, when working with the :checked psuedo class, we often don't want to style the checkbox or radio button directly. Instead, we want to hide the form element and change how the label, article, or some other element looks. To do this, we'll often need to use sibling selectors.

So, to style the label after an input, we can use:

input:checked + label {
  color: #900;
}

/* OR */

input:checked + article {
  display: block;
}

However, each element can only have one next element, so you can't do both of the above. And, unfortunately, at the time of writing (December, 2012) some of these selectors can lead to bad performance, even on advanced browsers (Chrome) and solid hardware. So, the following does not work well:

input:checked + label {
  color: #900;
}

input:checked + label + article { /* DO NOT USE */
  display: block;
}

Instead, a better solution to chaining element selectors is to either use the general younger sibling selector, or have a DOM node that contains both the label and article immediately after the checkbox. Both these solutions work, and I use the latter in the accordion demos. The former technique requires knowing there will only be one article following the checked at the same level of the DOM.

input:checked + label {
  color: #900;
}

input:checked ~ article {
  display:block;
}

/* OR */

input:checked + section label {
  color: #900;
}

input:checked + section article {
  display:block;
}