Bring in an SVG element from a separate document while retaining the CSS <style> details from the original source

Creating a number of SVG files can be made easier by keeping common symbols in one file and importing them into others.

An effective method for achieving this is using the <use> element:

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

However, there may be an issue if the `common.svg` file contains CSS styles that impact an element, as these styles may not carry over to the imported files.

To illustrate this problem, two SVGs have been uploaded on svgur.com:

This file defines a circle with id ball which is styled with a red border.

<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>

In this file, the circle from the previous SVG is used. However, the border does not appear.

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

Questions:

  1. Could this discrepancy in rendering be a bug in the SVG renderer or is it functioning as designed?

    All tested renderers (Chrome, Firefox, Inkscape) produce the same result, indicating that this behavior may be intentional.

  2. Is there any known way to import an element from an external SVG file along with its associated CSS styles, ensuring it retains its appearance from the original document?

Answer №1

  1. Could this be a glitch in the SVG renderer I am using or is it operating as expected?

It is working as intended. CSS rules do not extend across different documents. When you import the SVG into your main document, the CSS from another document will not apply.

  1. Is there a method to import an element from an external SVG file along with its associated CSS styles...

No, it is not possible directly.

However, if needed, you could potentially write some JavaScript code to load the external file and extract the CSS rules. Yet, this may not be the most practical solution.

Your SVG "sprite document" should ideally avoid containing CSS rules within a <style> tag.

The recommended approach is to prepare your SVGs as sprites beforehand.

A suggestion would be to import your common.svg file into a vector editor and convert all CSS attributes into presentation attributes. For instance, programs like Illustrator offer options for styling when exporting an SVG.

To illustrate, the desired outcome would transform code like:

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

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

into:

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

Answer №2

Based on the Scalable Vector Graphics (SVG) 2 specification outlined in the W3C Editor’s Draft dated June 8, 2021, it appears that the style of the original document should be retained when an element is imported.

Section 5.5 of the 'use' element states:

The copied content inherits styles from the 'use' element and can trigger user events. Despite this, these duplicated element instances stay connected to the referenced source and reflect changes made to the original DOM. Furthermore, all style rules applicable within the scope of the referenced element are also valid within the cloned shadow tree.

Moreover, Section 5.5.3 regarding Style Scoping and Inheritance explains:

The use-element shadow tree, like other shadow trees, exhibits style encapsulation following the guidelines of the CSS Scoping module. This implies that elements within the shadow tree inherit styles from their host 'use' element, while external style rules defined in the main document do not affect elements within the shadow tree. Instead, the shadow tree maintains its distinct list of stylesheets, with CSS rules directly impacting elements within the shadow tree.

When the referenced element originates from an external document, the stylesheet objects created during the processing of that document govern the shadow tree, remaining immutable. All references in the stylesheet, including fragment-only ones, must be absolute relative to the URL of the document containing the referenced element. Web browsers may reuse the same stylesheet objects for any shadow trees referencing the identical external document.

It seems that certain browsers and SVG renderers I have tested are not adhering strictly to the established standard.

I am actively exploring methods to replicate this functionality within existing SVG user agents.

Answer №3

As long as your svg asset code is embedded within the document itself, your styles will be applied.

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


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

If you'd rather not inline svg code, utilizing "fragment identifiers" could be a better approach for embedding.

This concept is similar to creating a sprite sheet where image assets are positioned with offsets on a single pane instead of overlapping symbols.

You can read more about this technique on css.tricks.com
css.tricks.com: How SVG Fragment Identifiers Work

Your svg format would resemble something like this:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32 96" >
    <g id="icon01">
        <path d="M20.6,23.3L14,16.7V7.9h4v7.2l5.4,5.4L20.6,23.3z M16-0.1c-8.8,0-16,7.2-16,16s7.2,16,16,16s16-7.2,16-16S24.8-0.1,16-0.1z  M16,27.9c-6.6,0-12-5.4-12-12s5.4-12,12-12s12,5.4,12,12S22.6,27.9,16,27.9z"/>
    </g>
    <g id="icon02">
        <path d="M32,43.2c0,2.7-1.2,5.1-3,6.8l0,0l-10,10c-1,1-2,2-3,2s-2-1-3-2l-10-10c-1.9-1.7-3-4.1-3-6.8c0-5.1,4.1-9.2,9.2-9.2c2.7,0,5.1,1.2,6.8,3c1.7-1.9,4.1-3,6.8-3C27.9,33.9,32,38.1,32,43.2z"/>
    </g>
    <view id="icon-clock-view" viewBox="0 0 32 32" />
    <view id="icon-heart-view" viewBox="0 32 32 32" />
</svg>

For implementing fragment identifiers, we need to define <view> elements with specific coordinates from the sprite sheet (defined in viewBox attribute).

When embedding in html, simply add the target ID to the src url.

<img class="svg-fragment" src="fragment-ready-1.svg#icon-heart-view">

Although inlining svg graphics in the html provides superior styling control, it's still possible to style remotely embedded svg assets using css files.

We may anticipate additional support for styling external svg assets in the future, but for now, some browser quirks may exist.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm seeking guidance on how to delete a specific ul li element by its id after making an ajax request to delete a corresponding row in MySQL database. I'm unsure about the correct placement for the jQuery

