img src SVG: изменение стилей с помощью CSS

375

HTML

<img src="logo.svg" alt="Logo" class="logo-img">

CSS

.logo-img path {
  fill: #000;
}

Приведенный выше svg загружается и изначально, fill: #fffно когда я использую приведенное выше, cssчтобы попытаться изменить его на черный, он не меняется, я впервые играю с SVG, и я не уверен, почему он не работает.

ngplayground
источник
26
Вы не можете воздействовать на изображения SVG, как это ... только встроенные элементы SVG
Paulie_D
Проверьте мой ответ здесь, чтобы использовать содержимое SVG и CSS. stackoverflow.com/questions/11978995/…
Бенджамин

Ответы:

153

Если ваша цель - просто изменить цвет логотипа, и вам не обязательно использовать CSS, то не используйте javascript или jquery, как предлагалось в предыдущих ответах.

Чтобы точно ответить на оригинальный вопрос, просто:

  1. Откройте logo.svgв текстовом редакторе.

  2. найдите fill: #fffи замените егоfill: #000

Например, вы logo.svgможете выглядеть так при открытии в текстовом редакторе:

<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
  <path d="M0 0h24v24H0z" fill="none"/>
  <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" fill="#fff"/>
</svg>

... просто измените заполнение и сохраните.

Роу Морхаус
источник
6
... и если нет "заполнения", вы можете просто добавить его в pathили circleэлементы, как <path fill="#777777" d="m129.774,74.409c-5.523,....
SaeX
1
Что если мой логотип имеет один цвет в заголовке и другой цвет в нижнем колонтитуле?
rubens.lopes
. @ ruben.lopes два разных файла, или две разные строчки были бы простейшими
Роу
11
Вы также можете использовать fill="currentColor"затем colorна родительском элементе css-tricks.com/cascading-svg-fill-color
Serge
10
Это очевидно возможно и не очень полезный ответ.
Тимммм
101

Вы можете установить свой SVG в качестве маски. Таким образом, установка цвета фона будет действовать как цвет заливки.

HTML

<div class="logo"></div>

CSS

.logo {
    background-color: red;
    -webkit-mask: url(logo.svg) no-repeat center;
    mask: url(logo.svg) no-repeat center;
}

JSFiddle: https://jsfiddle.net/KuhlTime/2j8exgcb/
MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/mask

Проверьте, поддерживает ли ваш браузер эту функцию: https://caniuse.com/#search=mask

Андре Кульман
источник
3
Так что ни для чего, кроме внутреннего сайта, непригодного для использования.
Хенрик Вендельбо
9
89% глобальная поддержка по состоянию на 29 мая 2016 года
Gajus
1
Это удивительное решение для ситуаций, подобных описанной здесь , где использование чего-либо, кроме data uris в css, немного проблематично. Спасибо!
Гарк Гарсия
3
это не работает. это говорит maskо invalid property value. Я тестирую это в Chrome.
Eren555
1
@MadMac Я использую ту же версию Chrome, но мне не удалось воспроизвести это поведение. Это JSFiddle, который вы пробовали, или ваш код?
Андре Кульманн
79

Попробуйте чистый CSS:

.logo-img {
  // to black
  filter: invert(1);
  // or to blue
  // filter: invert(1) sepia(1) saturate(5) hue-rotate(175deg);
}

больше информации в этой статье https://blog.union.io/code/2017/08/10/img-svg-fill/

Фери
источник
На Edge был другой цвет, чем в других браузерах с одной из моих недавних попыток.
Julix
4
Это работает в большинстве браузеров, но у меня были некоторые проблемы с браузером IOS-Safari.
Саймон Людвиг
31

2018: если вы хотите динамический цвет, не хотите использовать javascript и не хотите встроенный SVG, используйте переменную CSS. Работает в Chrome, Firefox и Safari. редактировать: и край

<svg>
    <use xlink:href="logo.svg" style="--color_fill: #000;"></use>
</svg>

В вашем SVG заменить все экземпляры style="fill: #000"с style="fill: var(--color_fill)".

