Create dynamic SVG component in Astro project
Integrating Responsive SVGs in Astro By: Dániel Sipos onSVGs (Scalable Vector Graphics) are a popular choice for web graphics due to their scalability and crispness at any resolution. In modern web development, dynamically loading and rendering SVGs can enhance performance and flexibility. In this guide, we’ll explore a method to dynamically load and render SVGs using Astro, a modern static site generator.
Introduction
Astro allows you to build fast websites using any front-end framework you prefer. One of the strengths of Astro is its ability to handle components and dynamically load assets. In this article, we’ll walk through creating an Astro component that dynamically loads and renders SVG files based on the component’s props.
The Component
Below is the Astro component that achieves dynamic SVG loading and rendering.
Component Code
---
import { parse } from "node-html-parser";
const files = import.meta.glob<string>("/public/**/*.svg", {
query: "?raw",
});
export interface Props {
src: string;
class: string;
}
const getSVG = async (src: string) => {
const filePath = `/public${src}`;
if (!(filePath in files)) {
throw new Error(`${filePath} not found`);
}
const { default: file } = await files[filePath]() as unknown as { default: string };
const root = parse(file);
const svg = root.querySelector("svg") as unknown as SVGElement;
const { attributes, innerHTML } = svg;
return {
attributes,
innerHTML,
};
}
const { src, ...attributes } = Astro.props;
const { attributes: baseAttributes, innerHTML } = await getSVG(src);
const svgAttributes = { ...baseAttributes, ...attributes };
---
<svg {...svgAttributes} set:html={innerHTML} />
Breakdown of the Code
Imports and File Handling
import { parse } from "node-html-parser";
const files = import.meta.glob<string>("/public/**/*.svg", {
query: "?raw",
});
- parse from “node-html-parser”: This library is used to parse raw SVG strings into a DOM-like structure.
- import.meta.glob: This Astro feature helps to create an object mapping paths to SVG files in the /public directory, allowing dynamic import of these files as raw strings.
Props Interface
export interface Props {
src: string;
class: string;
}
- Props interface: Defines the expected properties for the component. Src is the path of the SVG file, and class allows adding CSS classes.
getSVG Function
const getSVG = async (src: string) => {
const filePath = `/public${src}`;
if (!(filePath in files)) {
throw new Error(`${filePath} not found`);
}
const { default: file } = await files[filePath]() as unknown as { default: string };
const root = parse(file);
const svg = root.querySelector("svg") as unknown as SVGElement;
const { attributes, innerHTML } = svg;
return {
attributes,
innerHTML,
};
}
- getSVG: This asynchronous function takes the name of an SVG file and returns its attributes and inner HTML.
- filePath: Constructs the path to the SVG file.
- Error Handling: Throws an error if the file is not found.
- File Importing: Dynamically imports the SVG file.
- Parsing: Uses node-html-parser to parse the raw SVG string.
- Attributes and Inner HTML: Extracts the attributes and inner HTML from the parsed SVG element.
Component Logic
const { src, ...attributes } = Astro.props;
const { attributes: baseAttributes, innerHTML } = await getSVG(src);
const svgAttributes = { ...baseAttributes, ...attributes };
- Destructuring Astro.props: Extracts src and other attributes passed to the component.
- getSVG Call: Retrieves the SVG’s attributes and inner HTML.
- svgAttributes: Merges the SVG’s base attributes with any additional attributes passed to the component.
Component Markup
<svg {...svgAttributes} set:html={innerHTML} />
- SVG Element: Renders a svg element with the combined attributes and sets its inner HTML to the SVG’s content.
Summary
This Astro component allows for:
- Dynamic Loading: Loads an SVG file based on the src prop.
- Attribute Merging: Merges the SVG’s native attributes with additional ones passed to the component.
- Rendering: Renders the SVG content correctly inside a svg tag.
Using this approach, you can efficiently manage and render SVGs dynamically in your Astro project, enhancing both performance and maintainability.
Astro’s capability to dynamically import and handle assets makes it a powerful tool for modern web development. With this method, you can easily integrate SVGs into your components, ensuring your site remains fast and flexible.