I have created an app that displays a list of income items. Each item is contained within an li element with a unique id, along with the item description and a small trash icon. Currently, I have implemented code that triggers an AJAX call when the user cl ...

Adding a contact form to a slider: A step-by-step guide

Currently, I am faced with the challenge of placing my form on a slider in such a way that the slider appears to be running in the background of the form. When using position absolute, I find myself having to apply excessive margins and top pixels due to t ...

The dimensions of the div are fixed and contains some text

Can someone help me with my coding issue? I created a custom drop-down menu, but the problem is that my content div does not expand to 100% of the width. It seems to be stuck at 160px. Here is the CSS code snippet: .dropdown-content { display: none; po ...

Slide-out left menu using HTML and CSS

Currently, I am in the process of constructing a website that requires a menu to gracefully slide from the left side of the screen (with a width of 0px) to the right side (expanding to a width of 250px), all with the help of jQuery animations. Here is wha ...

HTML table row content should be aligned to the left side

I am attempting to align the data in the 'Address' column without any margin. I want it to start from the left since it's overflowing. You can find the HTML, CSS, and JS code here Even though I tried using <td align="left">..</td& ...

Update the hover effect specifically for mobile devices

.hovereffect a.info,.hovereffect h2{text-transform:uppercase;color:#fff} .hovereffect{float:left;position:relative;cursor:default} .hovereffect .overlay{position:absolute;top:0;left:0;opacity:0;background-color:none;-webkit-transition:all .4s ease-in-out ...

"Utilizing an ellipsis within a span element in a table cell to achieve maximum cell

Update Note: Primarily targeting Chrome (and maybe Firefox) for an extension. However, open to suggestions for a universal solution. Additional Information Note: Discovered that lack of spaces in text for A causing overflow issues with B. Situation seem ...

Adjusting image alignment and formatting long text with CSS in Firefox

I'm attempting to float an image and text within a paragraph, but encountering an issue when the text is long and in one line. The display appears fine in Chrome, but not in Mozilla Firefox. You can view the problem here: In Chrome, it looks like thi ...

"Creating Eye-Catching CSS Animation Effects with Dynamic Initial States

I am looking to understand how I can seamlessly transition from a hover-triggered animation to an exit-hover animation, regardless of where the hover animation is in progress. Currently, if I exit hover too quickly, the animation jumps back to its starting ...

Tips on adjusting the body or HTML to fill the entire page

Currently, I am designing the homepage using the bootstrap Cover page template. The images displayed are just placeholders. While the site functions perfectly on desktop screens, resizing it to smaller sizes causes the grid layout to collapse into a single ...

`Issues with CSS/JQuery menu functionality experienced in Firefox`

After creating a toggleable overlay menu and testing it in various browsers, including Internet Explorer, everything seemed to work fine except for one major issue in Firefox (version 46). The problem arises when toggling the overlay using the "MENU" butt ...

How to insert additional spacing within an input tag class in dynamic HTML using jQuery

When creating an html table dynamically from json data, I encountered an issue with adding space inside my input button control. It seems that after separating two classes with a space, the code is not functioning properly in this snippet environment. Howe ...

Include a navigation bar in the footer of my WordPress Theme's footer.php file

Looking for help with adding a custom footer to my WordPress theme. I have successfully uploaded my static website here, and now I am in the process of making it dynamic. I have added my primary menu to WordPress, but I am unsure of how to exactly add a fo ...

Adjust for the region shifted using transform: translate

I'm currently working on adjusting the positioning of elements using transform: translateY in CSS. The challenge I am facing is eliminating the empty space that appears between elements after repositioning one element below another without altering th ...

Having trouble with applying a class in Gtk3 css?

MY ATTEMPT AND EXPLANATION: In my application, I have the following layout structure: GtkWindow GtkOverlay GtkBox GtkGrid GtkButton Even after trying to apply this CSS style: GtkButton{ background-color:blue; } T ...

What is the best way to align these div elements within a table cell?

I am encountering an issue with the placement of elements. What I am striving for is something like this: https://i.stack.imgur.com/VSFXE.png where a div with several other divs inside is positioned at the top of the td, and another div is at the bottom o ...

Is there a bug causing the Admin LTE content height issue? Looking for solutions to fix it

What's the reason behind the oversized footer? The footer appears normal when I resize or zoom the page, why is that? How can this be resolved? ...

Utilizing gradient effects on table backgrounds with html/css

Trying to enhance my responsive table by adding a gradient background, but encountering an issue where the style being applied is repeating in every cell, creating a messy look. Here's the gradient I'm using: background: linear-gradient(to right ...

Looking for assistance with resizing and repositioning an image within a viewport?

The JSFiddle code can be found at this link - https://jsfiddle.net/pmi2018/smewua0k/211/ Javascript $('#rotate').click(function(e) { updateImage(90, 0) console.log("rotation"); }); $('#zoom-in').click(function() { updateImage(0 ...

Text overlay effect on hovering an image

I am struggling to add text to a photo and make the entire photo clickable with a link. I have already applied a darkening effect that I want to keep, but now I need to insert text on top of it. It is important for me to maintain the current dimensions and ...