Coding CSS for Context
Dave Rupert recently tweeted asking a question that I see quite often:
.some-context .thing { /* special rules and overrides */ }
Does that go in thing.css or some-context.css?
Then, Harry Roberts discussed this concept further in his article of CSS Code Smells Revisited.
Harry uses a practical example of .thing
being a .button
. (Well, actually, a .btn
but whatever. And yes, I just “well, actuallied” myself. It’s preemptive mansplaining.)
You’ll have the standard button that appears throughout your application. And then you have this variation in modal dialogs.
Instinctively, we start writing .modal .button
. Hence, Dave’s question of where to put this particular bit of code. It’s interesting to note that the results of Dave’s survey indicated that a slim majority of people prefer that this bit of code live in with the modal CSS and not with the button CSS.
Harry indicated that it should live with the button CSS. And I agree with him. We’re styling a button! It should be in with the buttons.
But then Harry seemed to contradict himself by saying that the button class name should be renamed to .modal__btn
, making it a part of the modal component. In doing so, this bit of CSS should now live in with the modal CSS. (And based on naming convention, I would agree with him.)
One thing you have to worry about is components becoming too complex. Yes, the modal has a button. It could also have inputs and headings and all sorts of things. Over my career, I’ve noticed useful boundaries and tend not to create components with deep hierarchies.
Identifying The Thing
Going back to our thing that we’re trying to style: the button. Yes, right now, we’re styling a button in a modal dialog. Is this the only place that this exists? Right now, quite possibly. Will it always be the only place it exists? If your project is constantly in flux, then not likely.
Here’s what’s important:
- We want to identify that this is a variation on our button.
- We want to indicate the purpose of this button style.
- We want to avoid tying the code to a particular context that could change.
Going with .button--modal
, for example, now identifies it as a variation. But fails on the other two points: It indicates its context and doesn’t say what it’s trying to do other than be in a particular place on the page.
So, why is the button in the modal different than regular buttons? (If you’re the designer, ask yourself this. If you’re not the designer, ask them this.) You might get something like, “It needs to be green to draw attention to the fact that it’s a primary action.” Or maybe something like, “the button is smaller because we don’t have as much room.”
This helps you come up with a name like .button--primary
or .button--compact
.
Either of those names satisfy the three points I mentioned above.
- It identifies itself as a variation using the BEM double hyphen.
- It indicates its purpose through the variation name.
- It hasn’t tied itself to a specific context.
That last point, to me, is the most important. As a designer, I might end up using these styles on a new page that hasn’t been thought up yet. I might want to use a primary button style on a form that isn’t in a modal dialog. I might want to use a compact button in a sidebar where I don’t have a lot of room.
And as Harry also mentioned, by keeping all our button styles in one place, we have the ability to see patterns emerge across an entire project.
Three months down the line, do we suddenly find ourselves with 30 button styles and need to reduce the complexity of our UI? That can be harder to do if button styles are strewn throughout the codebase, hidden within other contexts.