How to Style React-Icons
Simply add "color" property to
Like This:
<Icon color="blue" />
I think the easiest way here would be to just pass the className
prop directly to the Icon you'd like to apply styles to. Source Code in a CodeSandbox. I've used tailwindcss classes here, but you could use your own just as easily.
import React from "react";
import "./styles.css";
import {
FaFacebookF,
FaTwitter,
FaInstagram,
FaPinterest
} from "react-icons/fa";
export default function App() {
let circleClasses = "inline-block p-7 rounded-full w-20 mx-auto";
let iconStyles = { color: "white", fontSize: "1.5em" };
return (
<div className="App grid grid-cols-2 sm:grid-cols-4 gap-2 w-3/4 mx-auto">
<h1 className="col-span-full">Icon Demo</h1>
<span style={{ background: "#3B5998" }} className={circleClasses}>
<FaFacebookF style={iconStyles} />
</span>
<span style={{ background: "#1DA1F2" }} className={circleClasses}>
<FaTwitter style={iconStyles} />
</span>
<span style={{ background: "black" }} className={circleClasses}>
<FaInstagram style={iconStyles} />
</span>
<span style={{ background: "#BD081C" }} className={circleClasses}>
<FaPinterest style={iconStyles} />
</span>
</div>
);
}
If you'd like a little more context as to how this works, we can take a dive into the source code for react-icons. If you take a look at where the IconContext is defined within react-icons, you can see the allowed props:
export interface IconContext {
color?: string;
size?: string;
className?: string;
style?: React.CSSProperties;
attr?: React.SVGAttributes<SVGElement>;
}
export const DefaultContext: IconContext = {
color: undefined,
size: undefined,
className: undefined,
style: undefined,
attr: undefined,
};
export const IconContext: React.Context<IconContext> = React.createContext && React.createContext(DefaultContext);
Indeed, you're able to pass in color, size, style, additional svg attributes, and even a className string. But, this requires that you wrap the Icon component in the context.
When you install react-icons, all of the icons are added into the node_modules directory in a format that looks like this:
// THIS FILE IS AUTO GENERATED
var GenIcon = require('../lib').GenIcon
module.exports.Fa500Px = function Fa500Px (props) {
return GenIcon({"tag":"svg","attr":{"viewBox":"0 0 448 512"},"child":[{"tag":"path","attr":{"d":"M103.3 344.3c-6.5-14.2-6.9-18.3 7.4-23.1 25.6-8 8 9.2 43.2 49.2h.3v-93.9c1.2-50.2 44-92.2 97.7-92.2 53.9 0 97.7 43.5 97.7 96.8 0 63.4-60.8 113.2-128.5 93.3-10.5-4.2-2.1-31.7 8.5-28.6 53 0 89.4-10.1 89.4-64.4 0-61-77.1-89.6-116.9-44.6-23.5 26.4-17.6 42.1-17.6 157.6 50.7 31 118.3 22 160.4-20.1 24.8-24.8 38.5-58 38.5-93 0-35.2-13.8-68.2-38.8-93.3-24.8-24.8-57.8-38.5-93.3-38.5s-68.8 13.8-93.5 38.5c-.3.3-16 16.5-21.2 23.9l-.5.6c-3.3 4.7-6.3 9.1-20.1 6.1-6.9-1.7-14.3-5.8-14.3-11.8V20c0-5 3.9-10.5 10.5-10.5h241.3c8.3 0 8.3 11.6 8.3 15.1 0 3.9 0 15.1-8.3 15.1H130.3v132.9h.3c104.2-109.8 282.8-36 282.8 108.9 0 178.1-244.8 220.3-310.1 62.8zm63.3-260.8c-.5 4.2 4.6 24.5 14.6 20.6C306 56.6 384 144.5 390.6 144.5c4.8 0 22.8-15.3 14.3-22.8-93.2-89-234.5-57-238.3-38.2zM393 414.7C283 524.6 94 475.5 61 310.5c0-12.2-30.4-7.4-28.9 3.3 24 173.4 246 256.9 381.6 121.3 6.9-7.8-12.6-28.4-20.7-20.4zM213.6 306.6c0 4 4.3 7.3 5.5 8.5 3 3 6.1 4.4 8.5 4.4 3.8 0 2.6.2 22.3-19.5 19.6 19.3 19.1 19.5 22.3 19.5 5.4 0 18.5-10.4 10.7-18.2L265.6 284l18.2-18.2c6.3-6.8-10.1-21.8-16.2-15.7L249.7 268c-18.6-18.8-18.4-19.5-21.5-19.5-5 0-18 11.7-12.4 17.3L234 284c-18.1 17.9-20.4 19.2-20.4 22.6z"}}]})(props);
};
If we take a look at the source code for GenIcon
we can get a bit more context for how this is working.
import * as React from 'react';
import { IconContext, DefaultContext } from './iconContext';
export interface IconTree {
tag: string;
attr: {[key: string]: string};
child: IconTree[];
}
function Tree2Element(tree: IconTree[]): React.ReactElement<{}>[] {
return tree && tree.map((node, i) => React.createElement(node.tag, {key: i, ...node.attr}, Tree2Element(node.child)));
}
export function GenIcon(data: IconTree) {
return (props: IconBaseProps) => (
<IconBase attr={{...data.attr}} {...props}>
{Tree2Element(data.child)}
</IconBase>
);
}
export interface IconBaseProps extends React.SVGAttributes<SVGElement> {
children?: React.ReactNode;
size?: string | number;
color?: string;
title?: string;
}
export type IconType = (props: IconBaseProps) => JSX.Element;
export function IconBase(props:IconBaseProps & { attr?: {} }): JSX.Element {
const elem = (conf: IconContext) => {
const {attr, size, title, ...svgProps} = props;
const computedSize = size || conf.size || "1em";
let className;
if (conf.className) className = conf.className;
if (props.className) className = (className ? className + ' ' : '') + props.className;
return (
<svg
stroke="currentColor"
fill="currentColor"
strokeWidth="0"
{...conf.attr}
{...attr}
{...svgProps}
className={className}
style={{ color: props.color || conf.color, ...conf.style, ...props.style}}
height={computedSize}
width={computedSize}
xmlns="http://www.w3.org/2000/svg"
>
{title && <title>{title}</title>}
{props.children}
</svg>
)
};
return IconContext !== undefined
? <IconContext.Consumer>{(conf: IconContext) => elem(conf)}</IconContext.Consumer>
: elem(DefaultContext);
}
So, GenIcon
is a function that accepts an object with an interface of IconTree which includes tag
, attr
and child
properties. We can see this in action in the generated code above. GenIcon
returns a function itself. This function accepts props as an argument which implements the IconBaseProps
interface. The IconBaseProps
interface extends React.SVGAttributes
which include className
and style
. Those are then passed as props to the IconBase
component here:
export function GenIcon(data: IconTree) {
return (props: IconBaseProps) => (
<IconBase attr={{...data.attr}} {...props}>
{Tree2Element(data.child)}
</IconBase>
);
}
To get a sense of how IconBase
actually works with respect to the IconContext
let's check out its return statement:
return IconContext !== undefined
? <IconContext.Consumer>{(conf: IconContext) => elem(conf)}</IconContext.Consumer>
: elem(DefaultContext);
Here, we can see that IconBase
will invoke a function called elem
(defined inside the body of IconBase
) either way. So, IconBase
will use the IconContext
if one is defined, wrapping the returned element in IconContext.Consumer
and calling elem
with the IconContext
. But, if IconContext
is not defined in this scope, IconBase
will use the DefaultContext
instead.
To understand how this is working, we need to look at the elem
function defined inside of IconBase
. Here's the full source again:
const elem = (conf: IconContext) => {
const {attr, size, title, ...svgProps} = props;
const computedSize = size || conf.size || "1em";
let className;
if (conf.className) className = conf.className;
if (props.className) className = (className ? className + ' ' : '') + props.className;
return (
<svg
stroke="currentColor"
fill="currentColor"
strokeWidth="0"
{...conf.attr}
{...attr}
{...svgProps}
className={className}
style={{ color: props.color || conf.color, ...conf.style, ...props.style}}
height={computedSize}
width={computedSize}
xmlns="http://www.w3.org/2000/svg"
>
{title && <title>{title}</title>}
{props.children}
</svg>
)
};
So, if you take a look at the code relating to className, you can see that we can actually add className to the Context and/or the props directly (<FaFacebook className="bg-blue" />
) and they'll actually be combined and applied to the returned svg
let className;
if (conf.className) className = conf.className;
if (props.className) className = (className ? className + ' ' : '') + props.className;
Also, the styles defined in either the Context or the props will be combined and applied to the svg
style={{ color: props.color || conf.color, ...conf.style, ...props.style}}
One thing to note here is that all of the styles and classes are being applied directly to the returned svg
element. So, in your case, you'd probably need to have a wrapping element to build out the border-radius and background color and then apply the relevant styles for color and size directly to the svg.
Use IconContext
as mentioned in the Docs.
function BlueLargeIcon() {
return (
<IconContext.Provider
value={{ color: 'blue', size: '50px' }}
>
<div>
<FaBeer />
</div>
</IconContext.Provider>
);
}
To target specific Icon Components, you can use the style
prop or use the same API (see Configurations) on the component itself:
const style = { color: "white", fontSize: "1.5em" }
<FaFacebookF style={style} />
// API
<FaFacebookF color="white" fontSize="1.5em" />
To whoever this may be helpful...
Colours of some icons cant be changed.
For example, I tried to change the colour of { GrClose }
icon by doing
<GrClose
className="icon"
style={{
position: 'absolute',
top: '20px',
right: '20px',
}}
size="50px"
color="white"
onClick={handleExit}
/>
It just didn't change, when I replaced my icon with { AiOutlineClose }
icon it worked!