Multicolored icons
The recommended way to implement multicolored icons is to use CSS variables in SVGs. This will:
-
Eliminate the need to update all images when only one color in the palette changes.
-
Allow designers and developers to work seamlessly and share the same icon sets without any additional manual modifications.
vite-awesome-svg-loader allows you to map a set of predefined colors (or any values for that matter) to a set of CSS
variables (or any other values) via
replaceColorsList option:
export default defineConfig({ plugins: [ viteAwesomeSvgLoader({ replaceColorsList: // Global map of color replacements. Key is an original color, value is its replacement. Both can be any values: // HEX, name, rgb() or arbitrary custom values. Applied to all files. { "#003147": "red", "rgb(0, 49, 71)": "#003147", "myCustomColor": "var(--some-color-var)", },
// Map of color replacements per files { files: ["vars.svg"], // File names or regexes
// Replacements, same format as above replacements: { red: "var(--primary-color)", green: "var(--secondary-color)", blue: "var(--tertiary-color)", },
// Default value for colors that are not in replacements map. Set an empty string to preserve original colors. // Default value is "currentColor", default: "currentColor" }, }), ],}); Rendered demo
Demo's source code
src
assets
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" xml:space="preserve"> <circle fill="red" cx="8.0524569" cy="8.1588478" r="7.8950858" />
<circle fill="blue" cx="15.9475431" cy="8.1588478" r="7.8950858" />
<circle fill="green" cx="12" cy="15.8411522" r="7.8950858" />
<style type="text/css"> circle { opacity: 0.5; } </style></svg>import imageSrc from "@/assets/image.svg";import { CSSProperties } from "react";import { SvgImage } from "vite-awesome-svg-loader/react-integration";
export default function App() { return ( <div className="images"> <SvgImage src={imageSrc} style={ { "--primary-color": "red", "--secondary-color": "green", "--tertiary-color": "blue", } as CSSProperties } /> <SvgImage src={imageSrc} style={ { "--primary-color": "magenta", "--secondary-color": "cyan", "--tertiary-color": "yellow", } as CSSProperties } /> </div> );}import React from "react";import ReactDOM from "react-dom/client";import App from "./App.tsx";
ReactDOM.createRoot(document.getElementById("app")!).render( <React.StrictMode> <App /> </React.StrictMode>,);<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1" /> </head> <body> <div id="app"></div> <script type="module" src="/src/main.tsx" ></script> </body></html>{ "name": "react-multicolored-icons", "version": "0.0.0", "private": true, "type": "module", "scripts": { "dev": "npm run build -- --watch", "build": "npm run type-check && npm run build-only", "build-only": "vite build --config vite.config.lib.ts", "type-check": "tsc --noEmit" }, "dependencies": { "vite-awesome-svg-loader": "*", "vite-file-tree-builder": "*" }}{ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true,
/* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx",
/* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true,
"baseUrl": ".", "paths": { "@/*": ["./src/*"] },
"types": [ // Add types for query imports (for example, "@/some/file.svg?src"). // Unfortunately, it's impossible to fully type it. Use plugin configuration instead. "vite-awesome-svg-loader",
"vite/client", // Vite types "vite-file-tree-builder" // Internal types ] }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }]}{ "compilerOptions": { "composite": true, "skipLibCheck": true, "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true }, "include": ["vite.config.ts"]}import { fileURLToPath, URL } from "node:url";import { defineConfig } from "vite";import react from "@vitejs/plugin-react";
// Import vite-awesome-svg-loaderimport { viteAwesomeSvgLoader } from "vite-awesome-svg-loader";
export default defineConfig({ plugins: [ react(), viteAwesomeSvgLoader({ replaceColorsList: [ { files: ["image.svg"], // File names or regexes
// Replacements, same format as above replacements: { red: "var(--primary-color)", green: "var(--secondary-color)", blue: "var(--tertiary-color)", },
// Default value for colors that are not in replacements map. Set an empty string to preserve original colors. // Default value is "currentColor", default: "currentColor", }, ],
urlImportsInLibraryMode: "emit-files", }), ], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)), }, },});
Please open file to view its content