@svelte-put/inline-svg GitHub

solution for inlining SVGs in svelte land

@svelte-put/inline-svg @svelte-put/inline-svg @svelte-put/inline-svg changelog

Introduction

Existing solutions for inline SVGs in Svelte land often rely on component, which proves painful when it comes to styling and even handling. This package attempts to achieve a more minimal alternative using Svelte action.

Build Time Solution

This packages operates at runtime, meaning your prerendered HTML does not contain the complete SVG elements. To statically inline SVGs at build time, use @svelte-put/preprocess-inline-svg, which has similar interface but with additional setup step.

Installation

npm install --save-dev @svelte-put/inline-svg
pnpm add -D @svelte-put/inline-svg
yarn add -D @svelte-put/inline-svg

Quick Start

The Svelte logo SVG on the right is dynamically fetched via network at runtime upon page load. Notice in the source code below, only width (or height) needs to be specified. By default, inlineSvg will calculate the other dimension the keep the aspect ratio.

<script>
  import { inlineSvg } from '@svelte-put/inline-svg';

  export let src = 'https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg';
</script>

<!-- add attributes and styling as with any other HTML element -->
<svg use:inlineSvg={src} width="100" class="svelte" />

<style>
  svg.svelte {
    filter: drop-shadow(0 0 0.5rem theme('colors.svelte'));
  }
</style>

inlineSvg is typically used on SVGElement (i.e <svg>), for obvious reason.

Attributes and Inner HTML

Attributes provided to the svg element where inlineSvg is placed on will replace existed ones from the original SVG. On the contrary, its inner HTML will be replaced with that from the original SVG.

Take the following SVG as an example:

<svg viewBox="0 0 24 24" width="24" height="24" stroke-width="2">
  <!-- truncated original svg innerHTML -->
</svg>

And inlineSvg is used as follows:

<svg use:inlineSvg={'https://example.com/original.svg'} height="16" stroke-width="1">
  <!-- some innerHTML -->
</svg>

The resulting SVG at runtime will be:

<svg viewBox="0 0 24 24" width="16" height="16" stroke-width="1">
  <!-- truncated original svg innerHTML -->
</svg>

If you have a use case where it is useful to append/prepend the innerHTML of the original SVG rather than replacing it, please raise an issue over at github. For now, let’s keep things simple.

Customization

The inlineSvg action takes either a string for fetching remote SVG, or a config object with the following interface.

interface InlineSvgConfig {
	/** svg remote URI */
	src: string;
	/** cache policy for use in fetch from svg `src` */
	cache?: Request['cache'];
	/**
	 * automatically calculate dimensions from the available attributes
	 * of both the local SVG element (on which action is used) and the remote SVG
	 *
	 * For example, if you specify only `width` to the local SVG element, the
	 * height will automatically be calculated from the remote SVG
	 *
	 * @remarks
	 *
	 * For this to work, width & height must be "extractable" from the remote element,
	 * that is, the remote SVG must either have the `viewBox` or both `width` and `height` attributes that
	 * is in the same unit.
	 */
	autoDimensions?: boolean;
	/**
	 * optionally transform the SVG string fetched from remote source before inlining
	 */
	transform?: (svg: string) => string;
}

Some Questions and Answers

Q: Why should I care about runtime vs build time?
A: Javascript! Runtime requires Javascript. Without it, users will not see your SVG. On the other hand, build time does the work beforehand, so SVGs are already there in the initial HTML.

Q: When to use which?
A: If you do not know in advance what SVGs to inline, or if your SVG is huge but only conditionally rendered: use @svelte-put/inline-svg at runtime. Otherwise, especially for static icons and pictograms, use @svelte-put/preprocess-inline-svg at build time.

Q: Do I really need this package?
A: No! Use <img> when possible. My initial use case is to be able to change properties of the SVG, especially color. But that can potentially be done with mask-image. So consider your use case before adding another dependency.


Happy inlining SVGs! 👨‍💻

Edit this page on Github