Are icons content?

Avatar of Chris Coyier
Chris Coyier on

Edd Morgan writes in:

Obviously we all agree that the markup should contain only content, nothing ornamental. But what category do icons fall into? Are they not ornamental, therefore should not exist in the markup and be defined purely in CSS?

I’m sure we can imagine an “ornamental” icon. I’d wager it’s the most common type. It accompanies a word or phrase as part of the design. I don’t have scientific papers to cite here, but I imagine they would tell us it can make a thing more memorable or findable or distinguishable or cross-culturally relevant or whatever.

Here’s one:

Let’s build it like the quote in Ed’s question: “therefore should not exist in the markup and be defined purely in CSS”.

<button class="button button-follow">
  Follow
</button>
.button-follow {
  padding-left: 70px; /* Normal left padding plus space for icon */
  background: url(/images/icons/icon-follow.svg) no-repeat left center;
}

There is nothing in the HTML specifically about the icon. Purely ornamental. It would still be a button if that image failed to load, or even if the CSS failed to load, and it certainly doesn’t depend on any JavaScript. If we’re being perfect progressive enhancement citizens here, we’d make sure that <button> is wrapped in a <form action="/do/the/right/thing"> or made it <a href="/go/to/right/place"> to ensure it’s functionality is intact alone.

Or we could have done:

.button-follow::before {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1em;
  background: url(/images/icons/icon-follow.svg);
  background-size: cover;
}

No change to the HTML.

Icon fonts are the same kind of thing:

.button::before {
  font-family: "icon-font";
}
.button-follow::before {
  content: "\e901";
}

Although pseudo elements are read with screen readers, even when “Private Use Area” is used, which can be pretty awkward for an icon. Not to mention other issues with icon fonts.

In with the markup…

If you’re going for the best-you-can-do with icon fonts, you’re probably going to end up with at least:

<span class="icon icon-hamburger" aria-hidden="true"></span>

If not also having a wrapper element around that. So now we have something “ornamental” in the HTML. Should you feel bad about it? Nah.

I prefer SVG icon systems, which may give us markup more like:

<button class="button button-follow">
  <svg class="icon icon-follow" aria-hidden="true">
    <use xlink:href="#icon-follow" />
  </svg>
  Follow
</button>

… and that <use> probably references a <symbol> also somewhere in the HTML.

Do I feel bad about it? Nah.

And then there are icons without any supporting text:

For which we might do:

<button aria-label="Save Now" class="button button-save">
  <svg class="icon icon-save">
    <use xlink:href="#icon-save" />
  </svg>
</button>

It’s slightly different, but all in all, fairly similar. We didn’t turn the world upside down because this icon is “content” and others are “decorative”.

It’s just HTML

The trick is managing it well, not a dogmatic adherence to what “belongs there” and what doesn’t.

HTML is full of stuff. My favicon is in there, isn’t that decorative? My Google Analytics scripts are down there, that doesn’t seem like content at all. I had to use an extra <div> to give myself a relative positioning context. It harms nothing.

I’d worry more about cruft invading a database.

But I get it

It helps to have some rules. It helps to evangelize concepts that do the web more good than bad. You probably shouldn’t use an <img> for the job of a background-image.

I like the idea of considering what the implications of the markup is as you’re using it. Does it do what you need it to do? Does it hurt or help accessibility? Performance? How is the maintainability going to be?