Musings On The Mechanics of Writing Code

Post
The words "kebab-case", "camelCase", and "PascalCase" separated by lines od alternating dashes and underscores

I’ve been using the BEM methodology for structuring HTML and naming classes for at least a decade. It has its critics, and seems to have been eclipsed in the zeitgeist by Tailwind, but it has served me well and has kept my projects very maintainable over all those years. However, once I got over the initial “ew, underscores”, I never really stopped to think about the mechanics of writing and using these class names and how, if the original authors had gone just a little further, we could have been saved from ourselves in more ways than just class naming conventions. At least, not until now.

What’s wrong with BEM? Well, it’s not particularly wrong—it has, overall, made the maintenance of website styles and developer’s lives easier—and this post is not about criticizing its naming conventions specifically. Rather, BEM taught me something important:

Be not afraid of _underscores_.

Do you remember the first time you were introduced to BEM? Do you recall the visceral reaction you had to the fact that there were underscores? In class names?! How preposterous! Everyone knows that class names are always lower-case letters and dashes only!

…But then, perhaps, you were convinced by its utility; that, despite its obvious flaws (_underscores_!?) it had a straightforward structure that was easily applied and didn’t feel like spaghetti when you needed to make changes.

Or maybe you’re a holdout, a lone wolf, a cowboy coder that doesn’t play nice with other devs or even your own future self, in which case, this blog post is probably not for you.

Well, if you’re still here anyways, I’d like to find that crack that BEM made in your sense of that’s just how it’s always been done to talk to you about something else that is unheard of in CSS:

Capital Letters.

Wait, don’t go. Please. I’m not crazy. Just hear me out, etc.

Now that we’re through the second filter, please step into this hidden door behind a bookshelf into a new world of possibilities. A place where nothing is sacred and everything is permitted. A place where we see things for what they are, and consider things from first principles. Just place your preconceived notions, traditions, and dogmas into this little box here on your way in.


Let us consider the mechanics of what you, as a developers/programmers/engineers/coders, do, every day, for 8 hours or more. Let’s set aside the non-corporeal parts for a moment—the thinking, the searching, the worrying, the sense of inferiority… What are you doing?

Well, you’re writing, typing on a keyboard. Clicking a mouse sometimes. But mostly putting characters, one after another, on the screen. And then, occasionally, using the mouse or a series of keys, selecting groups of those characters to move or delete or copy and paste.

When you interact with the characters on the screen, do you notice that they have a texture to them? That some characters are different than others, that some have a function to them that isn’t tied to a sound you can make with your mouth-apparatus. Not the meaning of characters as a concept for communication—’@’ = “at”, ‘&’ = “and”, or any number of special characters that tell the human what to think or the computer what to do—but rather the ones that affect your ability to interact with the characters themselves.

Let’s begin with ‘-‘. Ah, the humble hyphen, the literal line that joins so many parts of our class names. It’s just a single key-press away, so simple and easy to add. But it holds a dark secret.

The hyphen, in our written language, is ostensibly a word-joiner, a way to place two separate words into closer context with one another than a space would allow for. And yet…

Well, see for yourself below. If the hyphen is meant to join words together, why is it that when you double-click, or Shift-Alt-arrow, or long-press, you aren’t provided a selection of the joined words but rather just the part closest to the action you just performed? Go ahead, try it yourself:

This is what I mean by texture. Whether right or wrong, the word-joiner has one meaning to your brain and a different meaning to your text editor—it is a word-separator.

Now consider the ‘_’. The poor, sad, misunderstood underscore. It’s a strange character, isn’t it? The name “under-score” implies it is a score (a line) under… something. It was originally put onto typewriters as a way to go back to already-typed characters and add a line under them. It used to be a helper, an additive marker that expressed a meta-textual meaning—but now, as a standalone digital character, it underlines nothing.

The underscore in its new non-combinable form has come to represent a space emptier than a space. A blank to be filled. A way to further _separate_ one word from its peers to provide weight, placing the word in it’s own enigmatic void. And yet…

Well, again, see for yourself below. It is the only line character that has the same texture as any other standard word-character, desperately trying to blend in, to be useful. When placed next to or in-between words, it joins them:

That’s right, the underscore is a team-player, doing what even the ‘◌̲’ “combining low line” character doesn’t. Among all of the easily-typed keyboard symbols, it is the only one that combines:

Now, let’s bring things back to CSS and BEM. Does this class name still feel right to you?

When you attempt to select that class name, what happens? If you happen to click near the center, you’ll end up with block__my selected. Is that what you wanted? In what possible scenario would it be beneficial to grab just the last part of the block name and the first part of the element name?

