it-swarm.com.ru

Как стилизовать SVG с помощью внешнего CSS?

У меня есть несколько SVG-графики, которые я хотел бы изменить цвета с помощью внешних таблиц стилей, а не непосредственно в каждом SVG-файле. Я не помещаю графику в линию, но храню их в своей папке изображений и указываю на них.

Я реализовал их таким образом, чтобы всплывающие подсказки работали, и также обернул их в тег <a>, чтобы разрешить ссылку.

<a href='http://youtube.com/...' target='_blank'><img class='socIcon' src='images/socYouTube.svg' title='View my videos on YouTube' alt='YouTube' /></a>

А вот код SVG-графики:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
    <path d="M28.44......./>
</g>
</svg>

Я поместил следующее в моем внешнем файле CSS (main.css):

.socIcon g {fill:red;}

Тем не менее, это не влияет на графику. Я также пробовал .socIcon g path {} и .socIcon path {}.

Что-то не так, возможно, моя реализация не допускает внешних модификаций CSS, или я пропустил шаг? Буду очень признателен за вашу помощь! Мне просто нужна возможность изменять цвета графики SVG через мою внешнюю таблицу стилей, но я не могу потерять всплывающую подсказку и возможность ссылки. (Хотя я могу жить без подсказок.) Спасибо!

70
Jordan H

Ваш файл main.css будет влиять только на содержимое SVG, если файл SVG включен в HTML:

https://developer.mozilla.org/en/docs/SVG_In_HTML_Introduction

<html>
  <body>
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
      <path d="M28.44......./>
    </g>
  </svg>
</html>

Если вы хотите сохранить SVG в файлах, CSS должен быть определен внутри SVG-файла. 

Вы можете сделать это с тегом стиля:

http://www.w3.org/TR/SVG/styling.html#StyleElementExample

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width="50px" height="50px" viewBox="0 0 50 50">
  <defs>
    <style type="text/css"><![CDATA[
      .socIcon g {
        fill:red;
      }
    ]]></style>
  </defs>
  <g>
    <path d="M28.44......./>
  </g>
</svg>

Вы можете использовать инструмент на стороне сервера для обновления тега стиля в зависимости от активного стиля. В Ruby вы можете достичь этого с помощью Nokogiri. SVG - это просто XML. Так что, вероятно, есть много доступных библиотек XML, которые могут достичь этого.

Если вы не можете этого сделать, вам просто нужно использовать их, как если бы они были PNG; создавая набор для каждого стиля и сохраняя их стили встроенными.

70
RGB

Вы можете делать то, что вы хотите, с одним (важным) предупреждением: пути внутри вашего символа не могут быть стилизованы независимо с помощью внешнего CSS - вы можете установить свойства только для всего символа с помощью этого метода. Итак, если у вас есть два пути в вашем символе и вы хотите, чтобы они имели разные цвета заливки, это не сработает, но если вы хотите, чтобы все ваши пути были одинаковыми, это должно сработать.

В вашем HTML-файле вы хотите что-то вроде этого:

<style>
  .fill-red { fill: red; }
  .fill-blue { fill: blue; }
</style>

<a href="//www.example.com/">
  <svg class="fill-red">
    <use xlink:href="images/icons.svg#example"></use>
  </svg>
</a>

А во внешнем файле SVG вы хотите что-то вроде этого:

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol id="example" viewBox="0 0 256 256">
    <path d="M120.... />
  </symbol>
</svg>

Поменяйте класс на теге svg (в вашем html) с fill-red на fill-blue и ta-da ... у вас синий вместо красного.

Вы можете частично обойти ограничение возможности нацеливать пути отдельно с помощью внешнего CSS, смешивая и сопоставляя внешний CSS с некоторым встроенным CSS на определенных путях, поскольку встроенный CSS будет иметь приоритет. Этот подход будет работать, если вы делаете что-то вроде белого значка на цветном фоне, где вы хотите изменить цвет фона с помощью внешнего CSS, но сам значок всегда белый (или наоборот). Итак, с тем же HTML-кодом, что и раньше, и чем-то вроде этого svg-кода, вы получите красный фон и белый путь переднего плана:

<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="example" viewBox="0 0 256 256">
    <path class="background" d="M120..." />
    <path class="icon" style="fill: white;" d="M20..." />
  </symbol>
</svg>
36
Adam Korman

Можно стилизовать SVG, динамически создав элемент стиля в JavaScript и добавив его к элементу SVG. Хаки, но это работает.

<object id="dynamic-svg" type="image/svg+xml" data="your-svg.svg">
    Your browser does not support SVG
</object>
<script>
    var svgHolder = document.querySelector('object#dynamic-svg');
    svgHolder.onload = function () {
        var svgDocument = svgHolder.contentDocument;
        var style = svgDocument.createElementNS("http://www.w3.org/2000/svg", "style");

        // Now (ab)use the @import directive to load make the browser load our css
        style.textContent = '@import url("/css/your-dynamic-css.css");';

        var svgElem = svgDocument.querySelector('svg');
        svgElem.insertBefore(style, svgElem.firstChild);
    };
</script>

Вы можете динамически генерировать JavaScript в PHP, если хотите - тот факт, что это возможно в JavaScript, открывает множество возможностей.

5
Pete

Один из подходов, который вы можете использовать, это просто использовать CSS-фильтры, чтобы изменить внешний вид SVG-графики в браузере.

Например, если у вас есть SVG-изображение, которое использует красный цвет заливки в коде SVG, вы можете сделать его фиолетовым с настройкой поворота оттенка на 180 градусов:

#theIdOfTheImgTagWithTheSVGInIt {
    filter: hue-rotate(180deg);
    -webkit-filter: hue-rotate(180deg);
    -moz-filter: hue-rotate(180deg);
    -o-filter: hue-rotate(180deg);
    -ms-filter: hue-rotate(180deg);
}

Поэкспериментируйте с другими настройками поворота оттенка, чтобы найти нужные цвета.

Чтобы быть ясным, вышеупомянутый CSS входит в CSS, который применяется к вашему HTML-документу. Вы стилизуете тег img в HTML-коде, а не стилизуете код SVG.

И обратите внимание, что это не будет работать с графикой, которая имеет черный, белый или серый цвет. Вы должны иметь фактический цвет, чтобы повернуть оттенок этого цвета.

4
Simon White

Это должно быть возможно сделать, сначала вставив внешние изображения SVG. Посмотрите здесь, например:

Заменить все изображения Svg с Inline Svg | JAVASCRIPT | Библиотека фрагментов кода от Jess Frazelle

3
Leo

"На самом деле я собираюсь изменить цвета этих изображений в зависимости от того, какую цветовую схему выбрал пользователь для моего сайта." - Иордания10 часов назад

Я предлагаю вам использовать PHP для этого. На самом деле нет лучшего способа сделать это без значков шрифтов, и если вы не воспользуетесь их использованием, вы можете попробовать это:

<?php

    header('Content-Type: image/svg+xml');
    echo '<?xml version="1.0" encoding="utf-8"?>';
    $color = $_GET['color'];

?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path fill="<?php echo $color; ?>" d="M28.44..."/>
    </g>
</svg>

И позже вы можете использовать этот файл как filename.php?color=#ffffff, чтобы получить файл SVG в желаемом цвете.

2
SeinopSys

При использовании в теге <image> SVG должен содержаться в одном файле из соображений конфиденциальности. Этот bugzilla bug содержит более подробную информацию о том, почему это так. К сожалению, вы не можете использовать другой тег, такой как <iframe>, потому что он не будет работать как ссылка, поэтому вам придется встроить CSS в тег <style> внутри самого файла.

Еще один способ сделать это - поместить данные SVG в основной html-файл, т.е.

<a href='http://youtube.com/...' target='_blank'>
  <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path d="M28.44......./>
    </g>
  </svg>
</a>

Вы можете оформить это с помощью внешнего CSS-файла, используя тег HTML <link>.

2
Robert Longson

Очень быстрое решение иметь динамический стиль с внешней таблицей стилей CSS, если вы используете тег <object> для встраивания svg.

В этом примере будет добавлен класс в корневой тег <svg> при щелчке по родительскому элементу.

file.svg:

<?xml-stylesheet type="text/css" href="../svg.css"?>
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="">
  <g>
   <path/>
  </g>
 </svg>

hTML:

<a class="parent">
  <object data="file.svg"></object>
</a>

Jquery:

$(function() {
  $(document).on('click', '.parent', function(){
    $(this).find('object').contents().find('svg').attr("class","selected");
  }
});

при нажатии родительского элемента:

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="" class="selected">

тогда вы можете управлять своим CSS

svg.css:

path {
 fill:none;
 stroke:#000;
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}

.selected path {
 fill:none;
 stroke:rgb(64, 136, 209);
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}
2
vhanahrni

Я знаю, что это старый пост, но просто чтобы решить эту проблему ... вы просто используете свои классы в неправильном месте: D

Прежде всего вы могли бы использовать 

svg { fill: red; }

в вашем main.css, чтобы получить его красным. Это имеет эффект. Вы также можете использовать селекторы узлов, чтобы получить конкретные пути.

Во-вторых, вы объявили класс тегу img-. 

<img class='socIcon'....

Вы на самом деле должны объявить это в вашем SVG. если у вас есть различные пути, вы можете определить больше, конечно.

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
    <path class="myClassForMyPath" d="M28.44......./>
</g>
</svg>

теперь вы можете изменить цвет в вашем main.css как

.myClassForMyPath {
    fill: yellow;
}
1
Dwza

Что работает для меня: тег стиля с правилом @import

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>
0
Fordi
  1. Для внешних стилей

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">

  <style>
	@import url(main.css);
  </style>

  <g>
    <path d="M28.44......./>
  </g>
</svg>

  1. Для внутренних стилей

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">

  <style>
	    .socIcon g {fill:red;}
  </style>

  <g>
    <path d="M28.44......./>
  </g>
</svg>

Примечание. Внешние стили не будут работать, если вы включите SVG в тег <img>. Он будет отлично работать внутри тега <div>

0
Yuvraj Patil

@leo вот версия angularJS, еще раз спасибо 

G.directive ( 'imgInlineSvg', function () {

return {
    restrict : 'C',
    scope : true,
    link : function ( scope, elem, attrs ) {

        if ( attrs.src ) {

            $ ( attrs ).each ( function () {
                var imgID    = attrs.class;
                var imgClass = attrs.class;
                var imgURL   = attrs.src;

                $.get ( imgURL, function ( data ) {

                    var $svg = $ ( data ).find ( 'svg' );
                    if ( typeof imgID !== 'undefined' ) {
                        $svg = $svg.attr ( 'id', imgID );
                    }

                    if ( typeof imgClass !== 'undefined' ) {
                        $svg = $svg.attr ( 'class', imgClass + ' replaced-svg' );
                    }

                    $svg = $svg.removeAttr ( 'xmlns:a' );

                    elem.replaceWith ( $svg );

                } );

            } );
        }

    }

}

} );
0
Tino Costa 'El Nino'