tactile

– thoughts on CSS, UIs and UX.

Progressive enhancement by adding classes

Posted: December 12th, 2012 Author:

Progressive enhancement is a Front-end Development practice that ensures your clients can still operate a webpage without (for instance) JavaScript support.
JS-driven widgets typically have styling applied, so it’s important to only add those styles if JavaScript is supported. One of the better ways to do this is by adding the relevant classes via JavaScript, but leaving the control of these classes in the HTML. Let me explain…

The No-JavaScript-Scenario

In the case JavaScript is not supported by the client / browser, then your page should still be functional and still make visual sense.
So, you should:

  1. Use semantic markup. Your page should still make sense without CSS.
  2. Your CSS should have a baseline style that makes sense for the page without JS support.
  3. Add the necessary styling to JS-driven widgets via extra classes

With the baseline styles taken care of, we need to move onto adding the relevant behaviours and styling to improve the user’s interaction with your page.

Initial state: adding the default classes

When the document is loading, you’ll want to set classes to cover the initial state of the element. If JS is enabled, we’ll want our loaded HTML to look like this:

<div class="container collapsible collapsed">
  <h3>More info</h3>
  <p>Once you've submitted the form...</p>
</div>

In this example, I want the <div class="container"> to have two extra classes, collapsible and collapsed:
collapsible is used for event handling and some styling.
collapsed is used for the open or closed state of the collapsible element (assumes an element is open is by default).

To add these two classes, we could write our script in several ways:

  • The JS would store and add the classes we want.
  • The HTML could store the classes with a prefix or array, the JS could then translate these classes into our CSS classes
  • Or we could use the HTML to store the classes somewhere else, and then use JS to read from those

This is a perfect scenario to use the HTML5 data- attributes. e.g.

<div class="container" data-add-class="collapsible collapsed">
  <h3>More info</h3>
  <p>Once you've submitted the form...</p>
</div>

From our script point of view, all we’d have to do is scour the document for a predefined data attribute and copy the values of this attribute into the class attribute, like so in jQuery:

$(document).ready(function(){
  // When the DOM is ready, scour the elements in the DOM for the existence of a 'data-add-class' attribute
  $('[data-add-class]').each(function(){
    var class_to_add = $(this).attr('data-add-class');
    // Then take the value from this attribute and add it into the class list.
    $(this).addClass(class_to_add);
  });
});

Now that the extra classes are being added we can add whatever styling we see fit.

Why use data-attributes?

“Wait, why not use JS to store and set these classes?” I hear you ask.
Often the server will want to set the initial state of the element, so instead of using script blocks and IDs to set initial state-classes, the server can set the state-classes via the data-attribute. e.g.:

<div class="container" data-add-class="collapsible <% if (someBoolean) %>collapsed<% endif %>">

A working example

Accordions are a perfect example of this approach. Accordions need to display all their information if JS is not available, and we only want the toggling behaviour to be added later. See my example on codepen.io.

Wrapping up

This is a great platform for further interaction enrichment. We’re leaving the styling up to the CSS, content and basic content styling in the hands of the HTML and then enriching the whole experience with JavaScript (if the browser supports it). We could make some further enhancements in the CSS such as by adding hardware-accelerated animations using transitions.

I hope this article was helpful. Are you writing progressive HTML, CSS and JS? If so, share your examples!

Comments are closed.