Chris Bateman

Blog

CSS Naming Patterns Compared

A few weeks ago, I heard about AMCSS, a newly formalized alternative to using classes for CSS hooks. I was pretty hesitant at first – and still am to some extent – if nothing else because it just feels odd.

The goal of this post is to briefly compare the most common methods of organizing CSS module classes – and see how AMCSS compares.

Multi-Class

<span class="badge">A Badge</span>
<span class="badge badge--large">A Large Badge</span>
.badge {
    display: inline-block;
    background: #555;
    color: #eee;
}
.badge--large {
    font-size: 1.5em;
}
 
/* overriding */
.darkheader .badge {
    background: #777;
    color: #eee;
}
  • Good: overrides are easy.
  • Bad: HTML can feel a bit repetitive.

Single-Class

<span class="badge">A Badge</span>
<span class="badge--large">A Large Badge</span>
.badge,
.badge--large {
    display: inline-block;
    background: #555;
    color: #eee;
}
.badge--large {
    font-size: 1.5em;
}
 
/* overriding */
.darkheader .badge,
.darkheader .badge--large {
    background: #777;
    color: #eee;
}
  • Good: HTML is shorter.
  • Bad: If you need more than one modifier you’re back to multi-class anyhow.
  • Bad: Overrides are messy because they have to be updated when a new modifier is added. Unless…

Single-Class with Single Selector: |=

[class|="badge"] {
    display: inline-block;
    background: #555;
    color: #eee;
}
  • You don’t have to list every modifier for the base styles.
  • Bad: Can’t add any extra classes to the base class (class=”badge extra” will fail). *dealbreaker*

Single-Class with Single Selector: ^=

[class^="badge"] {
    display: inline-block;
    background: #555;
    color: #eee;
}
  • You don’t have to list every modifier for the base styles.
  • Bad: It always must be the first class.
  • Bad: You can’t have any other classes that begin with your base class (it would also match class=”badgeAlt”).

So far

So far, for me it’s pretty clear that the multi-class pattern comes out on top. Yeah, the HTML is a bit longer – but that’s better than the downsides of the alternatives.

AMCSS

When compared to the previous options, Attribute Module CSS gets you the best of all worlds.

<span css-badge>A Badge</span>
<span css-badge="large">A Large Badge</span>
[css-badge] {
    display: inline-block;
    background: #555;
    color: #eee;
}
[css-badge~="large"] {
    font-size: 1.5em;
}

/* overriding */
.darkheader [css-badge] {
    background: #aaa;
    color: #444;
}

The HTML is short, overrides are straightforward, and there aren’t any caveats about how the “classes” can ordered or mixed with others.

However – there’s one drawback you might not notice at first: JavaScript. Modern browsers have classList, and everyone’s familiar with jQuery’s methods for managing classes. You can’t use any of it to toggle attribute values. The spec authors suggest that this is a feature, and that you might try regular classes for state changes.

But if you don’t like the idea of adding regular classes back into the mix, it’s easy enough to make a JS utility for manipulating attributes in the same way: Here’s a gist that should do the trick.

Perspective

Two years ago, Linds Redding passed away, about one year after being diagnosed with inoperable esophageal cancer. He was an art director and motion graphics designer in the advertising industry. He was 52 years old. I didn’t know him, but I recently read some of his blog, including a post entitled, A Short Lesson in Perspective. It’s worth a read – especially if you work in a "creative" job. These are the words of a man who knew his time was up.

It turns out I didn’t actually like my old life nearly as much as I thought I did. I know this now because I occasionally catch up with my old colleagues and work-mates. They fall over each other to enthusiastically show me the latest project they’re working on. Ask my opinion. Proudly show off their technical prowess (which is not inconsiderable). I find myself glazing over but politely listen as they brag about who’s had the least sleep and the most takaway food. “I haven’t seen my wife since January, I can’t feel my legs any more and I think I have scurvy but another three weeks and we’ll be done. It’s got to be done by then. The client’s going on holiday. What do I think?”

What do I think?

I think you’re all f-----g mad. Deranged. So disengaged from reality it’s not even funny. It’s a f-----g TV commercial. Nobody gives a shit.

The other thing I did, I now discover, was to convince myself that there was nothing else, absolutely nothing, I would rather be doing. That I had found my true calling in life, and that I was unbelievably lucky to be getting paid – most of the time – for something that I was passionate about, and would probably be doing in some form or other anyway.

Countless late nights and weekends, holidays, birthdays, school recitals and anniversary dinners were willingly sacrificed at the altar of some intangible but infinitely worthy higher cause. It would all be worth it in the long run.

So was it worth it?

Well of course not. It turns out it was just advertising. There was no higher calling. No ultimate prize. Just a lot of faded, yellowing newsprint, and old video cassettes in an obsolete format I can’t even play any more even if I was interested. Oh yes, and a lot of framed certificates and little gold statuettes. A shitload of empty Prozac boxes, wine bottles, a lot of grey hair and a tumor of indeterminate dimensions.

…Oh. And if you’re reading this while sitting in some darkened studio or edit suite agonizing over whether housewife A should pick up the soap powder with her left hand or her right, do yourself a favour. Power down. Lock up and go home and kiss your wife and kids.

No comments yet. Get it off your chest.

How Double-Equals Works in JavaScript

tl;dr — Don’t use double-equals!

