Svelte: SVG import

Created on 29 Oct 2018  路  19Comments  路  Source: sveltejs/svelte

To keep my component code clean, I need svg-imports. I use webpack. For some reasons I need inline svg. For now I just wrote simple replace loader, but it looks quite ugly.

A there any solutions like vue-svg-loader for svelte? It wrap`s svg in vue-component.
Or another way to deal with svg?

Most helpful comment

With rollup:

rollup.config.js:

import svg from 'rollup-plugin-svg-import';

plugins: [
      svg({ stringify: true }),
      svelte({....

svelte file:

<script>
import ArrowIcon from './arrow-dropdown.svg';
</script>

<div>
   {@html ArrowIcon}
</div>

All 19 comments

Hi @Stormsher - I use this code:

// webpack.config.js
const svgRules = {
  test: /\.svg$/,
  loader: 'svg-inline-loader',
  options: {
    removeSVGTagAttrs: true
  }
}

// server -> module -> rules []
svgRules

// client -> module -> rules []
svgRules
// Some component
      <div class="logo">
        {@html beyonkLogo}
      </div>

<script>
    import beyonkLogo from '../../static/images/logo.svg'

    data () {
      return {
        beyonkLogo
      }
    }
</script>

And what if I want change width/height/title/etc?
Of course it`s possible solution...

  :global(.container-name) svg {
    height: 51px;
    width: 22px;
    fill: #000;
  }

@antony
:global is unsupported in customElements..

@Winne4r Svelte doesn't generate customElements / WebComponents, it simply renders regular html markup from your component.

So any other solutions?
How to import SVG in custom element?

@Winne4r You can ask on stackoverflow for support questions. Custom Elements do not relate to Svelte.

@antony https://svelte.technology/guide#custom-elements

Error 404 :beetle: broken link.

Some redirects apparently aren't working correctly. The new URL for the v2 site is https://v2.svelte.dev/guide#custom-elements - The v3 docs are going to live at https://svelte.dev/docs#Custom_element_API but aren't written yet

this fails when you use a third party node module,such as
https://github.com/josdejong/jsoneditor

I found out you have to use the svg-url-loader
{
test: /.svg(\?v=\d+.\d+.\d+)?$/,
loader: 'svg-url-loader',
options: {},
},

With rollup:

rollup.config.js:

import svg from 'rollup-plugin-svg-import';

plugins: [
      svg({ stringify: true }),
      svelte({....

svelte file:

<script>
import ArrowIcon from './arrow-dropdown.svg';
</script>

<div>
   {@html ArrowIcon}
</div>

@bravecow you snippet worked for me after adding .svg to the list of supported extensions (before it said that I needed to add a plugin to import no JS files), but also ArrowIcon is not a function but a simple string, so it doesn't need parens nor it allows to override attributes.

@cibernox thanks, fixed according to latest rollup-plugin-svg-import version 馃憤

to the list of supported extensions

It works for me with default extensions. Please, check if you use in your config svg plugin before svelte.

@bravecow I locally made some changes to allow to add attributes to the SVG when we stringify. It is probably too naive to be released, but for my use case (just adding classes or "fill") works well:

const extname = require("path").extname;
const createFilter = require("rollup-pluginutils").createFilter;

const injectString = svg => `
export default function(attrs = {}) {
  console.log('rendering svg with attrs', attrs);
  let svg = ${svg};
  let parts = Object.keys(attrs).reduce((accum, key) => {
    if (attrs[key]) accum.push(key + "=" + attrs[key]);
    return accum;
  }, []);
  return parts.length > 0 ? '<svg ' + parts.join(' ') + svg.substring(4) : svg;
  }
`;

/**
 * @param options
 * @param options.include
 * @param options.exclude
 */
export default function(options = {}) {
  const filter = createFilter(options.include, options.exclude);

  return {
    name: "svg-import",
    transform: (code, id) => {
      if (!filter(id) || extname(id) !== ".svg") return null;
      const content = JSON.stringify(code);
      return { code: injectString(content), map: { mappings: "" } };
    }
  };
};
<script>
  import SearchIcon from '../svgs/search.svg';
</script>

<nav class="header__nav">
  <a href="/search">
    {@html SearchIcon({ class: "icon-svg"})} Search
  </a>
</nav>

@cibernox Yep, something like that. But does your class icon-svg not removed by Svelte from CSS?

@bravecow that class is in my global css.

@cibernox hah, okay. so do you need attributes support in this rollup plugin? If yes I can try do add it in next days.

And anyway it should work without svg ext option. Just move up svg plugin.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thoughtspile picture thoughtspile  路  3Comments

robnagler picture robnagler  路  3Comments

matt3224 picture matt3224  路  3Comments

AntoninBeaufort picture AntoninBeaufort  路  3Comments

rob-balfre picture rob-balfre  路  3Comments