североамериканский
источник
1
Какая поддержка браузера для этого
Кевин Гёдекке
@KevinGoedecke Chrome, Firefox, Safari и Edge
североамериканский
4
Кажется, устарела в SVG 2
vsync
5
@northamerican - ссылки на другие ответы на вопросы stackoverflow, поскольку «доказательства» не имеют значения. любой может написать что-нибудь на этой платформе. MDN:"This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped"
Вс
8
Похоже, что xlink:hrefне рекомендуется в пользу href. Так что это все еще может работать.
Бенджамин Интал
20

Сначала вам нужно внедрить SVG в HTML DOM.

Существует библиотека с открытым исходным кодом под названием SVGInject, которая делает это за вас. Он использует onloadатрибут для запуска инъекции.

Вот минимальный пример использования SVGInject:

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

После загрузки изображения onload="SVGInject(this)будет инициировано внедрение, и <img>элемент будет заменен содержимым файла SVG, предоставленного в srcатрибуте.

Это решает несколько проблем с инъекцией SVG:

  1. SVG могут быть скрыты до завершения инъекции. Это важно, если стиль уже применяется во время загрузки, что в противном случае могло бы вызвать краткую «флэш-память без стиля».

  2. Эти <img>элементы вводят себя автоматически. Если вы добавляете SVG динамически, вам не нужно беспокоиться о повторном вызове функции инъекции.

  3. Случайная строка добавляется к каждому идентификатору в SVG, чтобы избежать многократного использования одного и того же идентификатора в документе, если SVG вводится более одного раза.

SVGInject представляет собой простой Javascript и работает со всеми браузерами, поддерживающими SVG.

Отказ от ответственности: я соавтор SVGInject

Waruyama
источник
3
Это самый простой ответ. Я протестировал его в Chrome, Firefox и Edge, и он отлично работает.
Себастьян Лорион
15

Ответ от @Praveen твердый.

Я не мог заставить его отвечать в моей работе, поэтому я сделал для него функцию наведения jquery.

CSS

.svg path {
   transition:0.3s all !important;
}

JS / JQuery

// code from above wrapped into a function
replaceSVG();

// hover function
// hover over an element, and find the SVG that you want to change
$('.element').hover(function() {
    var el = $(this);
    var svg = el.find('svg path');
    svg.attr('fill', '#CCC');
}, function() {
    var el = $(this);
    var svg = el.find('svg path');
    svg.attr('fill', '#3A3A3A');
});
Мэтт Вуек
источник
1
Разве это не сработало бы, если бы SVG был встроенным для начала?
Даниэль Томпсон
Да, но если вы работаете со многими SVG-файлами или регулярно обновляете их, это очень сложно.
Мэтт Вуек
15

Почему бы не создать веб-шрифт с вашим изображением или изображениями SVG, импортировать веб-шрифт в CSS, а затем просто изменить цвет глифа с помощью атрибута цвета CSS? Нет необходимости в JavaScript

гринго
источник
5
Если ваш svg имеет несколько элементов разных цветов, это решение становится очень хакерским (несколько элементов вставляются).
Какая
1
@kakaja Это решение предназначено только для векторных изображений с одним цветом. см. ответ bpulecio для более подробной информации
гринго
1
Потому что значок не текст. Шрифты для текста. Свги для иконок.
Лазарь Любенович
2
@ LazarLjubenović - технически текст состоит из символов, которые являются символами, а значки также являются символами, поэтому у многих не возникает проблем с использованием значков-шрифтов. это как создание «другого» текстового языка. Мандарин также использует «значки», а не буквы, в человечестве нередко используют значки в качестве «текста»
vsync
1
хотя это звучит как интересное решение, я действительно рекомендую развить ответ во что-то более похожее на «как» вместо «почему бы и нет»
YakovL
15

Этот ответ основан на ответе https://stackoverflow.com/a/24933495/3890888, но с простой версией JavaScript используемого сценария.

Вы должны сделать SVG встроенным SVG . Вы можете использовать этот скрипт, добавив класс svgк изображению:

/*
 * Replace all SVG images with inline SVG
 */
