SVG

SVG is a vector-based 2D graphics format based on XML, with support for interactivity and animation. Parcel includes support for SVG as a separate file, embedded in HTML, or imported as JSX in a JavaScript file.

Dependencies

#

Parcel detects most references in SVG to other files (such as <script>, <image>, and <use>) and processes them as well. These references are rewritten so that they link to the correct output files.

File names are resolved relative to the current SVG file, but you can also use absolute and tilde specifiers. See Dependency resolution for details.

Stylesheets

#

External stylesheets can be referenced via the xml-stylesheet processing instruction in an SVG document. You can reference a CSS file, or any other file that compiles to CSS such as SASS, Less, or Stylus.

example.svg:
<?xml-stylesheet href="style.css" ?>
<svg viewBox="0 0 240 20" xmlns="http://www.w3.org/2000/svg">
<text>Red text</text>
</svg>
style.css:
text {
fill: red;
}

See the CSS docs for details on how CSS is processed by Parcel.

Scripts

#

The <script> element can be used to reference a script file from SVG. You can reference a JavaScript file, or any other file that compiles to JavaScript such as TypeScript, JSX, or CoffeeScript.

The type="module" attribute should be used to indicate that a file is an ES module or CommonJS file. If it is omitted, then the referenced file is treated as a classic script. See Classic scripts for more information about this. ES modules are not yet supported natively in SVG, so Parcel compiles all JavaScript to classic scripts even if authored as a module.

Note: SVG uses the href attribute rather than the src attribute for <script> elements.

example.svg:
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="red" />
<script type="module" href="interactions.js" />
</svg>
interactions.js:
let circle = document.querySelector("circle");
circle.addEventListener("click", () => {
circle.setAttribute("fill", "blue");
});

See the MDN docs for the <script> element for more info, and the JavaScript docs for details on how Parcel processes JavaScript.

Images

#

Raster images or other SVGs can be embedded in an SVG file using the <image> element. Parcel recognizes the href and xlink:href attributes.

<image href="image.jpg" width="100" height="50" />

Parcel’s image transformer can also be used to resize and convert images by using Query parameters.

<image href="image.jpg?as=webp" width="100" height="50" />

Note: SVGs referenced via the <image> element do not load external resources such as stylesheets, fonts, and other images, and scripting and interactivity is disabled.

See the Image docs for details on how Parcel processes images.

#

SVG files can link to other web pages or files using the <a> element. Parcel supports the href and xlink:href attributes.

<a href="circle.html">
<circle cx="50" cy="40" r="35" />
</a>

While other assets referenced from an SVG file will include a content hash in their compiled filename by default, files referenced by an <a> element will not. That's because these URLs are typically human readable, and need to have a stable name over time. Bundle naming can be overridden by Namer plugins.

External references

#

Parcel supports external references via the href and xlink:href attributes on many other elements. See the MDN docs for more details.

<use href="fox.svg#path" stroke="red" />
<text>
<textPath href="fox.svg#path">
Quick brown fox jumps over the lazy dog.
</textPath>
</text>

External resources referenced via the url() function in presentation attributes such as fill, stroke, clip-path, and many others are also supported.

<circle
cx="50" cy="40" r="35"
fill="url(external.svg#gradient)" />

Inline scripts and styles

#

<script> and <style> tags with text content are also processed just like standalone files, and the generated bundles are inserted back into the SVG file. Use the type="module" attribute as described above to enable importing other modules from an inline script.

example.svg:
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
<style>
@import './style.scss';
</style>
<script type="module">
import {setup} from './interactions.ts';
let circle = document.querySelector('circle');
setup(circle);
</script>
</svg>
style.scss:
$fill: blue;

circle {
fill: $fill;
}
interactions.ts:
export function setup(element: SVGElement) {
element.addEventListener("click", () => {
element.setAttribute("fill", "red");
});
}

CSS files referenced via @import, and JavaScript referenced via import will be bundled into the compiled SVG file. See Stylesheets and Scripts for how to reference an external file.

Inline style attribute

#

The style attribute can be used on any SVG element to define CSS styles. Parcel will process the inline CSS, and insert the result back into the style attribute. This includes following referenced URLs, as well as transforming modern CSS for your target browsers.

<circle
cx="50" cy="40" r="35"
style="fill: url(external.svg#gradient)" />

SVG in HTML

#

SVG in HTML can either be referenced as an external file, or embedded directly into an HTML document.

External SVG

#

SVG files can be referenced from HTML in several ways. The simplest is to use the <img> element, and reference the SVG file using the src attribute. Parcel will follow the reference and process the SVG and all of its dependencies as well.

<img src="logo.svg" alt="logo" />

This approach works great if your SVG is static. If the SVG references external resources such as other SVGs, images, fonts, stylesheets, or scripts, or contains any interactivity, it won’t work. You also cannot alter the styling of the SVG via CSS in the HTML page or manipulate the DOM of the SVG with JavaScript, and any text in the SVG cannot be selected by the user.

The <object> element can be used to embed an external SVG in HTML and enable external references, scripting, interactivity, and text selection. Use the data attribute to reference the SVG file.

<object data="interactive.svg" title="Interactive SVG"></object>

This also allows you to get access to the SVG DOM via the getSVGDocument() method on the <object> element.

let object = document.querySelector("object");
let svg = object.getSVGDocument();
let circle = svg.querySelector("circle");
circle.setAttribute("fill", "red");

However, SVGs embedded using the <object> element cannot be styled by CSS on the HTML page.

Inline SVG

#

