Using Styled Components to change the color of an SVG's stroke
Solution 1
So I looked into this. Turns out you cannot CSS style an SVG image you're loading using the <img>
tag.
What I've done is this:
I inlined my SVG like this:
<BurgerImageStyle x="0px" y="0px" viewBox="0 0 38 28.4">
<line x1="0" y1="1" x2="38" y2="1"/>
<line x1="0" y1="14.2" x2="38" y2="14.2"/>
<line x1="0" y1="27.4" x2="38" y2="27.4"/>
</BurgerImageStyle>
Then I used Styled Components to style BurgerImageStyle
:
const BurgerImageStyle = styled.svg`
line {
stroke: black;
}
&:hover {
line {
stroke: purple;
}
}
`;
This worked.
Solution 2
If you are looking to avoid writing separate components or copying your raw SVG file, consider react-inlinesvg
;
https://github.com/gilbarbara/react-inlinesvg
import React from "react";
import styled from "styled-components";
import SVG from "react-inlinesvg";
import radio from "./radio.svg";
interface SVGProps {
color: string;
}
const StyledSVG = styled(SVG)<SVGProps>`
width: 24px;
height: 24px;
& path {
fill: ${({ color }) => color};
}
`;
export default function App() {
const color = "#007bff";
return <StyledSVG color={color} src={radio} />;
}
Code Sandbox: https://codesandbox.io/s/stack-56692784-styling-svgs-iz3dc?file=/src/App.tsx:0-414
Solution 3
If you want to have some styling shared across multiple SVGs and you don't want to have an extra dependency on react-inlinesvg
you can use this thing instead:
In src
prop it accepts SVG React component
import styled from 'styled-components';
import React, { FC, memo } from 'react';
type StyledIconProps = {
checked?: boolean;
};
const StyledIconWrapper = styled.div<StyledIconProps>`
& svg {
color: ${(p) => p.checked ? '#8761DB' : '#A1AAB9'};
transition: 0.1s color ease-out;
}
`;
export const StyledIcon = memo((props: StyledIconProps & { src: FC }) => {
const { src, ...rest } = props;
const Icon = src;
return (
<StyledIconWrapper {...rest}>
<Icon/>
</StyledIconWrapper>
);
});
And then you can use it like:
import { StyledIcon } from 'src/StyledIcon';
import { ReactComponent as Icon } from 'assets/icon.svg';
const A = () => (<StyledIcon src={Icon} checked={false} />)
Related videos on Youtube
JasonGenX
My passion is solving real world problems with code. Always learning new languages/frameworks - hence why I'm here.
Updated on June 04, 2022Comments
-
JasonGenX almost 2 years
I have an SVG I'm using as an
<img>
tag. Using Styled Components I am trying to get to a point where I change the stroke color upon hover.I imported the SVG:
import BurgerOpenSvg from '../../images/burger_open.svg';
I Created a Styled Components for it:
const BurgerImageStyle = styled.img` &:hover { .st0 { stroke: red; } } `;
And I use it:
<BurgerImageStyle alt="my-burger" src={BurgerOpenSvg}/>
The result is, my SVG is displayed correctly, but no color change upon hovering.
Source for the SVG I use:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 38 28.4" style="enable-background:new 0 0 38 28.4;" xml:space="preserve"> <style type="text/css"> .st0{fill:none;stroke:#221f1f;stroke-width:2;stroke-miterlimit:10;} </style> <g> <g id="XMLID_7_"> <line class="st0" x1="0" y1="1" x2="38" y2="1"/> </g> <g id="XMLID_6_"> <line class="st0" x1="0" y1="14.2" x2="38" y2="14.2"/> </g> <g id="XMLID_5_"> <line class="st0" x1="0" y1="27.4" x2="38" y2="27.4"/> </g> </g> </svg>
The SVG Renders as follows:
Is it even possible to update the class on an SVG loaded in an
<img>
tag? or must it be inline<svg>
tag?