1

I have enabled SVG-file-linking on my WP site using the Safe SVG plug-in, and I'm mostly happy with it. However, I'm having an issue with styling the SVG-paths contained in the external-file I am calling/linikng. Currently, I am unable to create the interactivitiy I desire because I cannot:

  1. use my custom javascript/jQuery to add classes to the individual SVG paths (it works with all my inline svgs, just not the externally linked ones);
  2. change the fills/opacity of the SVG paths in my style.css file, using the the jQuery applied classes.

When I use inline SVG, I can control everything the way I want, my jQuery and CSS work. But when I use the external file using the Safe SVG plug-in, my CSS doesn't seem to interact with the path-elements nor to modify them.

I have found information that speaks to this problem, in-general and beyond WordPress, about CSS and external SVGs (for example this), but I was wondering if anyone here might have an efficient, simple WordPress-based solution that would allow 1) my jQuery scripts to access and modify the path classes and 2) my CSS to modify the path-elements.

I realize I just go the inline route and save myself the hassle, but I have reasons for wanting to see if I can't accomplish this with independent SVG-files.

Thanks!

2 Answers 2

1

Sorry to say, but it's not possible, because none of the elements from the SVG are read in the DOM, so CSS and Javascript don't see them. All it sees is the <img> block, none of its contents. You have to import your SVGs into the page to have them be able to be manipulated.

Check out the CSS Tricks article on SVGs