SVG can be inlined into HTML directly rather than referenced as a separate file. This allows CSS on the HTML page to style the SVG elements. Parcel supports external references within embedded SVG the same way it does when the SVG is in a separate file.

<!DOCTYPE html>
<html>
<body>
<svg width="100" height="100">
<circle cx="50" cy="50" r="50" />
</svg>
<style>
circle {
fill: blue;
}

circle:hover {
fill: green;
}
</style>
</body>
</html>

SVG in CSS

#

SVG can be referenced from CSS files using the url() function. As with the <img> element, SVGs in background images do not support external resources such as stylesheets, and scripting and interactivity is disabled.

.logo {
background: url("logo.svg");
}

You can also embed small SVGs in a CSS file using data URLs. Use the data-url: scheme to do this, and Parcel will build the SVG and inline the result into the compiled CSS. See Bundle inlining for more details.

.logo {
background: url("data-url:logo.svg");
}

SVG in JavaScript

#

SVG files can either be referenced as an external URL from JavaScript, inlined as a string, or converted to JSX for rendering in a framework like React.

URL references

#

Parcel supports referencing SVG files using the URL constructor. This example uses the result to render an <img> element using JSX. This works the same way as described in External SVG above. You can use an <object> element instead if the SVG is interactive or has external resources.

const logo = new URL('logo.svg', import.meta.url);

export function Logo() {
return <img src={logo} alt="logo" />;
}

See URL dependencies in the JavaScript docs for more details.

Inlining as a string

#

SVG can be inlined as a string in JavaScript by importing it using the bundle-text: scheme.

import svg from 'bundle-text:./logo.svg';

let logo = document.createElement('div');
logo.innerHTML = svg;
document.body.appendChild(logo);

See Bundle inlining for more details.

Importing as a React component

#

The @parcel/transformer-svg-jsx plugin can be used to import an SVG file as a React component. This transforms SVG into JSX, and optimizes it for file size. It's compatible with SVGR.

This plugin is built into Parcel, but it is not used by the default config, so you'll need to add it to your .parcelrc.

You can either configure your .parcelrc to convert all SVGs to JSX, or use a named pipeline to create a URL scheme that you can reference from a JavaScript import statement. This approach allows SVG files referenced from JavaScript to be converted to JSX, but SVGs referenced elsewhere to be kept as SVG files.

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": ["@parcel/transformer-svg-jsx"]
}
}
example.jsx:
import Icon from "jsx:./icon.svg";

export const App = () => <Icon />;

SVG to JSX can be configured in your .parcelrc, following the options documented by SVGR. The supported options are icon, dimensions, expandProps, ref, memo, svgProps, replaceAttrValues, titleProp, descProp, svgo, and svgoConfig. The svgoConfig option accepts the same options as the optimize object of the SVG minifier.

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": [
{
"plugin": "@parcel/transformer-svg-jsx",
"config": {
"icon": true,
"svgProps": {
"role": "img"
}
}
}
]
}
}

The template option customizes the JavaScript module that is generated for the component. Unlike SVGR's template function, it is a string containing an ES module written in plain JavaScript. The first $ICON identifier used as an expression in the template is replaced with the component, which is wrapped in forwardRef or memo if the ref or memo options are enabled. The template must export the component itself, and imports within it are resolved relative to the SVG file.

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": [
{
"plugin": "@parcel/transformer-svg-jsx",
"config": {
"template": "import {wrap} from './wrap.js';\nexport default wrap($ICON);"
}
}
]
}
}

Production

#

In production mode, Parcel includes optimizations to reduce the file size of your code. See Production for more details about how this works.

Tree shaking

#

SVG files are often used as sprite sheets containing many icons, which are referenced by fragment from other files. In production builds, Parcel tracks these references and removes the elements that aren't used. Only the referenced elements are kept, along with anything they reference in turn, such as gradients, masks, and other <use> elements.

index.html:
<svg width="24" height="24"><use href="icons.svg#home" /></svg>
icons.svg:
<svg xmlns="http://www.w3.org/2000/svg">
<linearGradient id="fade">...</linearGradient>
<symbol id="home" viewBox="0 0 24 24">
<path d="..." fill="url(#fade)" />
</symbol>
<symbol id="search" viewBox="0 0 24 24">
<path d="..." />
</symbol>
</svg>

In this example, only the home symbol is used, so the search symbol is removed from the output. The fade gradient is kept because the home symbol references it.

Fragment references are tracked from HTML, other SVG files, and CSS url() functions. If an SVG file is also displayed as a whole, e.g. using <img src="icons.svg">, its visible content is kept as well. Parcel also warns when a fragment references an id that doesn't exist in the SVG file.

All elements are kept when Parcel cannot determine which ones are used. This includes when the SVG file:

Tree shaking runs as part of SVG minification, so disabling the optimize option also disables it.

Minification

#

In production mode, Parcel automatically minifies your code to reduce the file sizes of your bundles. By default, Parcel uses oxvg to perform SVG minification, which is compatible with SVGO. To configure it, set the optimize option of @parcel/transformer-svg in your .parcelrc. Set it to false to disable SVG minification, or to an object of options.

Each key is the name of an SVGO plugin, and the value is either true or false to enable or disable it, or an object of options for the plugin. Plugins from SVGO's preset-default are enabled by default (except cleanupIds). Set "default": false to disable them, and only run the plugins you list.

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"*.svg": [
{
"plugin": "@parcel/transformer-svg",
"config": {
"optimize": {
"inlineStyles": false,
"removeTitle": true
}
}
}
]
}
}