When asked about the difference between double and triple-equals, a lot of JS developers will tell you that == compares values and === compares values and types. In other words, 1 == "1" will be true, and 1 === "1" will be false.

That explanation is somewhat true, but it belies a much more complicated reality.

Some of the confusion comes from thinking that == is somehow related to truthiness, which is all about how variables get coerced into booleans — which happens in an if statement like this:

if (something) {

In that case — 0, "" the empty string, null, undefined, and NaN will all return false. Non-zero numbers, Non-empty strings, arrays and objects (empty or not) will all return true. Most devs have a pretty good handle on this.

But… does that mean that a non-zero number, or all non-empty strings will double-equal true? This is where things can get confusing.

if ('a') {           // true
if ('a' == true) {   // false
if ('a' == false) {  // false

if (2) {             // true
if (2 == true) {     // false
if (1 == true) {     // true

Hopefully that makes it clear that truthiness has nothing to do with ==.

Remember: truthiness is about coercion into booleans. With double-equals, nothing will ever get coerced into a boolean. So what’s really going on?

The answer is the Abstract Equality Comparison Algorithm. If the two types differ, JS follows a particular process for converting them into the same type, so that it can compare them. If types don’t match somewhere along the way — the endgame will be numbers.

  • First, booleans are converted to numbers. True becomes 1 and false becomes 0.
  • Next, objects will be turned into strings using .toString() (unless you modified .valueOf() to return a primitive). So [1] becomes "1", [1,2] becomes "1,2", and both {...} and [{...}] become "[object Object]".
  • If a string and a number are left, the string is converted to a number (so any string with non-number characters will become NaN — which, by the way, never ever equals anything, including itself).
  • null and undefined equal themselves and each other.

That’s the gist of it, but you can check out the spec for more details.

So — do you need to remember all these rules? Absolutely not. As Felix Geisendörfer puts it, “Programming is not about remembering stupid rules. Use the triple equality operator as it will work just as expected.”

That’s why most all JS style guides recommend using only ===. Some allow for an exception when checking for null or undefined (by using “== null“). But some folks would argue against even that.

Mozilla, DRM, and Pragmatism

Mozilla has taken a bit of a beating lately — more than their fair share, for sure. The latest trouble has been over their decision to add the Encrypted Media Extensions (EME) standard to Firefox. EME basically allows for native browser implementations of Digital Rights Management (DRM) systems.

There was a lot of unhappiness about this, which is understandable. I’m opposed to DRM — not because I’m in favor of pirating content — but because DRM has nothing to do with piracy and everything to do with leverage over creators of playback devices.

I shared an article on Twitter which made the case that there should have been a bigger outcry when Google and Microsoft implemented EME:

Google and Microsoft and Apple have already started implementing EME, over the complaints of precisely nobody…

I like the warm fuzzy feeling I get from knowing that Mozilla are out there doing the right thing… Firefox should stand on principle here and refuse to play DRMed videos – but of course I’m not going to stop using DRMed video, I’ll just use Safari for that. The warm fuzzy feeling is jolly nice, but it’s not enough to actually keep the Mozilla organisation running…

Mozilla helps keep the web open for us, but in return we have to help keep the web open for Mozilla. And we aren’t.

However, I was immediately seized upon by a dissenter who claimed that Mozilla was losing their core values and would lose their core user base because of it.

First off — switching away from Firefox because of DRM doesn’t add up. “I’ve been going out of my way to use the browser fighting against DRM, but now I might as well switch to Chrome, which embraced and promoted DRM from the start. Because DRM is the only aspect of the open web that Mozilla ever has or will stand for.” Yeah, that makes tons of sense.

But here’s the most important part — while there certainly are lots of people who use Firefox because of their committment to the open web, the average Firefox user has no idea about any of this. Half a billion people use Firefox (according to Mozilla); and for the vast majority of them, without EME, all they would know is that their Netflix doesn’t work in Firefox.

So it’s a tough situation for Mozilla. They’re clearly unhappy about adding EME, but they’re doing it because they believe that they simply can’t survive without it. And I agree. Mozilla hasn’t lost their core values, and I believe they still have much to offer the open web. But they can’t do any good at all if they don’t have people using their browser.

Tony Kushner penned the following words (inspried by Abraham Lincoln):

A compass, I learned when I was surveying, it’ll point you true north from where you’re standing, but it’s got no advice about the swamps and deserts and chasms that you’ll encounter along the way. If in pursuit of your destination, you plunge ahead, heedless of obstacles, and achieve nothing more than to sink in a swamp… what’s the use of knowing true north?

No comments yet. Now's your chance.

Old Particle App

Access it here: Bright Lights.

A couple years ago, I built an app for the iOS app store using HTML5 Canvas. It was there for a year, and made a very modest profit, but it was really too silly and simple to be worth keeping there.

I’ve been meaning to put it on GitHub for a while, and I finally got around to it, so here you go. I made a number of modifications to make it suitable for use on the open web, and it’s also hosted here now. It’s a couple minutes worth of fun for kids, you can add it to your home screen, and it works offline.

With an app like this, there’s just one notable drawback to having a “home screen app” instead of a native app – you can’t prevent the notification and control centers from popping up when your finger goes past the top or bottom of the screen. Oh well. Also, you can’t remove the status bar, though that’s not a huge deal.