How to use svg in react
How to use svg in react
Еще один способ использовать SVG в React. На этот раз удобный
Суперсила SVG
Инлайнинг
Вставка SVG непосредственно в html это одновременно и самая простая и самая мощная с точки зрения кастомизации и манипуляции изображением техника.
Такое изображение можно стилизовать через css, менять практически любое свойство и атрибут, даже анимировать его отдельные части. Но здесь есть ряд существенных ограничений:
Если изображение большое, вся страница будет загружаться дольше
Использование этой техники в js-фреймворках, даже с такими крайне мощными инструментами, как SVGR, сильно увеличивает размер js-бандла.
Спрайт символов
А если вы, как и Microsoft, не поддерживаете IE11, спрайт символов можно загружать по HTTP.
Хорошие новости в том, что каскад продолжает работать, можно менять атрибуты fill и использовать currentColor в любом свойстве. Для большинства кейсов с иконками этого более чем достаточно:
Компромисс
Добавит их в символьный спрайт
Первым о таком решении задумался Chris Coyier еще в 2015 году, но оно так и не было оформлено и ждало своего дня. Сегодня этот день настал.
Handy SVG
И использовать в React :
Или в любом другом проекте с ванильным javascript:
Никаких проблем со стилизацией не возникнет:
На страницу будут загружаться только необходимые изображения, вы сможете их закешировать, а в SPA-приложениях запросы конечно же не будут отправляться дважды. Ваш спрайт не будет разрастаться и вы вообще не будете задумываться о его существовании.
Пул-реквесты приветствуются и я буду рад любому фидбеку.
How to Use SVG Icons in React with React Icons and Font Awesome
Icons are a way to visually communicate concepts and meaning without the use of words. This could be for categorization, an action, or even a warning.
How can we add icons using SVG to our React apps to improve our visual communication?
What is SVG?
SVG stands for Scalable Vector Graphics. It’s a file format based on a markup language similar to XML that allows developers and designers to create vector-based images using path definitions.
What makes SVG great for the web?
SVG was born for the web. It’s an open standard that was created by W3C to provide a better way to add images to the web. If you open an SVG file on your computer, you might be surprised to find that it’s all code!
This plays a part in the small file size. Typically when using SVG, you can take advantage of its smaller size compared to larger image files that might be required to deliver the same high resolution.
Additionally, since we’re defining SVG as paths, they can scale as large or as small as we want. This makes them extra flexible for web usage, especially when making experiences responsive.
What are we going to create?
We’re first going to walk through using a package called react-icons that will allow us to easily import icons from popular icon sets like Font Awesome right into our app.
We’ll also take a look at how we can manually add SVG files right into our app by copying the code of an SVG file right into a new component.
Part 0: Creating a React app
For this walkthrough, you can use any React framework you’d like whether that’s Create React App or Next.js. You can even use an existing project.
Because we don’t need anything special to add our icons, I’m going to use create-react-app.
To get started with create-react-app, you can create a new project using the following command in your terminal:
Once you have your new app or your existing app, we should be ready to go!
New Create React App
Part 1: Adding SVG icons with react-icons
Adding react-icons to your project
To get started with react-icons, we want to install it in our project.
Inside of your project, run the following command:
Once it’s completed, we should be ready to use it in our project.
Selecting icons for a project
One of the cool things about react-icons is the extensive library they make available within the single package.
Not only do we have Font Awesome immediately available, we have GitHub’s Octicons, Heroicons, Material Design Icons, and a whole bunch more.
When choosing icons, you pretty much have the ability to use any icon you want at any time. That said, I would recommend trying to keep a consistent look and feel with your icons.
If you primarily use Font Awesome for your website, it might look a bit strange and inconsistent if you were to start adding Flat Color Icons to the mix. You ultimately want to provide an experience that people will be able to easily identify the patterns that you create.
Using react-icons in your project
Once you’ve found the icons you want to use, we can now add them to our project.
react-icons’s website makes it easy for us to look up the name of the icon we want to use to import to our project.
If we wanted to use the Font Awesome rocket icon, we can navigate to Font Awesome in the sidebar, search the page for “rocket” (CMD+F or CTRL+F), and then click the icon which will copy its name to your clipboard.
Font Awesome rocket icon
We could also search for “rocket” in the search form at the top left of the page, which shows us the result “rocket” throughout all icon sets.
To test this out, let’s replace the React logo with our icon.
Remove the component and instead add:
And if we reload the page, we can see our rocket!
Our rocket isn’t spinning like the React logo though, so let’s fix that.
And the rocket should now be spinning!
Spinning rocket icon in React app
And while it’s probably a little too big now, we’re at a more appropriate size and we have our icon!
Part 2: Manually adding SVG files to a React component
Sometimes you don’t want to add a new library just to get an icon. Sometimes it’s a custom icon that’s not available in a public library.
Luckily with React, we can create a new SVG component pretty easily that allows us to add our custom SVG icons anywhere we want.
First, let’s find an icon.
While all Heroicons are available inside react-icons, let’s use it as an example since it’s easy to find and copy some SVG code.
Go to heroicons.com and search for an icon that you’d like to use for this example. I’m going to use “globe”.
After finding the icon you want, hover over that icon, where you’ll see options to copy that icon as SVG or JSX, and copy it as JSX.
Inside of that file, we’re going to create a new component called Globe and paste in our SVG within that component.
Note: when copying normal SVG to a React component, it might not work «as is». Sometimes SVG files include CSS classes or element attributes that aren’t valid with JSX.
If you run into errors, try fixing the attributes and looking at the web console to see the warnings and errors React throws. Because we copied as JSX, we were able to make it work right away.
Now, go back to src/App.js and import our new component:
Then we can replace our rocket icon with our new component:
And if we open up our browser, we can see our globe!
Large globe icon in REact app
Though, it’s a little big.
Then, add a new prop with that className to the component:
Now, we can update our Globe component in src/App.js to include that class:
And if we reload the page, we can see our logo is back at the right size and it’s spinning again!
Why don’t we include it as an img file?
While we can include it as an image file just like React does in the default create-react-app code, we get a few benefits from adding our SVG files “inline”.
For one, when adding SVG inline, we can access the different paths with CSS properties. This gives us more flexibility for customizing it dynamically.
It’s also going to provide fewer HTTP requests. The browser will know how to load that SVG, so we don’t need to bother the browser to request that file to include in the page.
That said, it’s still a valid option for adding an SVG file to the page.
How To Integrate SVG For Website And React App With Webpack
In this post, we will see how to use SVG images in a website and React app. We’ll learn how to integrate, simplify, optimize and automate the use of SVG with Webpack.
What is SVG
Scalable Vector Graphics is an XML-based vector image format. It’s an open format supported by the W3C. All modern browsers (Firefox, Chrome, Opera, Safari, Edge) have SVG rendering support. W3C create this format for websites a few years ago. Let’s take a look at some advantages of SVG:
HTML5 and the SVG format
State of the support of SVG format
SVG stable version is the SVG 1.1-second edition. Almost all browsers have great support for SVG rendering. Note, the specification is not trivial, and browsers don’t implement all specs. For more details about SVG 1.1 browser support, see caniuse.com.
After this introduction, let’s see how to load SVG.
How to load SVG as an image
The IMG tag can load the SVG as an image. With an IMG tag, the image is not vectorial anymore, and the advantage of scalability is lost.
Exit fullscreen mode
How to inline SVG
Another way to display an SVG is to inline the XML directly into the HTML file. It’s the better way to use SVG because the browser will compute the vectors and keep all advantages of it.
Exit fullscreen mode
We have seen how to manually add SVG images into a static website. The aim is now to automate this operation with Webpack.
Website integration through Webpack
Almost every website and web app use Webpack as a bundler to apply some operations on the assets. An easy way to make the SVG integration is to use a Webpack plugin to automatically inline the SVG files’ content to the bundled HTML.
Let’s use html-webpack-plugin to manage the HTML files as a template with Webpack. We can use html-webpack-inline-svg-plugin in addition to this one to manage SVG into our HTML template. This plugin can easily inline some SVG’s to HTML files by simply using an IMG tag with an «inline» attribute.
Let’s install these plugins:
Exit fullscreen mode
Now, add some configurations to manage HTML and SVG, add it to webpack.js (or webpack.comon.js if you split the configurations into multiple files).
Exit fullscreen mode
To inline an SVG, you have to use the IMG HTML tag and add an inline attribute. Webpack will replace the tag and inline the XML from the file.
Exit fullscreen mode
We know how to integrate SVG into a static website. Now, let’s see what to do if we use React to construct the frontend.
React app integration
How to integrate SVG with create-react-app
create-react-app is the easiest way to init a React application. It comes with some Webpack configurations.
The first way to load an SVG is to import the file to your component and load it as an image.
Exit fullscreen mode
Or to directly inline the XML into the JSX:
Exit fullscreen mode
But, react-script (the component used by create-react-app ) can use the Svgr plugin to convert the imported SVG as a component. The created React component will inline the XML from the SVG file inside the DOM.
Exit fullscreen mode
Now, we can use SVG with create-react-app, but it is interesting to know more about the configuration of Webpack to convert an SVG image to React component.
Let’s see how to integrate SVG with a custom Webpack configuration for React application.
How to integrate SVG with a custom webpack configuration
We have seen react-scripts use the Svgr plugin to create React component for inlining SGVs in the DOM.
Let’s deep dive into the Svgr configuration with Webpack:
How to use SVG Icons as React Components
I always struggled to use SVG in my React applications. Every time I searched about the topic online, I’ve found many ways on how to use SVG in React, but once I implemented the approaches, the success rates were very low. Today I want to give you a straightforward approach on how to use SVG icons as React components for your next React application.
Note: All icons used in this tutorial are from Flaticon. If you use icons from there, don’t forget to attribute the authors/platform.
Table of Contents
React SVG Icon Components from CLI
In this section, we will start by generating SVG icons manually for your React application. If you need a starter project, head over to this Webpack + Babel + React project and follow the installation instructions.
Now, create an empty src/Icons/ folder for all your generated React icon components:
The desired outcome would be to use the React icon components in our src/App.js component:
However, this doesn’t work yet because the src/Icons/ folder is empty. There are no icon components yet. In the next step, the assets/ folder will act as source folder and the src/Icons/ as target folder. We will add a new npm script to our package.json file which will generate the React icon components:
Last but not least, install the SVGR CLI package on the command line:
Now, after having everything set up properly, you can execute your new npm script with npm run svgr on the command line. Reading the command line output, you can see that new JavaScript files are being generated from your svg files. After the command terminates, you should be able to see the svg icons rendered as React components when starting your application. You can also check your src/Icons folder to see all generated React icon components. They take props as arguments as well, which makes it possible for us to define their height and width.
That’s all it needs to generate React components from SVGs. Every time you have a new SVG file or adjust one of your existing SVG files, you can the npm run svgr command again.
React SVG Icon Components from Webpack
Running the SVGR script every time to update your SVG icons is not the best solution though. What about integrating the whole process in your Webpack configuration? You should start out with an empty src/Icons folder. Afterward, move all your SVG files to this folder and remove the assets/ folder. Your folder structure should look like the following:
Your App component imports SVG files rather than JavaScript files now:
Starting your application wouldn’t work, because we cannot simply import SVG files this way. Fortunately, we can make Webpack doing the work for us implicitly with every application start. Let’s add the following configuration to our webpack.config.js file:
Afterward, install the necessary Webpack package for SVGR:
Once you start your application, Webpack is doing its thing and you don’t need to worry about your SVGs anymore. You can put your SVG files anywhere in your src/ folder and import them wherever you need them as React components. There is no need anymore for the SVGR npm script in your package.json file which we have implemented in the previous section.
Alternative: react-svg-loader
If you are using Webpack, you can also use a simplified SVG loader instead of SVGR. For instance, react-svg-loader can be used within your Webpack configuration. Note that it replaces SVGR:
Also you need to install it:
Afterward, you can import SVG files the same way as React components as you did before with SVGR. It can be seen as a lightweight alternative to SVGR.
SVGR Templates for advanced SVGs
When I worked with my last client on their React application, I had the problem of dealing with SVG icons which had only partially the viewBox attribute. Since this attribute is needed for giving your SVG icons a size, I had to find a way around to introduce this attribute whenever it wasn’t present for an icon. Now I could go through every SVG icon to fix this issue, however, dealing with more than 500 icons doesn’t make this a comfortable task. Let me show how I dealt with it by using SVGR templates instead.
The default SVGR template in your webpack.config.js file looks like the following:
By having this template at your disposal, you can change the code which is generated from the SVG file. Let’s say we want to fill all our icons with a blue color. We just extend the props object with a fill attribute:
This should work to give all icons a blue fill attribute. However, simple use cases like this are already provided by SVGR itself. Just check out their documentation on how to add/replace/remove attribute from SVGs.
SVGR with custom viewBox attribute
In our case, we wanted to compute the viewBox attribute for every SVG icon where the attribute isn’t present. First, remove the viewBox attribute from one of your SVGs to see that it’s not rendered properly anymore. After confirming the bug, we will try to fix it by using the introduced SVGR template and an external React Hook:
The React hook only needs a reference (ref) to the SVG components in order to set the viewBox attribute. The measurements for the viewBox attribute are computed based on the rendered icon. If the icon hasn’t been rendered or the viewBox attribute is already present, we do nothing.
The hook should be somewhere available not far away from our src/Icons/ folder:
Now, we can use the hook for our SVG template in the webpack.config.js file:
Having this in place, SVGR’s template feature will add the custom hook to every generated icon component. The hook only runs for icon components which have no viewBox attribute though. If you run your application again, you should see all icon components rendered properly, even though you may have removed the viewBox attribute from one of them.
In the end, I hope this walkthrough has helped you to get started with SVG icons in React by using SVGR with your command line/npm scripts or Webpack. The finished application using the Webpack approach and React can be found in this GitHub repository. If you run into any bugs, let me know in the comments. Otherwise I am happy to heard about your special use cases which fall into the category of my missing viewBox bug. Let me know about these cases in the comments.
How to use SVGs in React
This article will explore how to use SVG in React in three examples:
SVG is an incredible format. Not only is it a lightweight, infinitely scalable alternative to raster images, it can also be styled, animated with CSS when embedding inline in HTML. SVGs can be used everywhere:
How to use SVG in React
There are a few ways to use an SVG in a React app:
Let’s quickly go over each of them.
Use SVGs as regular images
SVGs can be used as an image, so we’d treat them as any other image resource:
Pros:
Cons:
Use case: Simple replacement for raster images that don’t need customization, e.g., logos.
Protip
Importing SVG
A few meta frameworks support importing SVGs out-of-the-box, such as Gatsby & Create React App.
With Webpack 5, this is relatively straightforward to setup. Parcel 2 handles this out of the box with a special import prefix. Rollup has an official plugin.
Import SVGs as components via bundler magic
When importing an SVG as a component, we can inline SVGs directly in our markup & use them as a component.
SVGR is the library that powers this ability. Setting it up could be a little hairy, thankfully many popular frameworks (Create React App, Gatsby) support this feature out of the box.
Pros:
Cons:
Use case: A custom SVG icon library
Include SVGs directly in JSX
JSX supports all SVG tags. We can (almost) paste the SVG directly into our React components!
This is the most straightforward method to take full advantage of SVG without bundler support, which is why we will use this method for all of our examples later in this article.
Pros:
Cons:
Use case: One-off graphic such as illustration, blog header
SVGs & React in practice
This article will not be completed if we don’t at least show off a few SVG tricks. In the following examples, we will explore what makes SVGs awesome.
All examples will use create-react-app (CRA) and CSS Module. A way to start a CRA project is using codesandbox. Otherwise, make sure Node is installed (any TLS versions will do) and run this:
npx create-react-app my-app && cd my-app
Example 1: A Loading Icon
Here’s what we’ll be making:
Let’s try writing this SVG from scratch. All we need is one circle. This is the SVG in its entirety:
Now let’s make it move! We can now attach class names to SVG elements and animate them with CSS transform & animation.
Nothing too exciting. However, things get more interesting when you realize that these dashes can be offset. What if, instead of many short dashes, we have a single dash whose length is the same as the circle’s circumference? We can then move that dash around by changing the offset, giving the appearance that the path is being shortened or lengthened.
Let’s give it a try:
Setting stroke-dashoffset to a negative value pushes the path further down & create the looping effect.
Protip
50 is roughly the circumference of the circle and for our use case we don’t ever need to change that value. In other cases, we might need to calculate the exact number:
circumference = radius * 2 * Math.PI
Finally, to make the animation more dynamic, let’s also rotate the circle.
prefers-reduced-motion
Loading icons typically doesn’t have the type of animations that could cause issues. However, for a larger graphic with lots of animation, it’s a good practice to provide a more gentle animation. In our case, we can extract the animation duration into a CSS variable & define a larger value inside of the prefers-reduced-motion media tag.
Customize with React
Now let’s make the icon customizable. We want to allow users to change color & thickness.
If color is unset, the stroke color will inherit from its parent.
Accessibility
Since our loading icon does not contain any text, we should give it a so a screen reader can make sense of it. To dive deeper into accessibility with SVGs, CSS Tricks cover this topic extensively.
Now that we have a title, a tooltip will show up when the cursor hovers over the SVG. If that seems unnecessary, we can get rid of it by adding pointer-events: none to SVG’s style.
Result
And with that, we can now use this loading icon anywhere! This Codesandbox demo contains a slightly more complex version of the icon above.
Example 2: Special Text Effect
SVG can do wild things with text, but let’s start with something simple. Like the previous example, we will start with just the SVG and then bring things up a notch with React.
The graphic we’ll be working with is rather long, but here’s the main parts:
SEO Concerns
We can nest this SVG inside heading tags. It is valid HTML (test it with the w3c validation tool) and screen readers can pick up the text inside.
SVG assets
Let’s look at the parts. is SVG’s compartment where we can put stuff for later use. That can be shapes, paths, filters, and gradients, such as in the SVG above. True to the compartment analogy, browsers will not render elements placed inside a block.
If we want to apply the defined gradient to the text object, we can reference its id with the following syntax: