ChatGPT解决这个技术问题 Extra ChatGPT

How to change color of SVG image using CSS (jQuery SVG image replacement)?

This is a self Q&A of a handy piece of code I came up with.

Currently, there isn't an easy way to embed an SVG image and then have access to the SVG elements via CSS. There are various methods of using JS SVG frameworks, but they are overly complicated if all you are doing is making a simple icon with a rollover state.

So here is what I came up with, which I think is by far the easiest way to use SVG files on a website. It takes its concept from the early text-to-image replacement methods, but as far as I am aware has never been done for SVGs.

This is the question:

How do I embed an SVG and change its color in CSS without using a JS-SVG framework?

Unfortunately the img tag doesn't work with svg files in IE, so keep in mind that. IE recognize embed tags. Anyway, nice job!
For svg, you should use the "fill" css property. For images it's appropriate to use "filter". "Filter" does in fact work for both but it is unnecessary to do all of that work for a vector graphic.

c
cheesus

Firstly, use an IMG tag in your HTML to embed an SVG graphic. I used Adobe Illustrator to make the graphic.

<img id="facebook-logo" class="svg social-link" src="/images/logo-facebook.svg"/>

This is just like how you'd embed a normal image. Note that you need to set the IMG to have a class of svg. The 'social-link' class is just for examples sake. The ID is not required, but is useful.

Then use this jQuery code (in a separate file or inline in the HEAD).

    /**
     * Replace all SVG images with inline SVG
     */
        jQuery('img.svg').each(function(){
            var $img = jQuery(this);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

            jQuery.get(imgURL, function(data) {
                // Get the SVG tag, ignore the rest
                var $svg = jQuery(data).find('svg');

                // Add replaced image's ID to the new SVG
                if(typeof imgID !== 'undefined') {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if(typeof imgClass !== 'undefined') {
                    $svg = $svg.attr('class', imgClass+' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        });

What the above code does is look for all IMG's with the class 'svg' and replace it with the inline SVG from the linked file. The massive advantage is that it allows you to use CSS to change the color of the SVG now, like so:

svg:hover path {
    fill: red;
}

The jQuery code I wrote also ports across the original images ID and classes. So this CSS works too:

#facebook-logo:hover path {
    fill: red;
}

Or:

.social-link:hover path {
    fill: red;
}

You can see an example of it working here: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

We have a more complicated version that includes caching here: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90


This is awesome! I've been looking for a way to keep the markup clean, but still allow access to the svg "innards" for use in CSS. This should work, but I'm getting an error with the JS: "XMLHttpRequest cannot load file:///H:/svg/test/test.svg. Origin null is not allowed by Access-Control-Allow-Origin." Any ideas?
My guess is because you are running it locally and getting a cross domain problem. Put it on a server and it should work.
If you put this in the onDocumentReady handler, you may get the FOUC (flash of unstyled content) effect where it renders the original tags before replacing them with the . If there were some way to run this immediately before each tag is rendered, it would be perfect. I suppose you could also use CSS to hide 'img.svg' elements so they only render after the replacement occurs.
It may sometimes not work in Safari (for e.g.), to ensure returned data is readable, remplace the }); of $.get with }, 'xml');
You could probably even replace the selector with img[src$=".svg"] and eliminate the need for the svg class.
H
Henrik Albrechtsson

Style

svg path {
    fill: #000;
}

Script

$(document).ready(function() {
    $('img[src$=".svg"]').each(function() {
        var $img = jQuery(this);
        var imgURL = $img.attr('src');
        var attributes = $img.prop("attributes");

        $.get(imgURL, function(data) {
            // Get the SVG tag, ignore the rest
            var $svg = jQuery(data).find('svg');

            // Remove any invalid XML tags
            $svg = $svg.removeAttr('xmlns:a');

            // Loop through IMG attributes and apply on SVG
            $.each(attributes, function() {
                $svg.attr(this.name, this.value);
            });

            // Replace IMG with SVG
            $img.replaceWith($svg);
        }, 'xml');
    });
});

If you don't have a width attr, it just creates one with a wrong number. width="170.667" in my case
This isnt perfect since it loses the previous img dimensions.
Hello suppose i have different svg with differnet color each. Using this method, all my svg colors become the same as the first svg that is being looped. Any idea how can I maneuver around this so each color stays the same as before?
note that if your svg is made also from non-path shapes (like rect) you'd need to handle them in css as well
B
Brian Burns

You can now use the CSS filter property in most modern browsers (including Edge, but not IE11). It works on SVG images as well as other elements. You can use hue-rotate or invert to modify colors, although they don't let you modify different colors independently. I use the following CSS class to show a "disabled" version of an icon (where the original is an SVG picture with saturated color):

.disabled {
    opacity: 0.4;
    filter: grayscale(100%);
    -webkit-filter: grayscale(100%);
}

This makes it light grey in most browsers. In IE (and probably Opera Mini, which I haven't tested) it is noticeably faded by the opacity property, which still looks pretty good, although it's not grey.

Here's an example with four different CSS classes for the Twemoji bell icon: original (yellow), the above "disabled" class, hue-rotate (green), and invert (blue).

.twa-bell { background-image: url("https://twemoji.maxcdn.com/svg/1f514.svg"); display: inline-block; background-repeat: no-repeat; background-position: center center; height: 3em; width: 3em; margin: 0 0.15em 0 0.3em; vertical-align: -0.3em; background-size: 3em 3em; } .grey-out { opacity: 0.4; filter: grayscale(100%); -webkit-filter: grayscale(100%); } .hue-rotate { filter: hue-rotate(90deg); -webkit-filter: hue-rotate(90deg); } .invert { filter: invert(100%); -webkit-filter: invert(100%); }


Just noticed that invert is good solution if you don't want to create icon fonts. I used this jQuery code to change icon in my website's header according to css color property (notice that I am using white png icons): if ($('.w3-top img').css("color") == "rgb(0, 0, 0)") { $('.w3-top img').css("filter", "invert(100%)"); $('.w3-top img').css("-webkit-filter", "invert(100%)"); };
Great approach. Edited my SVG xml to add the target icon color then used an .icon-disabled class to gray it out.
Notice that old Explores doesn't support filter: w3schools.com/cssref/css3_pr_filter.asp
p
paulalexandru

Alternatively you could use CSS mask, granted browser support isn't good but you could use a fallback

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}

MDN specifies that -webkit-mask should not be used on any production website.
doesn't color the svg
Maybe it's relevant to say that now, four years later, this solution is working in all major browsers. Just tested here and it's 100% ok.
t
trebor1979

If you can include files (PHP include or include via your CMS of choice) in your page, you can add the SVG code and include it into your page. This works the same as pasting the SVG source into the page, but makes the page markup cleaner.

The benefit is that you can target parts of your SVG via CSS for hover -- no javascript required.

http://codepen.io/chriscoyier/pen/evcBu

You just have to use a CSS rule like this:

#pathidorclass:hover { fill: #303 !important; }

Note that the !important bit is necessary to override the fill color.


For those using AngularJS: <div ng-include="'svg.svg'"></div>
Not a very elegant solution storing svg data in a database though. Not wrong, but pumping out xml/html/svg DOM data from an API or CMS rather than using templates or other assets just feels wrong.
Additionally, if your SVG has transparent areas, these won't count as hovering and you may experience "flashy hover". To fix that, just add a wrapper element (an <a>, if it's convenient) and then add that to the CSS rule. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; } Or even just eliminate the original hover of the SVG path since you are targeting it via the wrapper element now anyway.
A
AhrenFullStop

TL/DR: GO here-> https://codepen.io/sosuke/pen/Pjoqqp

Explanation:

I'm assuming you have html something like this:

<img src="/img/source.svg" class="myClass">

Definitely go the filter route, ie. your svg is most likely black or white. You can apply a filter to get it to be whatever color you want, for example, I have a black svg that I want mint green. I first invert it to be white (which is technically all RGB colors on full) then play with the hue saturation etc. To get it right:

filter: invert(86%) sepia(21%) saturate(761%) hue-rotate(92deg) brightness(99%) contrast(107%);

Even better is that you could just use a tool to convert the hex you want into a filter for you: https://codepen.io/sosuke/pen/Pjoqqp


M
Max

@Drew Baker gave a great solution to solve the problem. The code works properly. However, those who uses AngularJs may find lots of dependency on jQuery. Consequently, I thought it is a good idea to paste for AngularJS users, a code following @Drew Baker's solution.

AngularJs way of the same code

1. Html: use the bellow tag in you html file:

<svg-image src="/icons/my.svg" class="any-class-you-wish"></svg-image>

2. Directive: this will be the directive that you will need to recognise the tag:

