Як стилізувати SVG із зовнішнім CSS?


102

У мене є кілька графічних зображень 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 за допомогою моїх зовнішніх таблиць стилів, але я не можу втратити підказку та можливість зв’язування. (Я, можливо, зможу жити без підказок.) Дякую!



Спробуйте svg { fill:red; }або вкажіть свій шлях назви класу. Наприклад, <path class="socIcon" d="M28.44 ..... />це повинно зробити трюк.
Dwza

Відповіді:


92

Ваш файл 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>

Ви можете використовувати інструмент на стороні сервера, щоб оновити тег стилів залежно від активного стилю. У рубіні ви могли досягти цього за допомогою Нокогірі. SVG - це лише XML. Тому, мабуть, є багато бібліотек XML, які, можливо, можуть цього досягти.

Якщо ви не можете цього зробити, вам доведеться просто використовувати їх так, ніби вони були PNG; створення набору для кожного стилю та збереження їх стилів у формі.


17
Чи означає це, що не існує жодного методу, який би отримав користь від кешування SVG та застосування різноманітних стилів? Здається, Inline не кешується добре, тоді як інші методи потребують створення багатьох версій зображення, виключаючи будь-яку користь від кешування.
msg45f

Інший спосіб - кодувати SVG-файли як урис даних фонового зображення, з різними кольорами для кожної версії та покладатися на gzip, щоб зменшити розмір файлу через дублювання.
Раскін

1
У моєму випадку я хотів змінити стилі елементів із SVG. Мій CSS не працював, тому що стилі елементів мали більший пріоритет. Найпростішим рішенням було додавання!! Важливого стилю CSS для SVG. Тоді все було добре. Якщо ви хочете уникнути! Важливо, вам потрібно перемістити стилі елементів у CSS.
Девід Гаусман

прикро, що ви не можете завантажити таблицю стилів всередині svg з URL
clayRay

1
@clayRay ви зможете це зробити так, як тільки SVG2 завершить проект w3.org/TR/SVG2/styling.html#LinkElement
RGB,

51

Ви можете робити все, що завгодно, з одним (важливим) застереженням: шляхи в межах вашого символу не можна стилізувати самостійно за допомогою зовнішньої 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та-та ... у вас синій замість червоного.

Ви можете частково обійти обмеження можливості орієнтації на шляхи окремо із зовнішнім 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>

хороша відповідь .. Я думаю, що застереження справді має бути: Хоча підтримка браузера! хороша довідка (детальніше, ніж канюза): css-tricks.com/svg-fragment-identifiers-work
ptim

Це рішення! Насправді немає необхідності загортати весь вміст svg в symbolелемент, тобто ви можете просто дати idелемент svg, так що: <<svg id = example "xmlns =" w3.org/2000/svg "viewBox =" 0 0 256 256 "> <шлях клас =" фон "d =" M120 ... "/> <шлях клас =" значок "стиль =" заповнити: білий; "d =" M20 ... "/> </ svg > `
SimoneMSR

12

Ви можете включити у свій SVG-файл посилання на зовнішній файл css, використовуючи:

<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>

Потрібно поставити це після відкриття тегу:

<svg>
  <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>
  <g>
    <path d=.../>
  </g>
</svg>

Це не ідеальне рішення, тому що ви повинні змінювати файли svg, але ви змінюєте їх один раз, і всі зміни стилів можна зробити в одному файлі css для всіх файлів svg.


1
Нічого собі, це працює, але лише 1 підсумок ... чи добре це рішення для всіх ситуацій? Це так просто, чому це не обрана відповідь?
Бруно Вінсент

Вся справа в централізації визначень вашого стилю. Скажімо, у вас є 10 SVG, які ви хочете стилізувати. Тепер вам потрібно скопіювати посилання на CSS у всі SVG, на які потрібно вплинути. І якщо ім'я / місце вашого CSS зміниться, вам потрібно оновити його в 10 SVG. Клас CSS відчуває набагато символічніше, ніж посилання на фізичний файл CSS.
Франс

Зауважте, що svg, завантажений через тег <img>, не завантажує зовнішній вміст (наприклад, таблиці стилів).
Moose Morals

7

Можна стилізувати 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, відкриває безліч можливостей.


ей, я насправді вам подобається рішення, і воно працює, але мені потрібно прийняти його в моєму розташуванні, якщо ви готові допомогти OS курсу, у мене всередині <defs> тег стилю я можу видалити їх вручну та запустити цей код, щоб це створило стиль, чи є спосіб, як я можу видалити defs, потім відтворити елемент, як ви зробили, або просто оновити його, а також URL отримав URL-адресу помилки, не визначено, будь ласка, допоможіть, дякую
Kamel Mili

6

Один із підходів, який ви можете скористатися, - це просто використовувати фільтри 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

Дуже швидке рішення мати динамічний стиль із зовнішнім таблицею стилів 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;
}