document.querySelectorAll('img.svg').forEach(function(img){
    var imgID = img.id;
    var imgClass = img.className;
    var imgURL = img.src;

    fetch(imgURL).then(function(response) {
        return response.text();
    }).then(function(text){

        var parser = new DOMParser();
        var xmlDoc = parser.parseFromString(text, "text/xml");

        // Get the SVG tag, ignore the rest
        var svg = xmlDoc.getElementsByTagName('svg')[0];

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

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

        // Check if the viewport is set, if the viewport is not set the SVG wont't scale.
        if(!svg.getAttribute('viewBox') && svg.getAttribute('height') && svg.getAttribute('width')) {
            svg.setAttribute('viewBox', '0 0 ' + svg.getAttribute('height') + ' ' + svg.getAttribute('width'))
        }

        // Replace image with new SVG
        img.parentNode.replaceChild(svg, img);

    });

});

И тогда, теперь, если вы делаете:

.logo-img path {
  fill: #000;
}

Или, может быть:

.logo-img path {
  background-color: #000;
}

JSFiddle: http://jsfiddle.net/erxu0dzz/1/

Seb3736
источник
1
Отлично .. работает. Кроме того, если на нашей странице есть несколько svgs, нам нужно будет поместить блок выборки в IIFE.
Сандип Шарма
1
Большой! Хорошо работает с ES6. Если вас не волнует IE 9, вы даже можете использовать: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi
Не работает в UIWebView на iOS 9.3.5. Я думаю, что это может быть связано с использованием fetchкоторого было добавлено в Safari в 10.1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). Версия jQuery выше работает.
Мария-Инес Каррера
7

Используйте фильтры для преобразования в любой цвет.

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

Если у вас есть одноцветное изображение, цвет которого вы просто хотите изменить, вы можете сделать это с помощью некоторых фильтров. Конечно, он работает и на многоцветных изображениях, но вы не можете выбрать определенный цвет. Только весь образ.

Фильтры взяты из сценария, предложенного в разделе Как преобразовать черный в любой заданный цвет, используя только фильтры CSS. Если вы хотите изменить белый цвет на любой, вы можете настроить значение инвертирования в каждом фильтре.

.startAsBlack{
  display: inline-block;
  width: 50px;
  height: 50px;
  background: black;
}

.black-green{
  filter: invert(43%) sepia(96%) saturate(1237%) hue-rotate(88deg) brightness(128%) contrast(119%);
}

.black-red{
  filter: invert(37%) sepia(93%) saturate(7471%) hue-rotate(356deg) brightness(91%) contrast(135%);
}

.black-blue{
  filter: invert(12%) sepia(83%) saturate(5841%) hue-rotate(244deg) brightness(87%) contrast(153%);
}

.black-purple{
  filter: invert(18%) sepia(98%) saturate(2657%) hue-rotate(289deg) brightness(121%) contrast(140%);
}
Black to any color: <br/>
<div class="startAsBlack black-green"></div>
<div class="startAsBlack black-red"></div>
<div class="startAsBlack black-blue"></div>
<div class="startAsBlack black-purple"></div>

JasperZelf
источник
5

Если вы просто переключаете изображение между реальным цветом и черно-белым, вы можете установить один селектор как:

{Фильтр: нет;}

а другой как:

{filter:grayscale(100%);}
wcb1
источник
4

Чтобы расширить ответ @gringo, метод Javascript, описанный в других ответах, работает, но требует, чтобы пользователь загружал ненужные файлы изображений, а IMO - раздувает ваш код.

Я думаю, что лучшим подходом было бы перенести всю одноцветную векторную графику в файл веб-шрифта. В прошлом я использовал Fort Awesome , и он прекрасно работает для объединения пользовательских значков / изображений в формате SVG вместе с любыми сторонними значками, которые вы можете использовать (Font Awesome, Bootstrap icons и т. Д.), В один файл веб-шрифта. пользователь должен скачать. Вы также можете настроить его, чтобы вы включали только сторонние значки, которые вы используете. Это уменьшает количество запросов, которые должна сделать страница, и ваш общий вес страницы, особенно если вы уже включили какие-либо сторонние библиотеки значков.

Если вы предпочитаете более ориентированный на dev вариант, вы можете использовать Google «npm svg webfont» и использовать один из узловых модулей, наиболее подходящий для вашей среды.

После того, как вы сделали любой из этих двух вариантов, вы можете легко изменить цвет с помощью CSS, и, скорее всего, вы ускорили свой сайт в процессе.

bpulecio
источник
Вы должны попробовать SVG спрайты. По моему опыту, веб-шрифты имеют случайные проблемы между выпусками браузера. Попробуйте это: fontastic.me - но используйте версии SVG-спрайтов - и посмотрите, что вы думаете. :)
sheriffderek
3

Просто..

Вы можете использовать этот код:

<svg class="logo">
  <use xlink:href="../../static/icons/logo.svg#Capa_1"></use>
</svg>

Сначала укажите путь к svg, а затем напишите его ID, в данном случае «Capa_1». Вы можете получить идентификатор SVG, открыв его в любом редакторе.

В css:

.logo {
  fill: red;
}
Хамза Джамал
источник
kabrice, Вы можете использовать этот код codepen.io/hmzajmal/pen/ZEGvWYa
Хамза Джамал
2

Основная проблема в вашем случае заключается в том, что вы импортируете svg из <img>тега, который скрывает структуру SVG.

Вам нужно использовать <svg>тег вместе с, <use>чтобы получить желаемый эффект. Чтобы это сработало, вам нужно указать idпуть, который вы хотите использовать в файле SVG, <path id='myName'...>чтобы затем получить их из <use xlink:href="#myName"/>тега. Попробуйте разрезать ниже.

Обратите внимание, что вы можете поместить любой URL перед фрагментом, #если вы хотите загрузить SVG из внешнего источника (а не встраивать его в ваш HTML). Также обычно вы не указываете заливку в CSS. Лучше рассмотреть возможность использования fill:"currentColor"в самом SVG. Затем будет использовано значение цвета соответствующего элемента CSS.

Флавиен Волкен
источник
2

Поскольку SVG - это в основном код, вам нужно просто содержимое. Я использовал PHP для получения контента, но вы можете использовать все, что захотите.

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

Затем я напечатал содержимое "как есть" внутри контейнера div

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

Чтобы окончательно установить правило для SVG-потомков контейнера на CSS

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

Я получил этот результат с иконкой материала SVG:

Mozilla Firefox 59.0.2 (64-разрядная версия) Linux

введите описание изображения здесь

Google Chrome66.0.3359.181 (сборка официальная) (64 бит) Linux

введите описание изображения здесь

Опера 53.0.2907.37 Linux

введите описание изображения здесь

Вениамин
источник
Я не могу понизить голос, но, пожалуйста, никогда не делай этого.
Сандер
5
Причины? Альтернативы?
Бенджамин
Моя причина не делать этого состоит в том, что это мешает браузеру кэшировать SVG. Альтернативой является использование инжектора SVG, упомянутого в нескольких других ответах здесь. Файл SVG все еще будет кэшироваться браузером, а введенный SVG все еще может быть стилизован с помощью CSS. Но я не отрицаю тебя.
Сон
Я понимаю, но все равно кеш не упоминается. Лучший ответ - это JavaScript-код, который можно каждый раз перезагружать (или нет) с помощью манипуляций с истечением срока действия заголовка или принудительного хеширования после ссылки на имя файла. Спасибо за не понизить голос, но я все еще верю, что мой ответ решает изменение SVG с использованием атрибута заполнения CSS.
Бенджамин
2

Это может быть полезно для людей, использующих PHPв сочетании с .svgизображениями, которыми они хотят манипулировать с помощью CSS.

Вы не можете перезаписать свойства внутри тега img с помощью CSS. Но когда исходный код SVG встроен в HTML, вы, безусловно, можете. Мне нравится решать эту проблему с помощью require_onceфункции, в которую я включаю .svg.phpфайл. Это похоже на импорт изображения, но вы все равно можете переписать стили с помощью CSS!

Сначала включите файл SVG:

<?php require_once( '/assets/images/my-icon.svg.php' ); ?>

И это включает в себя этот значок, например:

