BLOG.siposdani87

Create dynamic SVG component in Astro project

By: Dániel Sipos on

SVGs (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 {
    icon: string;
    class: string;
}

const getSVG = async (name: string) => {
    const filepath = `/public/${name}.svg`;

    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 { icon, ...attributes } = Astro.props;
const { attributes: baseAttributes, innerHTML } = await getSVG(icon);

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",
});

Props Interface

export interface Props {
    icon: string;
    class: string;
}

getSVG Function

const getSVG = async (name: string) => {
    const filepath = `/public/${name}.svg`;

    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,
    };
}

Component Logic

const { icon, ...attributes } = Astro.props;
const { attributes: baseAttributes, innerHTML } = await getSVG(icon);

const svgAttributes = { ...baseAttributes, ...attributes };

Component Markup

<svg {...svgAttributes} set:html={innerHTML} />

Summary

This Astro component allows for:

  1. Dynamic Loading: Loads an SVG file based on the icon prop.
  2. Attribute Merging: Merges the SVG’s native attributes with additional ones passed to the component.
  3. 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.

Share with your friends

Related posts