A partial archive of discourse.wicg.io as of Saturday February 24, 2024.

CSS isn’t used for icons - it should be


This is already an issue on GitHub but I was told to gather an more open discussion here. Copy the original text below:

I’m developing a new front-end for the IoT OS “ESP Easy” and we really don’t want to have any dependencies. Thus I have created my own framework called “guiEasy” which consists of a plain CSS file. The idea is to have everything modular and thus all element styling depend on global and element based variables to manipulate the GUI.

Font Awesome has become defacto standard for icons which seems a bit weird since we should have a standard for icons and not rely on third party aid. Font based icons are a hack, not a standard in my opinion. So… to get rid of static (but often nice looking) font based icons and hard to tweak SVG based icons I stumbled upon this page: https://cssicon.space/#/

It is a hackish way of creating icons using pure CSS and I have been starting to create icons this way. Not that I suggest all should create icons this way but as a proof of concept. You may see how this is done here: https://grovkillen.com/guieasy

My idea is that CSS should be the main source of styling icons as well as everything else. That way the icons can adapt to not only color but form and style and even be animated. If you mess around with the radius on the above site (main tab, radius=1 for very round style, radius=2…7 for semi round, radius=100 for sharp style) and you’ll see that the icons themselves adapt to this style.

So my suggestion:

<icon class=...>
<icon data-attribute=...>
... etc.

The above HTML element would be able to be styled using layers:

.classname {
  icon-background: iconbg;
  icon-layer-0: shadow;
  icon-layer-1: graphics;
  icon-layer-n: ....
  icon-badge: roundbadge;

  icon-background-color: #...;
  icon-layer-n-color: #...;
  icon-badge-color: #...;

  icon-background-fill-color: #...;
  icon-layer-n-fill-color: #...;
  icon-badge-fill-color: #...;

  icon-background-transform: XXXX;
  icon-layer-n-transform: XXXX;
  icon-badge-transform: XXXX;

  ... Adding more icon related CSS stuff here...

@icon-layer iconbg {
  ...CSS stuff
  ...SVG paths
@icon-layer roundbadge {
  contents: attr(data-badge-number);
  ...CSS stuff
  ...SVG paths

The background is ALWAYS on bottom The badge is ALWAYS on top

Badge = a notifying small element which could be used to show numbers of unread messages etc. It may fetch it’s value from a set attribute.

You can now combine multiple “keyframes” which are defined in the @icon-layer part of the CSS to create icons. The badge can be set at one place and not on individual icons, the background could be round or square depending on the radius of the background element and so on. Screen readers would be helped upon reading an icon element and read out “icon” + the title of the element.

The icon element is by design always NxN in size and will (if not override) obey the size (height) of the font scope it’s part of. Internal origo (for it’s own shapes etc) should be defined by default from 0,0=center-center and then you can place the different layers in arrays X&Y…-X&-Y and orthogonality (R&Angle). Overflow is by design hidden within the NxN. By design you’re not allowed to have more than one closed figure per icon-layer. The closed area is colored by the ...fill-color attribute and the boundary is colored by the ...-color attribute. I.e. an open figure will not be affected by setting the fill-color attribute. icon-layer will not place the shape/figure, by default it will be placed symmetrical in the origo of the icon. To move it you need to use the ...-transform attribute. Arrays of a layer is done this way as well.


PS. a battery icon (as an example) doesn’t have to have multiple icons to represent charging, battery level etc. it could just adjust a attribute value or add/remove a class etc. As an example you may add the class “one, two, three, four, or five” to have the wifi signal strength icon on my above linked site to have the bars filled in. Change the attribute for signal strength and you’ll see that the dBm is updated in the icon as well.


Why do you consider font-based icons a hack?


Well, they are :slight_smile: Consider a screen reader, how should it interpret that “text”? It’s not like all the developers of font based icons use the same font values for the same type of symbol. A proper HTML element is how it should be.


Icons are always a challenge for accessibility. Even when using regular images or SVG, you need to tell screen readers how to describe the icon.

Can you clarify what are the benefits of your proposal over SVG? Maybe provide some example to illustrate the shortcomings of SVG that your proposal addresses.


My suggestion is that given the element screen readers know that the element they’ve reached is in fact an icon. <span> or <i> which is currently the used standard is not intended to be used by icons.

In regards of the <svg> element that is already an established standard I would like to point out that the svg is a generic graphical element (and good at it) but used in broad way and thus hard to use for screen readers, add to a CSS framework and combine layers etc. The icon element is by design cutting off overflow and you can always be sure that it’s a NxN size and adapted to the font size.

My element can be filled with a general background which can be defined in one @icon-layer and then applied to all icons. Also it’s possible to share layers between icons. Make icons animated upon hover etc. And they will also be possible to tweak using CSS variables.

I could give it a try giving “real examples” but I’m not (at this point) sure how to best present my idea. I’ll get back to you on that.

Thanks for your time! :slight_smile:


Generally, I support the idea of making it easier and less hacky to embed and style icons into websites. But before starting to talk about the solutions, we should first clarify the issues with the current ways icons can be embedded.

  1. Font-based icons / icon fonts

    There’s a great article about why icon fonts are often considered hacks written by Tyler Sticka back in 2015.

    • Accessibility issues
    • Error prone (because of relying on specific Unicode characters referring to specific icons)
    • Poor fallbacks
  2. SVG icons

  3. Pixel image icons

    • No styling possible
    • Alignment within text difficult
    • Poor display on zooming or high dpi displays

Regarding the suggested solution, it actually consists of several parts:

  1. A new HTML element with the semantic meaning of an icon
  2. An at-rule to define layers. (There were multiple discussions about this in the past, e.g. one related to the z-index property.)
  3. New CSS properties specific to icon layout

I suggest to split them up into individual threads so they can be discussed separately.



Thanks for this. I have now created these three topics:

[icon] Semantic HTML element HTML

[icon] CSS properties relating suggested semantic HTML element CSS

[icon] Layers @rule to create icons based on multiple “keyframes” CSS


Idea that just popped up: this element should be possible to populate favicon if desired.