<svg xmlns="http://www.w3.org/2000/svg" width="20.666" height="59.084" viewBox="0 0 20.666 59.084"><g transform="translate(-639.749 -3139)"><path d="M648.536,3173.876c0-2.875-1.725-3.8-3.471-3.8-1.683,0-3.49.9-3.49,3.8,0,3,1.786,3.8,3.49,3.8C646.811,3177.676,648.536,3176.769,648.536,3173.876Zm-3.471,2.341c-.883,0-1.437-.513-1.437-2.341,0-1.971.615-2.381,1.437-2.381.862,0,1.438.349,1.438,2.381,0,1.907-.616,2.339-1.438,2.339Z" fill="#142312"/><path d="M653.471,3170.076a1.565,1.565,0,0,0-1.416.9l-6.558,13.888h1.2a1.565,1.565,0,0,0,1.416-.9l6.559-13.887Z" fill="#142312"/><path d="M655.107,3177.263c-1.684,0-3.471.9-3.471,3.8,0,3,1.766,3.8,3.471,3.8,1.745,0,3.49-.9,3.49-3.8C658.6,3178.186,656.851,3177.263,655.107,3177.263Zm0,6.139c-.884,0-1.438-.514-1.438-2.34,0-1.972.617-2.381,1.438-2.381.862,0,1.437.349,1.437,2.381,0,1.909-.616,2.34-1.437,2.34Z" fill="#142312"/><path d="M656.263,3159.023l-1.49-14.063a1.35,1.35,0,0,0,.329-.293,1.319,1.319,0,0,0,.268-1.123l-.753-3.49a1.328,1.328,0,0,0-1.306-1.054h-6.448a1.336,1.336,0,0,0-1.311,1.068l-.71,3.493a1.344,1.344,0,0,0,.276,1.112,1.532,1.532,0,0,0,.283.262l-1.489,14.087c-1.7,1.727-4.153,4.871-4.153,8.638v28.924a1.339,1.339,0,0,0,1.168,1.49,1.357,1.357,0,0,0,.17.01h17.981a1.366,1.366,0,0,0,1.337-1.366v-29.059C660.414,3163.893,657.963,3160.749,656.263,3159.023Zm-8.307-17.349h4.274l.176.815H647.79Zm9.785,43.634v10.1H642.434v-17.253a4.728,4.728,0,0,1-2.028-4.284,4.661,4.661,0,0,1,2.028-4.215v-2c0-3.162,2.581-5.986,3.687-7.059a1.356,1.356,0,0,0,.4-.819l1.542-14.614H652.1l1.545,14.618a1.362,1.362,0,0,0,.4.819c1.109,1.072,3.688,3.9,3.688,7.059v9.153a5.457,5.457,0,0,1,0,8.5Z" fill="#142312"/></g></svg>

Теперь мы можем легко изменить цвет заливки с помощью CSS:

svg path {
  fill: blue;
}

Сначала я попытался решить эту проблему, file_get_contents()но решение выше гораздо быстрее.

Floris
источник
0

Знайте, это старый вопрос, но недавно мы столкнулись с той же проблемой и решили ее со стороны сервера. Это конкретный ответ php, но я уверен, что другие envs имеют что-то похожее. вместо использования тега img вы визуализируете svg как svg с самого начала.

public static function print_svg($file){
    $iconfile = new \DOMDocument();
    $iconfile->load($file);
    $tag = $iconfile->saveHTML($iconfile->getElementsByTagName('svg')[0]);
    return $tag;
}

теперь при рендеринге файла вы получите полный встроенный svg

Нечемья Унгар
источник
0

откройте значок svg в редакторе кода и добавьте класс после тега path:

<path class'colorToChange' ...

Вы можете добавить класс в SVG и изменить цвет следующим образом:

codepen

Хамза Джамал
источник
-2

Если у вас есть доступ к JQuery, то в ответ на ответ Правина можно программно изменить цвет различных вложенных элементов в SVG:

$('svg').find('path, text').css('fill', '#ffffff');

В рамках find вы можете упомянуть различные элементы, которые нужно изменить в цвете.

Маню
источник