(Superseded) Add a custom fontawesome icon and color to your tag

:information_source: The easiest way to do this is to use the new theme component: Tag Icons

UPDATE: These instructions have been updated since SVG images are now used on Discourse rather than Font Awesome icons.

I’ve styled my tags with colours and SVG images:

SVG icon images can be freely downloaded from sites such as https://thenounproject.com/

Example CSS (thanks @pmusaraj for the below):

@import "common/foundation/mixins";

[data-tag-name="tag1"]:link,
[data-tag-name="tag1"]:visited,
[data-tag-name="tag1"].bullet:before {
    color: red;
}

[data-tag-name="tag1"].bullet:before { 
    background: transparent;
    content: svg-uri('<svg fill="red" xmlns="http://www.w3.org/2000/svg" width="8px" height="8px" viewBox="0 0 512 512"><path d="M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"></path></svg>'); 
    vertical-align:baseline;
}

Note: ensure you add the color to the SVG fill property.

This is not an ideal solution, it makes the CSS less readable. But on the other hand, it’s efficient (no additional requests) and independent (the whole icon is in the SVG path).

54 Likes

And for image bullets:

@mixin withImage ($col, $image) {
    &.bullet {
        background-image: url($image);
        background-size: 16px 16px;
        background-repeat: no-repeat;
        opacity: 0.4;
        padding: 1px 0 1px 18px;
    }
    &:link, &:visited {
        color: $col;
    }
    &.bullet::before {
        display: none;
    }
}

[data-tag-name="trump"] {
    @include withImage(#823755, 'https://se23.life/uploads/default/original/2X/b/b784a22693d213ec5936051da30756c3765b06a1.png');
}

12 Likes

Very nice! I am assuming that these go into the Embedded CSS?

I put mine in “Common” CSS - unsure if that is best practice, mind you.

4 Likes

This is fantastic, Chris. Thanks.

I am using a font awesome graduation cap icon to indicated tags for assigning particular authors to generate a blog:

13%20PM

So, you see the graduation cap bullet point and you know the name next to it is for the person assigned to blogging that topic.

2 Likes

A non-coder question for clarification. Is this code for if you want to use an uploaded image (link) as the icon for a particular tag? I want to use an image I’ve uploaded for a particular tag due to fontawesome not having an appropriate image for a particular tag I am using.

Yes. You’ll need to substitute your image URL in here:

3 Likes

Just did it. That example icon you used cracked me up. A v. tiny head in a humungous screen. Thank you so much for sharing this code.

2 Likes

FYI: we had to change tag classes due to some CSS collision issues so I’m updating the references in the topic above.

Now instead of a class it’s a data attribute.

[data-tag-name="yourtagname"] {
  // styles here
}
8 Likes

Thanks for explaining the change and updating the examples in this topic.

I had quite a lot of CSS to update so I used the following replacement regexp in IntelliJ:

\.tag-([a-zA-Z0-9\-]*)
[data-tag-name="$1"]
4 Likes

Pinging this as i remembered that you will update discourse to fontawesome 5. Is the CSS here supposed to change?

2 Likes

Thanks for bumping this, with FontAwesome 5 the technique in the OP will no longer work. Our FA5 implementation switches from using an icon font to SVGs, so the content: "\f0a1" will no longer display an icon, the font where that character points will no longer be included.

Here is a way to do the same thing with SVGs once FA5 is in core:

@import "common/foundation/mixins";

[data-tag-name="tag1"]:link,
[data-tag-name="tag1"]:visited,
[data-tag-name="tag1"].bullet:before {
    color: red;
}

[data-tag-name="tag1"].bullet:before { 
    background: transparent;
    content: svg-uri('<svg fill="red" xmlns="http://www.w3.org/2000/svg" width="8px" height="8px" viewBox="0 0 512 512"><path d="M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"></path></svg>'); 
    vertical-align:baseline;
}

A few notes about this:

/// Helper function to easily use an SVG inline in CSS
/// without encoding it to base64, saving bytes.
/// It also helps with browser support, especially for IE11.
///
/// @author Jakob Eriksen
/// @link http://codepen.io/jakob-e/pen/doMoML
/// @param {String} $svg - SVG image to encode
/// @return {String} - Encoded SVG data uri
@function svg-uri($svg) {
  $encoded: "";
  $slice: 2000;
  $index: 0;
  $loops: ceil(str-length($svg) / $slice);

  @for $i from 1 through $loops {
    $chunk: str-slice($svg, $index, $index + $slice - 1);
    $chunk: str-replace($chunk, '"', "'");
    $chunk: str-replace($chunk, "<", "%3C");
    $chunk: str-replace($chunk, ">", "%3E");
    $chunk: str-replace($chunk, "&", "%26");
    $chunk: str-replace($chunk, "#", "%23");
    $encoded: #{$encoded}#{$chunk};
    $index: $index + $slice;
  }

  @return url("data:image/svg+xml;charset=utf8,#{$encoded}");
}

/// Replace `$search` with `$replace` in `$string`
/// @author Hugo Giraudel
/// @link http://sassmeister.com/gist/1b4f2da5527830088e4d
/// @param {String} $string - Initial string
/// @param {String} $search - Substring to replace
/// @param {String} $replace ('') - New value
/// @return {String} - Updated string
@function str-replace($string, $search, $replace: "") {
  $index: str-index($string, $search);

  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace +
      str-replace(
        str-slice($string, $index + str-length($search)),
        $search,
        $replace
      );
  }

  @return $string;
}

[data-tag-name="tag1"]:link,
[data-tag-name="tag1"]:visited,
[data-tag-name="tag1"].bullet:before {
    color: red;
}

[data-tag-name="tag1"].bullet:before { 
    background: transparent;
    content: svg-uri('<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="8px" height="8px" viewBox="0 0 512 512"><path d="M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"></path></svg>'); 
    vertical-align:baseline;
}

This is not an ideal solution, it makes the CSS less readable. But on the other hand, it’s efficient (no additional requests) and independent (the whole icon is in the SVG path).

13 Likes

Thanks @pmusaraj for this detailed explanation. That’s really helpful :+1:

In my case there are dozens of icons and quite a lot of CSS to change. Is is possible for me to restore the fontawesome icon font on my forum? At least, as a temporary measure while I work on the SVG equivalent?

You could @import the FontAwesome CSS file from a CDN temporarily, and see what happens. I have not tried this, but it might work. It’s possible it might also introduce duplicate icons in places where you’re overriding a previous :before.

2 Likes

Thanks - I’ll give this a try

@ChrisBeach please, can you update the OP with the new code when you have time?
See Custom CSS different on dekstop and mobile :wink:

Thanks

4 Likes

@dax, unfortunately I seem unable to edit the OP.

2 Likes

I made it a wiki - you should be able to edit it now.

6 Likes

Done.

@pmusaraj - is svg-uri() now available in core? If so I’ll delete the redundant code from the OP.

Yes, svg-uri() is now in core. That said, I would prefer to add icons to tags in a more elegant way. I recently wrote a theme component that adds icons to categories; something similar for tags would be ideal. I’ll take a look at this shortly.

10 Likes