How to import SVGs as components in Next.js, without using any library
Omogbai Atakpu
Posted on August 22, 2022
According to the official documentation, Next.js is a flexible React framework that gives you building blocks to create fast web applications. One reason for this, is due to its static generation and server-side rendering capabilities.
This means, however, that it is built on the original React Framework and uses React Components.
Now SVG stands for Scalable Vector Graphics, it is a vector graphics image format based on XML. These images are defined in a vector graphics format and stored in XML text files. This makes them lightweight and infinitely scalable, with high resolution. They can also be edited, styled and animated with CSS properties in any text editor. These are some of the major reasons why they are preferred by software developers and designers alike.
There are a few ways to use an SVG in Next.js without any library, which include:
- Serving statically with the Image component from next/image.
- Importing as an image, also using the Image component.
- Manually converting to a React Component
- To serve an SVG statically, you should save it in the "public" folder in the root directory. It can then be referenced from any component in the application by "/filename.ext" . For example:
import Image from 'next/image'
function Profile(): JSX.Element {
return <Image src="/my-icon.svg" alt="my profile" width="64" height="64" />
}
export default Profile
- Importing like your typical image file, here you can save the SVG in any folder and just import like you would import an image. However, since this was not saved in the 'public' directory, it will not be served statically by Next.js.
import githubIcon from "../assets/icons/github.svg";
const Socials: () => JSX.Element = () => {
return <Image src={githubIcon} width={16} height={16} alt="github" />
}
export default Socials;
The downside to these first two methods is that there is a limit to the available styling options when you import SVGs as images, you cannot change the colour of the image for one.
- You can convert the SVGs manually into React Components, and pass props defining the height, width, color and other CSS properties.
import React from "react";
const ArrowOut: React.FunctionComponent<React.SVGProps<SVGSVGElement>> = ({
height,
width,
className,
}) => (
<svg
height={height}
width={width}
viewBox="0 0 7 8"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M1 7L6 1M6 1H2.08696M6 1V5.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
export default ArrowOut;
'height', 'width', 'className' are all properties available to SVG Attributes which is an extended interface of React.SVGProps. These props can be passed from the parent component to style the SVG.
Let's take a look at the parent comoponent:
import Image from "next/image";
import styled from "styled-components";
import ArrowOut from "./svgs/ArrowOut";
const Socials: () => JSX.Element = () => {
return (
<Wrapper>
<a
href="https://github.com"
target="_blank"
rel="noopener noreferrer"
className="social"
>
<Image src="/github.svg" width={16} height={16} alt="github Icon" />
<p>GitHub</p>
<ArrowOut width={"10"} height={"10"} className="nav-svg" />
</a>
</Wrapper>
);
};
const Wrapper = styled.div`
.social {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
color: #fff;
margin: 2rem 0;
p {
margin: 0 1rem;
min-width: 45px;
}
.nav-svg {
stroke: #fff;
}
}
.social:hover,
.social:focus,
.social:active {
color: #0070f3;
.nav-svg {
stroke: #0070f3;
}
}
`;
export default Socials;
The Result:
Here, I imported two different SVG icons in very different ways. One as an image, that is not too styleable and the other as a React Component with a stroke colour that changes depending on the user's mouse interaction.
P.S: I'm using styled-components for styling here.
Thank you for reading this far, I hope you enjoyed it.
Do you have a better way to import SVGs into Next.js without libraries? You can share in the comments below, thanks!
Posted on August 22, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.