UX Design and Development course

Practical application

Sub-classing modules

When engineering modules, the name of the game is to be abstract, but there will be cases when a module's design is is altered based on context. The typical knee jerk response is to re-style the module simply based on it's parent container, whatever that may be.

For example, you may have a module called .contact. It contains a form with text fields and labels. The base UI would state that the width of the field is 75% and the label is to the left taking up the remaining 25%.

In context of the aside, the label and the text field take up 100% of the space.

As a result of these contextual differences, you may write CSS like this.

.contact label {
  width: 25%;
}

.contact input[type=text] {
  width: 75%;
}

#aside .contact .label {
  width: 100%;
}

#aside .contact input[type=text] {
  width: 100%;
}

There are a number of reasons why this is a bad idea. But mainly it is a loose dependency on a parent container that may not always be there.

Trying to be more 'future-proof' with our code, SMACSS' sub-classing principal would suggest that we define a new container for our module.

.contact {
  width: 100%;
}
.contact label {
  width: 25%;
}
.contact input[type=text] {
  width: 75%;
}

.contact-constrained label {
  width: 100%;
}
.contact-constrained input[type=text] {
  width: 100%;
}

And the HTML would look like this.

<div class="contact contact-constrained">
  <label>Name:</label>
  <input type="text"/>
</div>

This example clearly states that contact-constrained is a child module of contact, so when reading the CSS, it is clear as to the intent and use of these CSS rules.

Sub-classing confused with State rules

It is easy to look at the Sub-classing principal and say that this is simply another twist on state. After all, arguments can be made that would say that the placement of a module inside a new context is a definition of State. And I would agree.

Using the example above, here is the same solution using the constrained attribute of the sub-classed contact module and applying that as a State rule.

.contact {
  width: 100%;
}
.contact label {
  width: 25%;
}
.contact input[type=text] {
  width: 75%;
}

.contact.is-constrained label {
  width: 100%;
}
.contact.is-constrained input[type=text] {
  width: 100%;
}

And the HTML would look like this.

<div class="contact.is-constrained">
  <label>Name:</label>
  <input type="text"/>
</div>

What makes this significantly different is that is-constrained is now much more universal in application. It is no longer specifically tied to contact as in the sub-classing example.

Which is better? That is really up to you to decide. The win is knowing what each situation is doing and how it will impact the maintainability of the HTML and CSS.