I can't seem to get my SVG data URL located inside an HTML file within an SVG data URL to display in Chrome

Background

I am encountering an issue where an SVG data URL used as a background image property inside an HTML element within a <foreignObject> nested within an SVG data URL is not rendering properly in Google Chrome. If this structure was outside of an image context, it would render correctly. What could be causing this problem and how can it be resolved?

Wait, what? Why?

Further explanation on the issue will be provided below, including a tree structure and a code snippet to better illustrate the complex scenario described above.

Tree Structure:

  • <img src="data:image/svg+xml;utf8,
    (exhibit A)
    • <svg> (exhibit B)
      • <foreignObject>
        • <html>
          • <div style="background: url('data:image/svg+xml;utf8,
            • <svg> (exhibit C)

Exhibit C is failing to render completely, but if exhibit A is removed so that exhibit B becomes the top-level element, exhibit C renders properly.

Short Code Example:

<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='50'><circle cx='50' cy='25' r='25' fill='blue'/></svg>"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>

<div>As image source:</div>
<img style="position:relative" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,<svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;100&quot; height=&quot;50&quot;><circle cx=&quot;50&quot; cy=&quot;25&quot; r=&quot;25&quot; fill=&quot;blue&quot;/></svg>"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>'>

Additionally, using a PNG data URL instead of an SVG data URL resolves the issue. The problem seems specific to SVG data URLs.

Reason Behind the Issue

The main reason for this problem lies in embedding HTML inside an <img>, which enables HTML rendering on a canvas using context.drawImage. This method is commonly employed by popular libraries like https://github.com/tsayen/dom-to-image. However, complications arise when dealing with embedded SVG content within the HTML, as explained in the question. Various workaround methods have been attempted, including converting innermost SVG data URLs to PNG data URLs before rendering the top-level HTML element.

Another challenge arises when introducing scaling into the process, as scaling PNG images may lead to quality issues. Additionally, applying scaling at different stages can result in image elements becoming too large for their respective containers, further complicating the situation.

(notably, background-image supports scaling, while clip-path does not support scaling - creating additional conversion challenges).

Other Browser Considerations

It's worth noting that Internet Explorer and Edge do not support HTML within <foreignObject>, making the issue irrelevant in those browsers. Firefox supports this feature, but there are still rendering issues with its "standalone" version that need addressing.

Related Discussions

  • Append foreignObject containing some HTML inside an SVG element - focuses on namespace declaration concerns.
  • img Inside a foreignObject Inside an svg Inside an img - discusses external image usage rather than data URLs.

Answer №1

To make sure your code works across different browsers, it is important to encode special characters properly. Specifically, when using encodeURIComponent on the entire <CSSImage url> and then re-encoding the whole markup to pass it into the <img>, everything functions correctly in Chrome.

<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'100'%20height%3D'50'%3E%3Ccircle%20cx%3D'50'%20cy%3D'25'%20r%3D'25'%20fill%3D'blue'%2F%3E%3C%2Fsvg%3E"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>