'use strict';
angular.module('myApp')
  .directive('svgImage', ['$http', function($http) {
    return {
      restrict: 'E',
      link: function(scope, element) {
        var imgURL = element.attr('src');
        // if you want to use ng-include, then
        // instead of the above line write the bellow:
        // var imgURL = element.attr('ng-include');
        var request = $http.get(
          imgURL,
          {'Content-Type': 'application/xml'}
        );

        scope.manipulateImgNode = function(data, elem){
          var $svg = angular.element(data)[4];
          var imgClass = elem.attr('class');
          if(typeof(imgClass) !== 'undefined') {
            var classes = imgClass.split(' ');
            for(var i = 0; i < classes.length; ++i){
              $svg.classList.add(classes[i]);
            }
          }
          $svg.removeAttribute('xmlns:a');
          return $svg;
        };

        request.success(function(data){
          element.replaceWith(scope.manipulateImgNode(data, element));
        });
      }
    };
  }]);

3. CSS:

.any-class-you-wish{
    border: 1px solid red;
    height: 300px;
    width:  120px
}

4. Unit-test with karma-jasmine:

'use strict';

describe('Directive: svgImage', function() {

  var $rootScope, $compile, element, scope, $httpBackend, apiUrl, data;

  beforeEach(function() {
    module('myApp');

    inject(function($injector) {
      $rootScope = $injector.get('$rootScope');
      $compile = $injector.get('$compile');
      $httpBackend = $injector.get('$httpBackend');
      apiUrl = $injector.get('apiUrl');
    });

    scope = $rootScope.$new();
    element = angular.element('<svg-image src="/icons/icon-man.svg" class="svg"></svg-image>');
    element = $compile(element)(scope);

    spyOn(scope, 'manipulateImgNode').andCallThrough();
    $httpBackend.whenGET(apiUrl + 'me').respond(200, {});

    data = '<?xml version="1.0" encoding="utf-8"?>' +
      '<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->' +
      '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' +
      '<!-- Obj -->' +
      '<!-- Obj -->' +
      '<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
      'width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">' +
        '<g>' +
          '<path fill="#F4A902" d=""/>' +
          '<path fill="#F4A902" d=""/>' +
        '</g>' +
      '</svg>';
    $httpBackend.expectGET('/icons/icon-man.svg').respond(200, data);
  });

  afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  it('should call manipulateImgNode atleast once', function () {
    $httpBackend.flush();
    expect(scope.manipulateImgNode.callCount).toBe(1);
  });

  it('should return correct result', function () {
    $httpBackend.flush();
    var result = scope.manipulateImgNode(data, element);
    expect(result).toBeDefined();
  });

  it('should define classes', function () {
    $httpBackend.flush();
    var result = scope.manipulateImgNode(data, element);
    var classList = ["svg"];
    expect(result.classList[0]).toBe(classList[0]);
  });
});

your solution does not work, could be <div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
@guillaumevincent if you want to use it with ng-include then just change this line var imgURL = element.attr('src'); to var imgURL = element.attr('ng-include');
This is a very handy solution, but be careful in overusing it as it can hit performance pretty hard - I.E. a set of 5 sharing icons repeated on an article listing or something like that.
There is a problem with your code in IE. You can use just if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); } instead of split and for loop.
Awesome work! But for certain image you need to grab the first element of the svg (angular.element(data)[0];) and to make it work with IE use if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. Also you might want to add cache: true to the options of $http.get otherwise your page might become very slow.
D
DShultz

I realize you're wanting to accomplish this with CSS, but just a reminder in case it's a small, simple image - you can always pop it open in Notepad++ and change the path/whateverelement's fill:

<path style="fill:#010002;" d="M394.854,205.444c9.218-15.461,19.102-30.181,14.258-49.527
    ...
    C412.843,226.163,402.511,211.451,394.854,205.444z"/>

It could save a ton of ugly script. Sorry if it's off-base, but sometimes the simple solutions can be overlooked.

...even swapping multiple svg images might be smaller in size than some of the code snippets for this question.


O
Omri Aharon

I wrote a directive to solve this issue with AngularJS. It is available here - ngReusableSvg.

It replaces the SVG element after it's been rendered, and places it inside a div element, making its CSS easily changeable. This helps using the same SVG file in different places using different sizes/colors.

The usage is simple:

<object oa-reusable-svg
        data="my_icon.svg"
        type="image/svg+xml"
        class="svg-class"
        height="30"  // given to prevent UI glitches at switch time
        width="30">
