Font-awesome: Gradients on FA v5 icons

Created on 13 Dec 2017  路  16Comments  路  Source: FortAwesome/Font-Awesome

I liked the fact that FA < v4 was a font so that I could apply a CSS gradient on it (ex: http://jsfiddle.net/HGxMu/220/)

screen shot 2017-12-13 at 09 49 36

.icon {
    font-size: 50px;
    background: -webkit-gradient(linear, left top, left bottom, from(#0c8), to(#333));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

I am currently using react-fontawesome which outputs SVG icons, on which I can not apply CSS gradients. Is there a way to either:

  • Apply a CSS gradient on SVG icons? _(using the React repo referenced above)_
  • Force web font usage instead of SVG icons? _(preferably using the React repo referenced above)_
feature question

Most helpful comment

For anyone still trying to achieve this effect with Font Awesome (5.0.13 as of this comment) working with JS and SVG, @ccprog 's solution above worked for me.

I had several icons that I wanted to apply a gradient to; I didn't care about hover, I just wanted it on there.

Here are the steps I followed to achieve this effect:

  1. I used Angry Tools's gradient generator to give me an svg I can define.
  2. Define an svg element in your html.
<svg width="0" height="0">
    <linearGradient id="lgrad" x1="100%" y1="100%" x2="0%" y2="0%" >
        <stop offset="0%" style="stop-color:rgb(252,207,49);stop-opacity:1" />
        <stop offset="100%" style="stop-color:rgb(245,85,85);stop-opacity:1" />
    </linearGradient>
</svg>
  1. In your stylesheet, reference the svg icons you would like to apply the gradient to. With Font Awesome 5.0.13, using js, your <i> tags are replaced with inline-svg.
.parent-div svg * {
  fill: url(#lgrad);
}

Done!

See this JSFiddle for an example.

All 16 comments

Hi,

I'm not sto much into SVG icons and javascript.

I've found this workaround on SO: https://jsfiddle.net/tagliala/f019sa7v/2/

Ref: #https://stackoverflow.com/questions/10894377/dynamically-adding-a-svg-gradient

Maybe it is possible to add a feature to use icons as clippath or add extra properties to the generated svg

@tagliala the jsfiddle example is not working on my end (MacOS / Chrome v63) but I believe that SVG gradients definitions with Javascript are a real pain. Even if I could pass a <LinearGradient> inside the <svg> and reference it in the <path> I would still have to generate it with React which I prefer to avoid :)

The cleanest -and pure CSS- way would be that I could use FA web font instead of SVG icons

I just spelled out a static solution on SO: https://stackoverflow.com/a/47801536/4996779

@ccprog Thanks, your solution works like a charm.
Still, it would have been awesome if this was a part of FA's API.

Note that this is not running with React in this demo 馃檪
My solution was to use the Font version of FA 5 (instead of the SVG version) so I could use CSS gradients on it instead of using react-fontawesome

@jebarjonet maybe I got you wrong(?!), but I'm using @ccprog's solution in react

@CanRau yep, but I really wanted to generate gradients on the fly as simply as a css line

@jebarjonet would definitely be preferable 馃憤

Having a hard time with @ccprog's solution using Vue and with webpack. I managed to get webpack to inline the svg in the url() but the gradient never displayed. Not sure what I'm doing wrong.

@r-tanner-f have you tried to preserve the reference instead of inlining it in the css like in ccprog's answer? i don't know but it might not work like this..
so you have the svg in you html, hidden with css and the css just references the id of the svg gradient

For anyone still trying to achieve this effect with Font Awesome (5.0.13 as of this comment) working with JS and SVG, @ccprog 's solution above worked for me.

I had several icons that I wanted to apply a gradient to; I didn't care about hover, I just wanted it on there.

Here are the steps I followed to achieve this effect:

  1. I used Angry Tools's gradient generator to give me an svg I can define.
  2. Define an svg element in your html.
<svg width="0" height="0">
    <linearGradient id="lgrad" x1="100%" y1="100%" x2="0%" y2="0%" >
        <stop offset="0%" style="stop-color:rgb(252,207,49);stop-opacity:1" />
        <stop offset="100%" style="stop-color:rgb(245,85,85);stop-opacity:1" />
    </linearGradient>
</svg>
  1. In your stylesheet, reference the svg icons you would like to apply the gradient to. With Font Awesome 5.0.13, using js, your <i> tags are replaced with inline-svg.
.parent-div svg * {
  fill: url(#lgrad);
}

Done!

See this JSFiddle for an example.

Thanks, @stavvie34 .This will get you into troubles inside of a loop because you can't use the same id for multiple elements. You can't use v-bind:style here because we need to have the same id in both CSS and SVG. Here an example of what I could do hoping it will help someone.
Source

<template>
    <!-- ... -->
    <Fa :icon="[ 'fab', child.icon ]" />
    <svg width="0" height="0">
        <linearGradient :id="'lgrad' + child.id" x1="100%" y1="100%" x2="0%" y2="0%">
            <stop ... />
            <stop ... />
        </linearGradient>
    </svg>
    <!-- ... -->
</template>


<script>
    export default {
        // Our prop
        // child: {
        //     id: 4,
        //     icon: 'js',
        // },
        mounted() {
            let style = document.createElement('style');
            style.type = "text/css";
            style.appendChild(document.createTextNode(''));
            this.styleNode = style.childNodes[0];
            document.head.appendChild(style);

            // The magic
            let css = '.fa-' + this.lang.icon + ' * {fill: url(#lgrad' + this.child.id + ');}';
            this.styleNode.textContent = css;
        },
        props: {
            child: Object,
        },
    }
</script>

I guess it can also be done using CSS variable but I could't find a way to get the prop inside the style scope.

@stavvie34 Amazing thanks! You saved me <3

Have you considered using a mask to accomplish this? Here's a quick codepen demoing what I;m thinking.

https://codepen.io/seanreiser/pen/QWLaZZp

Have you considered using a mask to accomplish this? Here's a quick codepen demoing what I;m thinking.

https://codepen.io/seanreiser/pen/QWLaZZp

Thank You!

Have you considered using a mask to accomplish this? Here's a quick codepen demoing what I;m thinking.

https://codepen.io/seanreiser/pen/QWLaZZp

In case it helps anyone (it took me a while to find) to get this working in angular-fontawesome you need to add a custom class:
https://github.com/FortAwesome/angular-fontawesome/issues/173#issuecomment-529375797

Was this page helpful?
1 / 5 - 1 ratings

Related issues

tinyoverflow picture tinyoverflow  路  402Comments

mitch621 picture mitch621  路  180Comments

ivafrydkova picture ivafrydkova  路  176Comments

bhubbard picture bhubbard  路  169Comments

Vilscon picture Vilscon  路  178Comments