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?
I agree. We shouldn’t limit ourselves solely due to “best practices”, while we should strive for best practices and web standards there are cases where the lines are blurred.
background-image
is not always practical nor is<img>
but neither is necessarily bad to use. In some cases,background-image
is actually too restrictive. Icons though are both content and style, especially icon font packs. In the case of font/svg packs, use the method described as preferred by the pack and for image based packs, look for a font/svg pack instead. :)I was coming in looking for an “answer,” as I imagine most do. I would say it depends where it is used; is it inline (not in the CSS sense) with text or media content? If so, then it is content. If it is part of the apparatus of the UI then it is not. In this way; the same icon may be incorporated in a page in two different ways, one as content and another as UI ornamentation. If would seem to me to be a hack to include the same symbol for these two distinct purposes using the same method just because it is easier to do it the same way. Perhaps I am thinking like a CMS might…
What do you think about ligature icon? I have been using Material Font Icon for a while and it’s quite convenient.
Ligature is font icon that can transform word into icon. So I can write something like
<i>search</i>
to show the magnify icon.Ligatures are cool… unless you need multilanguage (or even just non-English) support ;) Then you have a problem.
@Comandeer But would it pollute screen reader? After reading the article, I started thinking that if I have
<button><i>search</i> Search</button>
, the screen reader will read “search Search”.with buttons just holding icons and using font icons, then when possible i think there should be a screen reader alternative text next to icon. just wrapped in a ‘visuallyhidden’ feels fine. or what?
I agree.
Quite often I see tick and cross icons used in comparison tables to indicate ‘includes this’, ‘does not include this’. Without hidden text or alt text it is completely inaccessible and invisible to SEO.
Any time you have non-text content (like an icon) you need to have an appropriate text alternative that serves the same or equivalent purpose.
So, looking through some of the examples above, the icon on the “follow” button can be done through CSS as the image doesn’t give any additional information to the user. It’s a decorative image that I could replace with a picture of Lord Helix and it’d still be relevant.
However, the icons used in the svg example (including the code’s use of “save”) would be best served by visibly hiding some text in a span within the button:
While the
aria-label
will give some assistive technology the right information it’s always better to use natural HTML semantics, and only using aria when HTML doesn’t offer what we need. Otherwise we run a real risk of failing WCAG 2.0’s 1.1.1.Though this next part is a design decision, I’d also suggest having the text visible in the button. Not everyone will understand what every icon the design uses is meant to suggest so it’s worth having key information, like ‘save now’, actually there on the page for everyone to see. It may not look pretty, but it’ll be easier and less frustrating for users.
Relevant here is the original definition of the element:
“The tag is used to incorporate in-line graphics (typically icons or small graphics) into an HTML document.”
Considering this, I would say an icon is semantic content, and should always be considered meaningful.
“the element” being the IMG tag:
https://www.w3.org/MarkUp/html3/img.html
IMHO:
I would suggest that the original purpose of an ‘icon’ as opposed to other forms of graphic; is content, not ornamentation. It’s purpose is to condense a concept into a small space to aid rapid recognition for the user. In environments other than web pages, icons may be the only representation of that information (albeit often with more bulky optional alternatives and fallbacks)
Certainly they can be used for ornamentation, but at heart they are an embodiment of the ‘a picture speaks a thousand words’ aphorism.
If it is something you want to change next time you change the look of your site (rebranding, design refresh, etc.), then it is probably decorative. And if you have hundreds of pages with icon’ed links scattered throughout, you’re going to want to change just one linked file, not hundreds of pages.
I think the icons are quite content – no complaints anyway. (Answer to the question as I first read it.)
On one hand I agree with David O’Rourke’s comment: that they are intended to be stand-alone, condensed content.
On the other hand, I really dislike seeing icons included directly in markup as I often do. I much prefer to trigger an icon’s appearance using a class, and leave the insertion of an icon to the css.
No:
<p><i class="my-icon"></i>text needing an icon </p>
Yes:
<p class="my-icon"> text needing an icon </p>