<div>As image source:</div>
<img style="position:relative" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2275%22%20height%3D%2250%22%20style%3D%22position%3Arelative%22%3E%3Ccircle%20cx%3D%2225%22%20cy%3D%2225%22%20r%3D%2225%22%20fill%3D%22red%22%20%2F%3E%3CforeignObject%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cstyle%3E.x%20%7Bposition%3A%20absolute%3Bbackground%3A%20url(%22data%3Aimage%2Fsvg%2Bxml%3Butf8%2C%253Csvg%2520xmlns%253D'http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg'%2520width%253D'100'%2520height%253D'50'%253E%253Ccircle%2520cx%253D'50'%2520cy%253D'25'%2520r%253D'25'%2530'fill%3D'blue'%2F%253E%253C%252Fsvg%253E%22)%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%7D%3C%2Fstyle%3E%3Cdiv%20class%3D%22x%22%3E%3C%2Fdiv%3E%3C%2Fhtml%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E">

Additionally, please keep in mind that <foreingObject>'s width and height attributes are mandatory in SVG1.1. Omitting them will only work in Chrome.

In order to ensure compatibility with other browsers that have yet to implement this new feature, consider the following modifications:

<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject width="100%" height="100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'100'%20height%3D'50'%3E%3Ccircle%20cx%3D'50'%20cy%3D'25'%20r%3D'25'%20fill%3D'blue'%2F%3E%3C%2Fsvg%3E"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>

<div>As image source:</div>
<img style="position:relative" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2275%22%20height%3D%2250%22%20style%3D%22position%3Arelative%22%3E%3Ccircle%20cx%3D%2225%22%20cy%3D%2225%22%20r%3D%2225%22%20fill%3D%22red%22%20%2F%3E%3CforeignObject%20width%3D%22100%%22%20height%3D%22100%%22%3E%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cstyle%3E.x%20%7Bposition%3A%20absolute%3Bbackground%3A%20url(%22data%3Aimage%2Fsvg%2Bxml%3Butf8%2C%253Csvg%2520xmlns%253D'http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg'%2520width%253D'100'%2520height%253D'50'%2530'%20fill%3D'blue'%2F%253E%253C%252Fsvg%253E%22)%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%7D%3C%2Fstyle%3E%3Cdiv%20class%3D%22x%22%3E%3C%2Fdiv%3E%3C%2Fhtml%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E">

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

Finding a particular sequence of characters and extracting information that comes after it

A while back, I created a website and now I'm looking to transfer the data into a database without manually copying and pasting the 400+ pages it has accumulated. This way, I can transform the site into a database-driven platform. Each page on my sit ...

What is the best way to conceal a section of a div using CSS/React?

I am attempting to create a design where the entire content of a div is displayed initially, and then after clicking a button labeled "show less", only 300px of the content will be shown with the button changing to "show more". <div className="bod ...

What is the best way to access the front camera on both Android and iOS devices in order to capture a photo using Vue.J

I am currently developing a PWA Vue.Js application and I am trying to implement a feature that allows users to take a picture with the front camera on their mobile devices. Although I have managed to write code that works on my desktop browser, I have bee ...

Here is a unique version: "A guide on centering a carousel item in jquery upon being clicked."

Does anyone know how to center the item I click in a carousel? I've searched high and low for a solution but couldn't find a clear answer. Can someone please assist me with this? This is what I have tried so far: http://jsfiddle.net/sp9Jv/ Here ...

The rendering of HTML DOM is being obstructed on iPhone devices running iOS 13

Currently, I'm developing a web-based URL stream music player using JavaScript. The player functions smoothly on Android devices, but I'm encountering an issue with DOM rendering being blocked on iPhone devices. Despite rearranging the JavaScript ...

Identifying when a user is idle on the browser

My current project involves developing an internal business application that requires tracking the time spent by users on a specific task. While users may access additional pages or documents for information while filling out a form, accurately monitoring ...

I'm looking for a way to showcase tasks in Fullcalendar that don't have a set end date

Is there a way to display a task in the full calendar when the task has a start date but no defined end date, such as a promotion that lasts until stock runs out? I would like the timeline for this type of task to extend indefinitely. However, since such ...

Enhance the functionality of a directive by incorporating the ui-mask directive

Recently, I implemented a custom directive for an input field that adds a calendar icon with a datepicker to the input. I have used this directive in various sections of my application and now I am interested in incorporating ui-mask - another directive I ...

Section is obstructing the view of Other Section above

I am struggling to create a responsive design for these two sections, both of which display quite similarly in line. Here are the resolutions for desktop and tablet/mobile: https://i.sstatic.net/XWbSP.png https://i.sstatic.net/3KLyY.png I suspect the is ...

Automate the process of modifying specific data in tables through Javascript

I've been attempting to replicate the appearance of a stock-exchange board, but I'm encountering difficulties in updating text automatically without interrupting another. My attempts so far: var textPositive = ["2.0%", "1.7%" ...

What is the best way to create a navigation link in PHP along with forms?

If the login credentials are correct, I will be directed to the member page. If not, I should remain on the same page. I am struggling with how to create a link to another page. I have come across some suggestions involving headers, but I am still unsure o ...

Separate your HTML code and move it to a different HTML document within Angular CLI

Is there a way to extract my HTML section from the file app.compontent.ts and place it in a separate HTML document? I've tried adding the HTML code directly into the generated class app.component.ts but it doesn't seem to work. I'd also lik ...

Is it possible to maintain a fixed footer while utilizing async/ajax functions?

Looking for a reliable solution to have a fixed footer that adjusts based on the page content? I've tested multiple samples, but they all fall short when it comes to incorporating AJAX elements. Is there a fixed footer out there that truly works seaml ...

Adjusting the width of a div element using a button

I am currently diving into the world of JavaScript, React, and Node.js. My current challenge involves attempting to adjust the width of a div element using a button. However, I keep encountering the same frustrating error message stating "Cannot read prope ...

Increase the parent height by 100% when the child element expands

I am attempting to create a full-screen website with 100% height and no scrollbar. I have a div that takes up 90% of the page height and I want to dynamically add elements inside it. However, when there are too many elements inside this div, they expand th ...

How to vertically align content using Zurb Foundation's equalizer feature?

I am currently utilizing Zurb Foundation 5 along with the equalizer component. In a scenario where I have three columns of equal width, I am aiming to achieve vertical center alignment for the content (text) in the middle column and vertical bottom alignme ...

Ways to remove the initial row of inline-block divs

My webpage is filled with inline-block divs that are contained within a larger div like so: <div class="container"> <div class="text">Text 1</div> <div class="text">Text 2 ... rest of the nu ...

Can one determine if a webpage is being displayed within an Infragistics igDialog?

Occasionally, my web page is displayed without a container and other times it's embedded within an igDialog of another container page, based on the user's navigation throughout our web application. Is there a way, using pure javascript or jQuery ...

Deploying CSS/JS files in Magento 2 is a crucial

Hello, I recently set up magento2 with the sample data included. After attempting to deploy static css/JS using the command php bin/magento setup:static-content:deploy, I didn't receive any errors but the issue persists. Additionally, I am unable to l ...

I aim to utilize vanilla JavaScript in order to remove the parent element of the button being clicked when the user interacts with it

My latest project involves a meme generator that allows users to input text and images, which are then combined to create a unique 'meme'. Each meme is assigned a unique ID and features buttons for deleting the meme upon hovering. To achieve this ...