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?
To change the color of an SVG in React:Import the SVG as a component. Set the fill and stroke props on the component, e.g. <MyLogo fill="black" stroke="yellow" /> .
One way to dynamically change css properties with styled components is to insert a custom prop into your React component and access said property using the dollar sign and curly braces commonly used for template literals. Our current example is testing to see if our use pointer prop is true.
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.
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
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} />)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With