не здається, ви можете додати робочий приклад?
Жанлука Скалері

4

Це можна зробити, спочатку вклавши зовнішні зображення svg. Код, наведений нижче, походить від заміни всіх зображень SVG на вбудований SVG від Джесса Фразелле.

$('img.svg').each(function(){
  var $img = $(this);
  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);
  });
});

3
важливо відзначити, що це буде працювати лише в тому випадку, якщо у вас є зображення, розміщене в тому ж домені, що і html, або на спеціально налаштованій політиці перехресного домену на сервері зображень. $ .get використовуватиме ajax і не завантажить зображення із зовнішнього сервера, якщо немає дійсного заголовка дозволу доступу
user151496

це легендарно
Tino Costa 'El Nino'

2

При використанні в <image>тезі SVG з міркувань конфіденційності повинен міститися в одному файлі. Цей помилок має більше інформації про те, чому саме так. На жаль, ви не можете використовувати інший тег, наприклад, <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, використовуючи <link>тег HTML .


2
Я не можу розмістити стилі у файлах. Я фактично збираюся змінити кольори цих зображень, виходячи з того, яку кольорову схему вибрав користувач для мого сайту. Моя поточна реалізація полягає в тому, щоб додати таблицю стилів на головну сторінку, яка переписує стилі за замовчуванням. Я хотів помістити зміни кольору у цей файл, щоб вплинути на вбудовану графіку SVG. Але це не спрацювало, тому що я повинен посилатися на таблицю стилів з файлу SVG (якщо тільки немає способу додати це посилання до всіх файлів SVG, використовуючи JavaScript). Звичайно, існує спосіб дозволити зовнішні файли SVG, зовнішні CSS, посилання та підказки.
Йордан Н

1
Неможливо зробити те, що ви хочете зробити через модель безпеки браузера. Ви не можете використовувати javascript для управління SVG, коли використовується як зображення. Подумайте про SVG, коли він використовується як зображення, як анімований png чи gif-файл, все в одному файлі та не має доступу до сценарію.
Роберт Лонгсон

1

"Я фактично збираюся змінити кольори цих зображень, виходячи з того, яку кольорову схему вибрав користувач для мого сайту." - Йорданія 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-файл у потрібному кольорі.


6
Зауважте, що цей код не перевіряє введення користувача - що-небудь може бути подано у вигляді кольору, і ваш SVG може бути наданий дуже цікавими способами ... Не впевнений, чи впливає він на вас, але вам слід звичити ВИНАГА перевіряти введення користувача. Щось подібне допоможе: if (!preg_match('/^[#][0-9a-f]{6}$/i', $_GET['color'])) die('Oops!');(покладіть його десь у стартовий блок PHP).
johndodo

1

Що для мене працює: тег стилю з правилом @import

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>

1

Я знаю його старий пост, але просто для того, щоб усунути цю проблему ... ви просто використовуєте свої заняття в неправильному місці: D

Перш за все ви могли використовувати

svg { fill: red; }

у вашому, main.cssщоб отримати його червоним. Це має ефект. Можна також широко використовувати селектори вузлів, щоб отримати певні пробіли.

Друга річ, ви оголосили клас на img-Tag.

<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;
}

Спробувавши це, це не працює, як багато інших відповідей уже говорять. Не можна застосовувати стилізацію до класів всередині SVG.
Франс

@Frans Ви включаєте svg як файл або у вас є джерело svg, як у прикладі вище? Тому що я маю на увазі, що це залежить від того, як ви використовуєте svg. У тому числі за роботою img wont.
Dwza

Точно він працює, лише якщо вбудувати SVG у свій HTML. Але це не те, що робить ваш приклад. Він використовує зовнішній (тобто не вбудований) SVG. Здається, немає способу стилізувати зовнішній SVG з CSS у вашому HTML.
Франс

Ви впевнені, що ви спробували мій приклад правильно? я маю на увазі, включений файл css із зовнішнього? <?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
Dwza

Гаразд, тепер я бачу, у вас є <?xml-stylesheet ... ?>декларація всередині вашого SVG. Я думаю, це спрацювало б. Це схоже на інші відповіді, які рекомендують <link rel="stylesheet" ... >всередині SVG. У нього також є ті ж проблеми (вам потрібно оновити кожен SVG, щоб вказати на таблицю стилів, і будь-яка зміна назви або місця розташування таблиці стилів означає, що потрібно знову змінити всі SVG).
Франс

1
  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

@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 );

                } );

            } );
        }

    }

}

} );

-1

Цей метод спрацює, якщо svg переглядається у веб-браузері, але як тільки цей код буде завантажений у sever і клас для піктограми svg кодується так, ніби це фонове зображення, колір втрачається і повертається до кольору за замовчуванням . Здається, що колір не може бути змінений із зовнішнього аркуша стилів, навіть якщо і клас svg для кольору, і клас верхнього шару для відображення та положення svg відображаються в одній і тій же директорії.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.