Now, try this on for size:

Maybe not perfect still, but now we can grab the entire base class my_block__my_element (sans modifier, but we’ll get to those) easily.

Again, my argument here is not that BEM is bad. The authors took the the widespread convention of kebab-case class names and added to it in order for the system to be more palatable to the masses. But I think it’s time to take the actual experience of working with the code into account when we decide on conventions like this.

I believe in reducing friction, even minute moments of it, related to things I do every single day. Otherwise, they pile up and start to affect my mood, and I’d prefer that my job, even my hobbies, not put me into a funk just in time to interact with my family and friends.


Are you ready to talk about Capital Letters now?

Surely you’ve used them in your code. If your a web developer, you’ve undoubtedly used the camelCase convention in JavaScript for naming variables and functions. Some DOM APIs even transform from kebab-case in HTML to camelCase in JS, like the dataset API. So why are capital letters a taboo in CSS?

If you go searching, you’ll find some arguments that, to me, come across as ex post facto justifications for the existing convention more than a positive argument in favor of sticking to kebab-case in CSS. I don’t find arguments about being “easier to type” particularly compelling, as we all use a multitude of languages for the web that we aren’t making this case for—and most of those require more typing in general. Readability arguments fall similarly flat, as well as case-sensitivity; I don’t personally know any web developer that works only with CSS and not also HTML, JS, and likely PHP or Python or DotNet, and they handle mixed case just fine in those cases. Consistency with HTML attribute names is a bit silly if you consider that the HTML might actually be more readable if attribute values looked visually different from attribute names. Compatibility concerns with extremely old browsers actually makes me want to break the convention even more so we aren’t bound by ancient technological shortcomings—embrace the freedoms our fore-people fought for!

If you’ve managed to stick with me so far, please consider this BEM-structured class name:

Huh, would you look at that. Double-line characters are no longer necessary as separators if we utilize camelCase, and the part of the class name that is most likely going to need to be copy-pasted is easily selectable. We have actually reduced the number of keystrokes while preserving the readability of the class name!

Dare I say, we could even utilize PascalCase to indicate something else? The sky is the limit, though I do admit there is a utility to rules and limitations.

As for the modifier, well, let’s talk about modifiers.

Let’s all admit something to ourselves: the HTML class attribute is messy. For starters, it can—and often does—have multiple classes in it whose order does not actually matter. Adding and removing individual classes in JS used to be a hassle, made easier these days with classList. If you’ve been using BEM for the last decade+, you know that the modifier part just never felt right.

Modifiers are essentially arbitrary flags, and it is not often that I see the possibility of multiple simultaneous flags handled gracefully.

Consider this BEM example:

SCSS
.my-block__my-element--blue {
	color: blue;
}

.my-block__my-element--red {
  color: red;
}

What happens if both classes are applied to the same element? This isn’t a pop-quiz, it doesn’t matter if you know or if you don’t—the point is that these states are mutually exclusive, but the format of the applicator (class name) does not indicate this.

Another supremely annoying thing about modifiers is that there doesn’t seem to be a consensus on how to use them. Should the base class be included as well as the full modifier class, i.e. class="my-block__my-element my-block__my-element--my-modifier", or should it stand on it’s own and include the base class’s styles? I vote for: neither.

Instead of modifiers, I prefer to think in terms of variants. Variants give us key-value pairs to work with instead of boolean flags, so we can better control the surface area that is affected.

Being smart and clever, we know what to use instead of a class name, right? This part is the pop-quiz, because I’m sure this isn’t breaking news either: data attributes.

Data attributes, i.e. data-variant="blue", make mutually exclusive variant styles possible. I can’t have both the blue and red variants applied simultaneously, because data-variant can only have one value.

SCSS
.myComponent {
	
	&[data-variant="blue"] {
		color: blue;
	}
	
	&[data-variant="red"] {
		color: red;
	}
}

While data attributes actually can also act as flags with a selector like [data-blue] or [data-red] that doesn’t check for a value, I don’t recommend crossing the streams. These are just class names one step removed. Don’t do that to yourself.


We’ve strayed a bit too far from talking purely about the mechanics of writing into the territory of criticizing BEM. That methodology completely changed the way I think about CSS organization and has helped keep projects maintainable for years as other frameworks and libraries have come and gone. But the awkwardness of the structure of its naming conventions has been wearing on me for all that time. It’s almost as if I’ve come full-circle on my reaction to BEM; instead of “ew, underscores?” it’s now “ew, two underscores?”.

No comments on Musings On The Mechanics of Writing Code

Broadcast a message

This site uses Akismet to reduce spam. Learn how your comment data is processed.