Home > front end >  Import an SVG element from another document, without losing the CSS <style> from the original
Import an SVG element from another document, without losing the CSS <style> from the original

Time:10-28

I need to create a number of SVG files and would love to keep a set of common symbols in one file and import them into the others.

I managed to do this using a <use> element:

<use href="common.svg#symbol1" />

The problem is that if common.svg has a CSS style that affects an element, the style has no effect in the file where the element is imported.

I uploaded two SVGs on svgur.com to show this:

https://svgur.com/i/bYv.svg

...defines a circle with id ball affected by a style that sets a red border around it.

<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <style>#ball { stroke:#ff0000; stroke-width:10; }</style>
    <circle id="ball" cx="50" cy="50" r="45" />
</svg>

https://svgur.com/i/bXA.svg

...uses the circle. The circle is visible but the border is not.

<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <use href="bYv.svg#ball" />
</svg>

Questions:

  1. Is this a bug of the SVG renderer I'm using or is it how it's supposed to behave?

    Every renderer I tried (chrome, firefox, inkscape) shows the same result so I suspect this might be the intended behavior.

  2. Is there any way to import an element from an external SVG file and the CSS styles that affect it too, so that it appears exactly like it does in its original document?

CodePudding user response:

  1. Is this a bug of the SVG renderer I'm using or is it how it's supposed to behave?

It is the intended behaviour. CSS rules do not apply across document boundaries. You are importing the SVG into your main document, but your CSS is in another document.

  1. Is there any way to import an element from an external SVG file and the CSS styles that affect it too...

No.

Well I suppose you could technically write some Javascript to load the other file and extract the CSS rules. But I strongly suspect you don't want to do that.

You SVG "sprite document" should not have CSS rules in a <style> tag.

The best approach is to pre-prepare you SVGs to be used as sprites.

What I would do is import your common.svg into a vector editor and convert all your CSS attributes into presentation attributes. For example Illustrator lets you choose the method of styling when you export an SVG.

What you want is for something like this:

<svg>
  <style>
    .st0 {
      fill: red;
    }
  </style>

  <symbol id="whatever">
    <path d="..." class="st0"/>
  </symbol>
</svg>

to be converted to:

<svg>
  <symbol id="whatever">
    <path d="..." fill="red"/>
  </symbol>
</svg>

CodePudding user response:

According to the Scalable Vector Graphics (SVG) 2 specification (W3C Editor’s Draft, 08 June 2021) it seems that the style of the original document should be applied where an element is imported.

Section 5.5. The ‘use’ element:

The cloned content inherits styles from the ‘use’ element and can be the target of user events. However, these cloned element instances remain linked to the referenced source and reflect DOM mutations in the original. In addition, all style rules that apply in the scope of the referenced element also apply in the scope of the cloned shadow tree.

And 5.5.3. Style Scoping and Inheritance:

The use-element shadow tree, like other shadow trees, exhibits style encapsulation, as defined in the CSS Scoping module [css-scoping-1]. This means that elements in the shadow tree inherit styles from its host ‘use’ element, but that style rules defined in the outer document do not match the elements in the shadow tree. Instead, the shadow tree maintains its own list of stylesheets, whose CSS rules are matched against elements in the shadow tree.

When the referenced element is from an external document, the stylesheet objects generated when processing that document apply to the shadow tree, and are read-only. All URL references in the stylesheet, including fragment-only references, must be made absolute, relative to the URL of the document that contains the referenced element. User agents may re-use the same stylesheet objects for any shadow trees that reference that same external document.

So it's the browsers and SVG renderers I tried that are not conforming to the standard.

I'm still looking for a way to emulate this behavior on existing SVG user agents.

  • Related