technorthodox

I'm just your average 30-something, web software-writing, dog-loving, bike-riding Orthodox Christian, baritone, family guy.

I'm a Software Architect and User Experience consultant, and founder of Hovercraft Studios. You can check out my resume and portfolio to see the professional and personal projects I've been working on.

OOCSS Antipatterns: Analog clock theme using only CSS

You asked for it, and you got it. Several people asked me after the digital clock demo at jQCon if I thought it was possible to create an analog theme for the clock using only CSS. I had wondered this as well, but came to the conclusion that it was impossible, given the current HTML structure. So, that’s the answer I gave at the conference.

The very next day, I thought of a way to do it, so here’s an analog theme (source on github) for the digital clock done entirely in CSS.

First, note a couple things:

  1. The first hour, minute, and second digits are hidden.
  2. The second hour, minute, and second digits have been styled to look like analog clock hands—i.e. long thin rectangles, and have been anchored at the center of the analog clock face.

The key is the use (in fact, abuse, read on!) of the immediate sibling selector to rotate the clock hands to the correct position, using CSS3 transforms. For example, the line above says when the first hour digit is a “0”, and the second hour digit is also a “1” rotate the second digit (remember, it’s been styled to look like an analog clock hand) by 30°. Each hour represents 30° (360 / 12 = 30), so looking at the rest of the hour selectors, you can see how it works.

Similarly, the minutes and seconds are rotated using the immediate sibling selector. The only difference is the degrees, since 360 / 60 = 6° per minute/second.

Ok, neat, it works, but …

How not to build an analog clock

At this point, you’re probably saying to yourself (and if you’re not, you should be) “This is a terrible way to build an analog clock”. You are absolutely right. There are many problems with this, and I’d even go so far as to call the whole thing an antipattern.

From the HTML element hierarchy, to the CSS classnames, to the time computations, most everything tailored to represent an LED-based digital clock.

However, the point of this little exercise was not to find the best way to engineer an analog clock. The point was to answer the question “could it be done?”. But maybe we can learn something about OOCSS anyway.

There is something to be learned here

As the saying goes, “when all you have is a hammer, everything looks like a nail”, and in this case of trying to use only OOCSS to transform the digital clock into analog, there’s certainly some overly-ambitious hammering going on.

If the HTML is poorly-suited to the task at hand, trying to apply OOCSS on top of it will probably just make things worse. In fact, in this example, the HTML and CSS are fighting each other rather than working together.

OOCSS is not just about CSS, it’s about identifying objects in the view first (as John said in our presentation, “ignore the HTML!”), and then structuring HTML and CSS around the containers, content, identity, and states of those objects.

The fact is that the objects in this clock are LED digits, not analog clock hands, and some mildly clever CSS doesn’t change that. Conversely, this bastardization means that the hands of the analog clock have the classes “display-area” and “digit”, as well as “d0” – “d9”, none of which seem like logical choices for the hands of an analog clock!

Antipattern: In any reasonably complex system, writing HTML and CSS first is an antipattern.

What to do?: Break out the wireframes, gather around the whiteboard, and start identifying objects! List their states. Talk about ways to translate them into well-structured HTML containers and content.

One of the results of this object/HTML/CSS mismatch is state explosion, aka combinatorial explosion. There are 72 CSS rules needed just to rotate the clock hands, whereas there are only 10 rules for the original digital clock LED digits. That certainly qualifies as state explosion, and just looking at the analog rules should give you an uneasy feeling that something is wrong.

In fact, modeling any analog clock, not just this bad example of an analog clock, as discrete OOCSS states seems wrong. Consider also the progress bar example John gave during our talk. Progress bars, in most cases, represent a continuous function rather than a discrete function, and therefore can require an infinite number of states to model their possible values—e.g. 30%, 30.1%, 30.15%, and so on.

Antipattern: Trying to model continuous values with OOCSS state is an antipattern.

What to do?: Use a mechanism better suited to continuous values/functions, such as a vector library, or yes, even direct (but well abstracted!) style manipulation.

One other thing that should be bothering you about this analog clock is that nearly half the HTML elements are permanently hidden by the analog theme’s CSS. This can be an indication that you’ve misidentified the view objects. In this case, I think it’s pretty obvious that the objects I originally identified when creating the digital clock, that is, active digits composed of lit or unlit LED bars, simply are not present in the analog clock.

Antipattern: Having sections of permanently hidden HTML is an antipattern.

What to do?: Review your objects and wireframes. You may have misidentified some objects, or your application may have changed significantly enough over time that the objects you had originally, and correctly, identified are no longer present. Either way, it’s time to revisit the wireframes and refactor.

Trying to shoehorn an analog display into the digital clock was fun, but more importantly, I think it helped to identify some OOCSS antipatterns. Hopefully these will help us all avoid some pitfalls!

Font-based digital clock theme using only CSS

Ever since Daniel posted his binary mod of my digital clock, I’ve been thinking about other ways to push the limits of the clock using only CSS. At JQCon, I also talked to a few folks between sessions who had wondered the same thing. So, I’ve decided to give it a go.

One of the first ideas I had was to try to use fonts instead of the LED divs to show the clock digits. So, here you go.

It turned out to be fairly easy, and required zero changes to the Javascript view controller. The view controller simply passes the same messages to the view as it did before. In other words, the view controller relies on a message-passing-based view API to which the OOCSS responds. That API is unchanged in this version. To verify, you can hop on over to Daniel’s binary mod, which references my JS directly, and see that it still works.

It also required only superficial changes to the HTML:

  1. I added the button for the new theme in the row of theme buttons.
  2. I added “hour” and “minute” classes to the digits representing hours and minutes. This change was not necessary to support the new font-based theme, but makes the hours and minutes consistent with the seconds, which already had the class “second”.

The key changes were, of course, in the CSS, and here are some of the most relevant bits.

The comments pretty much say it all, but basically it hides the LEDs and then uses :before content to inject the font-based digits.

One thing I hadn’t thought about before I actually ran it the first time, was that the “1” digit is much thinner than all the others, so I had to forcibly set a specific width for it (in both hours/minutes and the smaller seconds). Without that specialization, the clock looks too sparse when there is a “1” (or several “1"s) being displayed. Yet another win for the OOCSS base and specialization pattern.

I think this theme looks pretty good (although I’m still partial to the LEDs), but if you have suggestions for how to tweak it, I’d love to hear them. Also, if you have an idea for how to push the envelope, feel free to leave a comment, or tweet it up!

Stay tuned for more envelope pushing …

Building a digital clock with OOCSS and MVC

I’ve been thinking a lot about OOCSS and MVC-in-the-browser over the past months. These certainly aren’t things I invented, but what I found is that my own philosophy of building applications for the web had evolved to include these concepts. It was only later that I learned that some really smart folks had also been thinking about these things, and had given them names.

So, I created this digital clock app as a simple example of some of the concepts I have been applying to build apps with OOCSS and MVC.

Very shortly after that, I got a walkthrough of John (unscriptable) Hann’s ambitious cujo.js project, and I was blown away by two things. First, he and I had basically come to believe many of the same things about applying OOCSS and MVC, and second, he had actually wrapped those things up in an incredibly simple and intuitive API inside cujo.js.

Let’s get down to business, and look at a few of these techniques in practice. I’ll hope that some theory will fall out of it as I write.

“Is A” and Specialization

Here’s a bit of HTML from the clock.

Some of the classes here set up “is a” relationships. Even though the order of classes in HTML doesn’t matter, I’ve arranged them left to right from general to specific, because I think that makes the most sense. The node “is a” slot—an admittedly awful name for an area in which the clock will display something. Also, it “is a” digit, which in this case, is a specialization of slot that will display a digit.

Farther down, there is another specialization of digit:

This node is still a digit, but more specifically, it’s a second, as opposed to a minute or hour. Looking at the rendered clock, you can see that seconds are smaller than minutes and hours—the presentation of seconds has been specialized to be smaller.

States, Views, and View Controllers

If you watch the DOM while the clock is running you’ll notice the digit nodes getting the classes d0 through d9. Obviously, this is driven by Javascript. That Javascript is acting as a View Controller. The digit is the View, and the Javascript driving, or controlling, it is the View Controller.

The classes d0 – d9 represent the possible states that the digit may be in. By changing the class, the View Controller is telling the View to change state. The View still “is a” digit, but it has changed state, for example, from a zero to a one. I guess you could say it “was a” zero and now it “is a” one, and that it’s actually mutating to another specialization rather than changing state. I think that’s a reasonable way to think about it—it’s just not how my brain works, so for me, it’s state.

The digits and the state transitions manifest themselves in the browser with the help of CSS. Here’s a bit of the CSS.

This CSS describes what a digit looks like when it’s in state d0 and d1. In addition to describing the resulting state’s presentation, it is also describing the state transition itself—that is, how (in the visual sense) the digit moves from one state to another using CSS3 transitions.

Specializations, State, and Ancestry

One thing that is subtle, but I feel is extremely important here, is that by changing the state of the digit, the state of the elements within the digit (i.e. the glowing bars) is being affected. There are no direct state changes to the bars, yet they are changing. The current state of each bar is defined by the hierarchy of classes above it in the DOM plus its own classes. Or, to put it in more general terms:

The current “whole state” (borrowing a term from a recent conversation with John) of a particular View is defined by the specializations and state of its ancestors plus its own specializations and state.

There’s no direct manipulation of nodes at the leaf level via Javascript. I’ll talk about why I believe doing direct style manipulation, such as $.css or dojo.style, is not a good engineering practice in another post, but, the key here is that by simply issuing a state transition on an enclosing View, state changes can be affected on its sub-Views.

Let’s look at why that’s interesting and useful on a practical level.

Back to Practical

So, the clock has a Javascript View Controller telling the View to change state which consequently alters the state of its sub-Views, HTML which is defining the structure of that View, and CSS that is describing the presentation of the states and the transitions between them. IMHO, that’s a very powerful separation of concerns.

Imagine you wanted to change the look of the digits by giving the bars beveled ends as some digital displays have, or you wanted to make the entire clock larger or small, or size it using percentages instead of pixels, or introducing a radical new presentation and color theme. You would not need to touch the View Controller. There are several reasons that is a good thing, IMHO, two of which are:

  1. The changes could be made by the team’s CSS designer, without involving a JS engineer, and
  2. Changing procedural code, like JS, is typically more risky than changing declarative code, like CSS.

This separation of concerns provides similar benefits on the View Controller side. When I decided to add support for 24 hour display, all I had to do (ignoring adding the new View components for selecting 12 or 24 hour time, and storing the preference) was to make a small change to the hour computation in the View Controller Javascript, issue slightly different state changes for the hour digits, and ensure that the AM or PM elements are always in the off state.

I didn’t need to make any changes to the CSS or HTML. Engineers can craft the JS, and the designers can craft the CSS. Sure, you might play both roles, but that’s not the case with every team, especially in large, complex apps, with many Views, company wide design standards, branding, and a small army of awesome designers complimented by an equally awesome army of software engineers.

I am very excited about building apps using these techniques, and I am especially excited after seeing John’s work so far on cujo.js. If it turns out to embody these concepts like I think it will, it’s gonna be a very powerful platform. I’ll certainly be keeping an eye on it.