2
  • Your answer was helpful (because I didn't know that img tags always prevented svg content from being visible to the DOM.) Though your answer is not completely correct (you can inject SVGs with Js), it, along with this link you posted on another of my questions, core.trac.wordpress.org/ticket/24251 , did aide me in finding the answer I posted. I would upvote you but I only have 8 rep and cannot yet. Thank you! Commented Nov 24, 2016 at 19:47
  • Yeah, sorry, import may have been an incomplete term, but anything that gets you to manipulate the DOM, whether back or front end, you can use it to inject SVGs. Either way, as long as the entire XML structure is represented in the DOM, then you can manipulate it.
    – socki03
    Commented Nov 24, 2016 at 20:02
1

I have found two imperfect but functional solutions, each with its own limitations.

Please note, before you can employ either of the solutions, you will need to enable SVG uploading to your page first (as WP does not allow it by default). You can do this by using a plugin like Safe SVG.

The solution I chose in the end actually doesn't require any jQuery at all. It involves using a popular WP plug-in called "Advanced Custom Fields" (or ACF) and adding some php to your templates. The second solution is one which I found in one of the SVG discussion threads posted by socki03 in a different question (which I happened to have asked); it uses a jQuery library called SVGinjector.

Solution #1: Advanced Custom Fields(ACF)

This solution is the one I chose to implement, and I found it in this discussion thread. It isn't ideal because you have to add some code explicitly to your templates, (instead of being able to add everything in in the WP dashboard). So, If you go this route, you should to know a bit about editing template files.

What the ACF solution does

Once you set-up the ACF plug-in appropriately and place the code in your template, you will field in your dashboard which you allows you to select an SVG file. It is great because that SVG is really a part of the page, which is modifyiable with CSS, and loads with all of the other elements early on.

How to implement it

  1. Install the ACF plugin.
  2. Using the ACF-plugin, follow the steps to create an image field that returned the image URL.

    2.1. go to the dashboard

    2.2. select the custom fields section (it is part of the ACF plugin)

    2.3. at the top of the page it says "Field Groups", select the "add new" button next to it.

    2.4. Create the field

    • 2.4.1. designate the "field name", and the select the appropriate options. You need to making sure to select the "image" for the "field type" option.

    • 2.4.2. After you select "image" from the "field type" options, a new option, "Return URL", will appear. It is that option that is going to generate the code that will grab your images. Choose "Return URL"

3.Open the php file for the template you want to add the svg to.

  1. Inside your php file, insert this code anywhere you want the SVG to appear: <?php echo file_get_contents( get_field( 'the_svg_field_name_you_designated' ) ); ?> and save your file.

  2. Go back to the WP dashboard, go to "pages", and navigate to the "edit" screen for the page you want the SVG to appear in. You should now have field with the "field name" you entered that will you to select an image.

  3. Click on the button near the field name, it should then prompt you to navigate your files. Navigate to the SVG file you want to upload, and select it.

  4. Click on "Update" to finalize the SVG insertion. You should now have SVGs that load as part of the page, which you can edit/stylize with CSS.

Pros:

The code that inserts the SVG executes as the page loads, so the SVG element is part of the foundations fo the page, rather than being "added-on" later (whic is the problem with the other solution).

Cons:

Because the SVG is called from a separate file, and not combined in any meaingful way with other code on the page, all of the classes must be manually inserted into the SVG file. That means if you want to have two different versions of the same SVG, with different classes, you have two use two different files. However, you can work around this limitation, and still use the same file for two differently styled SVGs, by editing the parent classes in the templages and then using those classes to stylize the two different files (e.g. .parentForStyle1 svg and .parentForStyle2 svg).

Also, with this method you have to modify your code a bit more, than in the other case, but it really isn't too bad.

Solution #2: SVGInjector

This did what I wanted, in that it allowed me to add SVGs that are visible to the DOM and stylizable with CSS, but it has one problem. Because it uses an enqueued script, it doesn't run until after the page has loaded the other elements. As such, can cause weird shifts/blinks while the page loads and and after excutes.

What SVGinjector does

When implemented, SVGinjector:

  1. calls a separate SVG file as an img element;
  2. uses javascript to parse the SVG and inject the SVG as an inline element; visible to the DOM.
  3. allows the designer to employ CSS to stylize the individual SVG paths/elements.
  4. converts the img element to an svg element, and combines any header info from the existing img tag and the SVG-file into the SVG-tag.

How to implement it

  1. In your template file, add a class called inject-me to your img element where you want to have the SVG drawn, and in the img tag link the SVG file to the img using data-src instead of src. Here is the working code I put in my template file: <img class="funkyLogo inject-me" data-src="<?php echo $logoImg; ?>" alt="logo" />
  2. enqueue the js script "svg-injector.min.js" (which is in the SVG injector .zip file) in your "functions.php", along with your custom js:

    function mytheme_enqueue_front_page_scripts() {
    if( is_front_page() )
    {
        wp_enqueue_script( 'myJq', "/js/jquery-1.10.2.min.js", array( 'jquery' ), null, true );
        wp_enqueue_script( 'injectSVG', get_stylesheet_directory_uri() . '/js/svg-injector.min.js', array( 'jquery' ), null, true );
        wp_enqueue_script( 'custom', get_stylesheet_directory_uri() . '/js/custom.js', array( 'jquery' ), null, true );

    } } add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_front_page_scripts' );

  3. include the following code in your "custom.js" file

    //For testing in IE8
    if (!window.console){ console = {log: function() {}}; };
    
    // Elements to inject
      var mySVGsToInject = document.querySelectorAll('img.inject-me');
    
    // Options
      var injectorOptions = {
        evalScripts: 'once',
        pngFallback: 'assets/png',
        each: function (svg) {
          // Callback after each SVG is injected
          if (svg) console.log('SVG injected: ' + svg.getAttribute('id'));
        }
      };
    
      // Trigger the injection
      SVGInjector(mySVGsToInject, injectorOptions, function (totalSVGsInjected) {
        // Callback after all SVGs are injected
        console.log('We injected ' + totalSVGsInjected + ' SVG(s)!');
      });
    

Pros:

It is simple, uses an img tag, and it is easy to edit classes in templates

Cons:

the SVGs are drawn later in the page drawing process, and this can cause weird rendering effects/blinking/changes in the pages while loading. I am currently using customizer and have my SVG designated as my header logo. Maybe it is happening because data-src tag is confusing Wordpress, so before the js for SVG runs, the theme temporarily shows the alt designated text "logo" in the img tag. If I remove the alt text, the div is empty for about half a second before the SVG is injected, but this causes an odd and undesirable shifting of elements on the page during the injection.

Alternately, the issue might have to do with order in which js is execute when drawing the page. I have learned that enqueued js always runs after page loading, so the fact that this is controlled via js, at the end of the loading process is very likely what is causing the blink. If someone can suggest a solution for that uses SVG injector, but doesn't cause a blink, it would be nice to see it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.