</object>

After that, you can easily have:

.svg-class svg {
    fill: red; // whichever color you want
}

Hi, thanks for providing this solution. I've tried it and it yields:
[[object SVGSVGElement]]
In the html it then just puts [[object SVGSVGElement]]. Do you know what's the problem? Another question, does it have a large impact on performance or can I use it on many svg's on a page? And lastly, it's still on angular 1.3 (the bower).
Which version of angular are you using? Haven't encountered your issue.. maybe it's something with the SVG? Performance-wise the switch is relatively heavy, I've used it myself on like 10 and it was fine.. I guess that depends on amount/size, so trial and experiment with it. What's the problem with the bower? Are you using a different version and there's a conflict?
S
Simon_Weaver

Here's a version for knockout.js based on the accepted answer:

Important: It does actually require jQuery too for the replacing, but I thought it may be useful to some.

ko.bindingHandlers.svgConvert =
    {
        'init': function ()
        {
            return { 'controlsDescendantBindings': true };
        },

        'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
        {
            var $img = $(element);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

            $.get(imgURL, function (data)
            {
                // Get the SVG tag, ignore the rest
                var $svg = $(data).find('svg');

                // Add replaced image's ID to the new SVG
                if (typeof imgID !== 'undefined')
                {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if (typeof imgClass !== 'undefined')
                {
                    $svg = $svg.attr('class', imgClass + ' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        }
    };

Then just apply data-bind="svgConvert: true" to your img tag.

This solution completely replaces the img tag with a SVG and any additional bindings would not be respected.


This is great! If you want to take it to the next level, we have an updated version that includes caching, so the same SVG isn't requested twice. github.com/funkhaus/style-guide/blob/master/template/js/…
I was a bit worried about that but didn't have time to look into it myself. Just needed something quick
@DrewBaker actually I was more concerned that the img tag would request the file and then the get would request it again. I considered changing the src to a data-src attribute on the img tag, but concluded that modern browsers are probably smart enough to cache the file anyway
W
Waruyama

There is an open source library called SVGInject that uses the onload attribute to trigger the injection. You can find the GitHub project at https://github.com/iconfu/svg-inject

Here is a minimal example using SVGInject:

<html>
  <head>
    <script src="svg-inject.min.js"></script>
  </head>
  <body>
    <img src="image.svg" onload="SVGInject(this)" />
  </body>
</html>

After the image is loaded the onload="SVGInject(this) will trigger the injection and the <img> element will be replaced by the contents of the SVG file provided in the src attribute.

It solves several issues with SVG injection:

SVGs can be hidden until injection has finished. This is important if a style is already applied during load time, which would otherwise cause a brief "unstyled content flash". The elements inject themselved automatically. If you add SVGs dynamically, you don't have to worry about calling the injection function again. A random string is added to each ID in the SVG to avoid having the same ID multiple times in the document if an SVG is injected more than once.

SVGInject is plain Javascript and works with all browsers that support SVG.

Disclaimer: I am the co-author of SVGInject


u
user3144480

Here's a no framework code, only pure js :

document.querySelectorAll('img.svg').forEach(function(element) {
            var imgID = element.getAttribute('id')
            var imgClass = element.getAttribute('class')
            var imgURL = element.getAttribute('src')

            xhr = new XMLHttpRequest()
            xhr.onreadystatechange = function() {
                if(xhr.readyState == 4 && xhr.status == 200) {
                    var svg = xhr.responseXML.getElementsByTagName('svg')[0];

                    if(imgID != null) {
                         svg.setAttribute('id', imgID);
                    }

                    if(imgClass != null) {
                         svg.setAttribute('class', imgClass + ' replaced-svg');
                    }

                    svg.removeAttribute('xmlns:a')

                    if(!svg.hasAttribute('viewBox') && svg.hasAttribute('height') && svg.hasAttribute('width')) {
                        svg.setAttribute('viewBox', '0 0 ' + svg.getAttribute('height') + ' ' + svg.getAttribute('width'))
                    }
                    element.parentElement.replaceChild(svg, element)
                }
            }
            xhr.open('GET', imgURL, true)
            xhr.send(null)
        })

A
Abhishek Borar

If we have a greater number of such svg images we can also take the help of font-files.
Sites like https://glyphter.com/ can get us a font file from our svgs.

E.g.

@font-face {
    font-family: 'iconFont';
    src: url('iconFont.eot');
}
#target{
    color: white;
    font-size:96px;
    font-family:iconFont;
}

I personally hate the "images as a font" technique. It makes it hard to add/edit images, adds a lot of nonsensical markup. Font's should be fonts, images should be images etc.
Agreed. You also need to remember/lookup the images assigned to characters. but for the specific case where images are used as icons/button/bullets, act more as text than media, font-files can also be an alternative
even github don't use font anymore for icon github.com/blog/2112-delivering-octicons-with-svg
p
patelarpan

You can use data-image for that. using data-image(data-URI) you can access SVG like inline.

Here is rollover effect using pure CSS and SVG.

I know it messy but you can do this way.

.action-btn { background-size: 20px 20px; background-position: center center; background-repeat: no-repeat; border-width: 1px; border-style: solid; border-radius: 30px; height: 40px; width: 60px; display: inline-block; } .delete { background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#FB404B' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e "); border-color:#FB404B; } .delete:hover { background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#fff' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e "); background-color: #FB404B; }  

You can convert your svg to data url here

https://codepen.io/elliz/full/ygvgay https://websemantics.uk/tools/svg-to-background-image-conversion/


This wouldn't work for complex SVGs where you only want certain paths/polygons/etc.. to change on hover right?
No you can..but it very complex
It just solutions for icon
If some work with icon. Then it great. Bootstrap 4 also use this technic
B
Benjamin

Since SVG is basically code, you need just contents. I used PHP to obtain content, but you can use whatever you want.

<?php
$content    = file_get_contents($pathToSVG);
?>

Then, I've printed content "as is" inside a div container

<div class="fill-class"><?php echo $content;?></div>

To finnaly set rule to container's SVG childs on CSS

.fill-class > svg { 
    fill: orange;
}

I got this results with a material icon SVG:

Mozilla Firefox 59.0.2 (64-bit) Linux

https://i.stack.imgur.com/hny3K.jpg

Google Chrome66.0.3359.181 (Build oficial) (64 bits) Linux

https://i.stack.imgur.com/shBNk.jpg

Opera 53.0.2907.37 Linux

https://i.stack.imgur.com/bcnwH.jpg


J
Johann

The selected solution is fine if you want jQuery to process all svg elements in your DOM and your DOM is of reasonable size. But if your DOM is large and you decide to load parts of your DOM dynamically, it really makes no sense to have to rescan the entire DOM just to update svg elements. Instead, use a jQuery plugin to do this:

/**
 * A jQuery plugin that loads an svg file and replaces the jQuery object with its contents.
 *
 * The path to the svg file is specified in the src attribute (which normally does not exist for an svg element).
 *
 * The width, height and class attributes in the loaded svg will be replaced by those that exist in the jQuery object's
 * underlying html. Note: All other attributes in the original element are lost including the style attribute. Place
 * any styles in a style class instead.
 */
(function ($) {
    $.fn.svgLoader = function () {
        var src = $(this).attr("src");
        var width = this.attr("width");
        var height = this.attr("height");
        var cls = this.attr("class");
        var ctx = $(this);

        // Get the svg file and replace the <svg> element.
        $.ajax({
            url: src,
            cache: false
        }).done(function (html) {
            let svg = $(html);
            svg.attr("width", width);
            svg.attr("height", height);
            svg.attr("class", cls);
            var newHtml = $('<a></a>').append(svg.clone()).html();
            ctx.replaceWith(newHtml);
        });

        return this;
    };

}(jQuery));

In your html, specify an svg element as follows:

<svg src="images/someSvgFile.svg" height="45" width="45" class="mySVGClass"/>

And apply the plugin:

$(".mySVGClass").svgLoader();

Yeah there are certainly more efficient ways to use the code I gave. Here is how we actually use it on production sites. It caches SVGs! github.com/funkhaus/style-guide/blob/master/template/js/…
g
ghett

for :hover event animations we can left the styles inside svg file, like a

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
  <style>
  rect {
    fill:rgb(165,225,75);
    stroke:none;
    transition: 550ms ease-in-out;
    transform-origin:125px 125px;
  }
  rect:hover {
    fill:rgb(75,165,225);
    transform:rotate(360deg);
  }
  </style>
</defs>
  <rect x='50' y='50' width='150' height='150'/>
</svg>

check this on svgshare


f
fahimeh ahmadi
.carousel-control-prev-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='rgb(3,122,247)' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e");
}

chnage color : fill='rgb(3,122,247)'