Styling
I'm going with TailwindCSS as my default styling utility library. Skip this if you have other preferences.
Tailwindcss
- Install the TailwindCSS and initialize it using the below commands.
pnpm add -D tailwindcss postcss autoprefixer
npx tailwindcss init
touch postcss.config.js
- The init command will create a
tailwind.config.js
file in the root directory where we can configure the tailwind library. Update the config file content property to process the HTML, and TS files in src and public directory as follows.
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: { extend: {} },
plugins: [],
}
- Now we should let the postcss preprocessor know that we are using tailwindcss in our project. To do that, open the postcss.config.js file and add the 'tailwindcss' option to the plugins list.
export default {
plugins: { tailwindcss: {}, autoprefixer: {} },
}
- Open
/src/index.css
file and update it with the following content
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
- Open the
src/App.tsx
file and update theh1
tag as follows and check whether the tailwind class is applied successfully.
<h1 className="text-green-500">Vite + React</h1>
Rendering icons
SVGs are the best image format for rendering icons for the following reasons.
- They are small in size
- The same icon can be used in different places in different sizes without losing the quality, that's why it's called Scalable Vector Graphics.
- A monochromatic icon can be rendered in different colors just by applying CSS
To render the icons inline I'm using this SVGR plugin to transform the SVGs to react components and then import it wherever necessary just like importing a normal react component.
- Install the necessary packages
pnpm add -D @svgr/core @svgr/plugin-svgo vite-plugin-svgr
- Update the Vite config to automatically convert the SVGs into react components.
export default defineConfig({
...,
plugins: [
...,
svgr({
svgrOptions: {
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
svgoConfig: {
plugins: ['preset-default'],
},
},
}),
]
});
- Update the package.json file
...,
"scripts": {
...,
"format:svg": "prettier --write '**/*.svg' --parser 'html'",
"format": "prettier --write . && pnpm format:svg",
},
"lint-staged": {
"**/*.{js,ts,tsx}": [
"eslint --fix"
],
"**/*.svg": "prettier --write --ignore-unknown --parser 'html'",
"**/*": "prettier --write --ignore-unknown"
},
...
- Open
src/vite-env.d.ts
and add the following entry to avoid the ReactComponent SVG error while importing.
/// <reference types="vite-plugin-svgr/client" />
- Let's make use of the already available
react.svg
and see how we can import it as an inline SVG. Update the/src/app.tsx
as follows,
import { ReactComponent as ReactIcon } from 'src/assets/react.svg'
export const App = () => {
return (
<div className="font-semibold text-lg text-green-500">
<ReactIcon width="24px" height="24px" className="text-blue-500" />
Rendered from react app
</div>
)
}
Things to remember
We need to make sure we import SVGs the right way so they are highly customizable and scalable. Rendering the SVGs as inline, allows us to customize the SVG properties such as dimensions, fill color, and stroke color through props.
For the library to properly parse the SVG and allow us to customize it inside our components ensure the following.
- The SVG you are adding has the fill property in the SVG as 'currentcolor' so it's easy to customize this color based on the prop. Please see reference SVG
src/assets/react.svg
. - The SVG shouldn't have width and height set so we can set them inside our components when used. (They will be overwritten anyways but it's better to avoid width and height in the SVG being added)
- Try to open the SVG in the browser and start deleting the unwanted elements present in the SVG by inspecting the elements in the developer console and making sure only valid tags are present and checking for any visual changes. If there are no visual changes we can delete those elements from the SVG.
- Set the
path
element'sfill
property toinherit
so that the color will be inherited from the SVG element itself. - Check the SVG size after making these changes.
- If the size of SVG is < 1kb then it's eligible to render as an inline icon. Put the SVG in the
src/assets/icons
path and render it inline using the component. - If the size > 1kb then it will increase the bundle size and affect the performance. Put the SVG in the
src/assets/images
folder and render it using<img>
tag src. This way it will not hinder the page load. - This 1kb is an arbitrary value, but it is advised to have a threshold beyond which the icons should be rendered using image tags only.
PS: You can also create a generic UI component wrapper that accepts the SVG as input and render it with some default sizes and config.
Next part
In the next part of this series, we will see how to add unit testing support to our app using JEST.
Top comments (0)