OOCSS Module Blue-Printing – Using External Constrains to Assure Markup and CSS Quality

illustration
Keep them in check

Update: This whole thing has been superseded with a more uniform and rigid concept. You can check an early draft outline over at the OOCSS Google Group.

There is no coupling whatsoever between your CSS and your markup. But don't get me wrong – this is a very good thing. However, this also means you can't use your markup to verify your CSS and of course it also means that you can't use your CSS to check your markup.

If you create a relatively complex website with more than 2000 lines of CSS this gets pretty annoying. With practice this just gets more annoying, since the impact on your productivity becomes more apparent with each project. During a site's lifetime you'll often notice how theoretically solid structures start to crumble. One mistake in the markup, another one in the CSS, and sooner or later everything will be in a somewhat inconsistent state.

If you come from a programming background this feels just plain wrong. It's almost like your selectors happen to coincidentally select some things here and there. There is no clear way to define a structure and to check if your markup and CSS adhere to your rules. There is currently only one way to check it: the dreaded, time-consuming, and error-prone manual one.

Also, if things are inconsistent – and chances are this happens right off the bat – it's very difficult to reason about it. You might look at two pieces of markup and their corresponding CSS and both might wrong in different places. Sure, you can just refer to your documentation… eh, yea, who am I kidding? No one knows how stuff like that is supposed to be documented. And if they do, it probably still won't happen.

The Big Caveat

I thought about this problem for a while and I think I finally came up with something that actually might do the trick. However, there is one noteworthy caveat: complete discontinuation of any IE6 support whatsoever.

The problem with IE6 (in this case) is its lack of support for the child combinator. Without it, you can't describe a rigid structure, which is an essential requirement for completely predictable behavior.

And this is something you really need, if you want to be able to test your structural pieces in isolation and yet be able to nest them in any way you like. With the magic of the child combinator you can just do that. You can reuse your "attribute classes" wherever you wan't – no strings attached!

By the way, this assumes that you're familiar with the OOCSS concepts. If you haven't heard about it, check Nicole Sullivan's talks over at the YUI Theater.

The Big Idea

As you've probably figured out by now: It's about defining the rules externally and then running automated tests against your markup and CSS. It's also possible to generate CSS selector stubs based on those rules and there might be even other things I haven't thought of.

For XML there are things like DTD and RELAX NG, but we won't need anything that complicated. All we need are classes and the classes of their children and their optional children. Another thing is inheritance, knowing about it allows one to verify the order of the selectors.

The syntax I came up with is straightforward and terse:

// newline and space serve as separator
// there can be an arbitrary amount of separators between tokens
.mod(
    ~.hd // this one is marked as optional
    .bd  // this one isn't
    ~.ft
)
.mod-x:.mod( // extends mod
    ~.arb
)
.bar(
    .inner(
        .hd
        .bd
        .ft
    )
)

// exactly the same as the stuff above
.mod(~.hd .bd ~.ft)
.mod-x:.mod(~.arb)
.bar(.inner(.hd .bd .ft))

Not much thought went into the syntax to be honest. It's just about the concept at this stage. But I already like the architectural overview it provides. It cuts it down to the bare metal. I really like that.

Now you can for example parse those constrains with JavaScript and perform checks in the background while building the site. The following markup for example would pass just fine and you wouldn't see a notification:

<div class="mod">
    <div class="hd"></div>
    <div class="bd"></div>
    <!-- there is no .ft, but this is ok -->
</div>

<div class="mod mod-x">
    <div class="hd"></div>
    <div class="bd">
        <!-- inside any leaf node can be any kind of arbitrary content -->
        <!-- for example, you could put another .mod here, or .mod-x, or both of them -->
        <!-- even bad RTE markup would be alright (as far as we're concerned) -->
    </div>
    <!-- no .ft and .arb, but this is ok  -->
</div>

<div class="bar">
    <div class="inner">
        <div class="hd"></div>
        <div class="bd"></div>
        <div class="ft"></div>
    </div>
</div>

You could also use those constrains to generate a selector stub CSS file, which would look like this:

.mod{}
.mod>.bd{}
.mod>.hd{}
.mod>.ft{}
/* .mod>.foo would cause an error to be thrown */

.mod-x{} /* mod-x's selectors must be declared after mod's */
.mod-x>.bd{}
.mod-x>.hd{}
.mod-x>.ft{}
.mod-x>.arb{}

.bar{}
.bar>.inner{}
.bar>.inner>.hd{}
.bar>.inner>.bd{}
.bar>.inner>.ft{}

Later on you can use those constrains and check if your updated CSS file still adheres to your (eventually updated) rules.

Well, it's really just a concept at this stage and yes, there probably isn't much of an audience for this topic. Anyhow, if you like the idea, I'm looking forward to your comments. Having a name would be cool, by the way. I really have no idea how I should call this… stuff.

(@Those who wanted to see the next Canvas article: I'll try to finish it tomorrow. I just had to get this out of the door first. ;))

Update: Implying classes is probably not the way to go. There might be some ids for JavaScript and it also might be useful to specify that there must be an img element as child. Added dots to the spec file to reflect this detail. Well, it's more verbose, but now it covers all use cases.

Update2: Removed commas from the single line versions. They were completely pointless. Also added some comments to the example HTML and CSS to make things a bit clearer. The content of leaf nodes isn't restricted in any way.

Comments

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options