skip to Main Content

I have an SVG file in the form of the following:

<svg id="test" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 1435 1084">
<style type="text/css">
    svg{background:red}
</style>
<script type="text/javascript">//<![CDATA[
    const x=1;
    const y=1;

    if (x===y){
        document.getElementById('test').append('<style type="text/css">svg{background:blue}</style>');
    }else{}
//]]></script>
</svg>

What I am trying to do is have a particular script not run when the SVG is embedded as an image object, but function normally when the SVG is embedded as an object or in an iFrame or when opened on its own in a browser. In particular, the code that needs to be blocked when embedded as an image includes a <style> tag.

The CDATA tag appears to be perfect for this job but it has not worked for me.

This has been a bit confusing. I have looked at SVGs that contain CDATA tags and run as expected, but for whatever reason when I do the exact same thing the JS never runs.

Also, bonus points if you can conceive of a concise way to create an SVG that can run different JS in the event it is; viewed standalone, inline, as object, as iframe and as image.

Any suggestions?

I’ve tried a number of things and have found my way to the CDATA tag as the most likely solution.

Edit: Including a code snippet. As I understand it, the SVG should have a blue background in this example but it renders red.

<svg id="test" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 1435 1084">
<style type="text/css">
    svg{background:red}
</style>
<script type="text/javascript">//<![CDATA[
    const x=1;
    const y=1;

    if (x===y){
        document.getElementById('test').append('<style type="text/css">svg{background:blue}</style>');
    }else{}
//]]></script>
</svg>

2

Answers


  1. My guess is that your script is throwing an error because jQuery isn’t available in the environment where you’re trying to run this.

    If jQuery isn’t available, this line will throw an error:

    $('svg').append('<style type="text/css">svg{background:blue}
    

    If jQuery is available, your example works without modification:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <?xml version="1.0" encoding="utf-8"?>
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 1435 1084">
    <style type="text/css">
        svg{background:red}
    </style>
    <script type="text/javascript">//<![CDATA[
        const x=1;
        const y=1;
    
        if (x===y){
            $('svg').append('<style type="text/css">svg{background:blue}</style>');
        }else{}
    //]]></script>
    </svg>

    You don’t need jQuery to do what you’re trying to do. You could do the same thing with built-in browser APIs:

    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 1435 1084">
    <style type="text/css">
        svg{background:red}
    </style>
    <script type="text/javascript">//<![CDATA[
        const x=1;
        const y=1;
    
        if (x===y){
            const style = document.createElement('style');
            style.innerText = "svg{background:blue}";
            document.querySelector('svg').append(style);
        }else{}
    //]]></script>
    </svg>
    Login or Signup to reply.
  2. The browser will not execute scripts inside img elements. Here is no need to block code.

    append() is available on DOM Level 3, but it works differently from what you expect (the jQuery method). String arguments will be appended as text nodes. They will not be parsed.

    So you would need to create the element node and append it. This node has to be in the SVG namespace.

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1435 1084">
      <style type="text/css">
        svg{background:red;}
      </style>
      <script type="text/javascript">//<![CDATA[
        const style = document.documentElement.appendChild(
          document.createElementNS('http://www.w3.org/2000/svg', 'style')
        );
        style.setAttribute( 'type', 'text/css');
        style.append('svg{background:blue !important;}');
      //]]></script>
    </svg>
    

    However to just apply different styles I would add a class to the svg element.

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1435 1084">
      <style type="text/css">
        svg{background:red;}
        svg.Active {background:blue;}
      </style>
      <script type="text/javascript">//<![CDATA[
        document.documentElement.classList.add('Active');
      //]]></script>
    </svg>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search