@svelte-put/inline-svg
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>
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
*
* 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! 👨💻