img src SVG zmienia style za pomocą CSS

373

HTML

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

css

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

Powyższe svg ładuje się i jest natywnie, fill: #fffale kiedy użyję powyższego, cssaby spróbować zmienić go na czarny, nie zmienia się, to jest moja pierwsza gra z SVG i nie jestem pewien, dlaczego to nie działa.

ngplayground
źródło
25
Nie możesz wpływać na takie obrazy SVG ... tylko wbudowane elementy SVG
Paulie_D
Sprawdź moją odpowiedź tutaj, aby użyć zawartości SVG i CSS. stackoverflow.com/questions/11978995/…
Benjamin

Odpowiedzi:

153

Jeśli Twoim celem jest zmiana koloru logo i niekoniecznie POTRZEBUJESZ użyć CSS, nie używaj javascript ani jquery, jak sugerowały niektóre wcześniejsze odpowiedzi.

Aby dokładnie odpowiedzieć na oryginalne pytanie, po prostu:

  1. Otwórz logo.svgw edytorze tekstu.

  2. poszukaj fill: #fffi zamień nafill: #000

Na przykład możesz logo.svgwyglądać tak po otwarciu w edytorze tekstu:

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

... po prostu zmień wypełnienie i zapisz.

Rowe Morehouse
źródło
6
... a jeśli nie ma „wypełnienia”, możesz po prostu dodać go do elementów pathlub . circle<path fill="#777777" d="m129.774,74.409c-5.523,...
SaeX
1
co jeśli moje logo ma jeden kolor w nagłówku i inny kolor w stopce?
rubens.lopes
. @ ruben.lopes dwa różne pliki lub dwa różne wstawki byłyby najprostsze
Rowe Morehouse
11
możesz również użyć fill="currentColor"następnie colorna elemencie nadrzędnym css-tricks.com/cascading-svg-fill-color
Serge
10
Jest to oczywiście możliwe i niezbyt pomocna odpowiedź.
Timmmm,
102

Możesz ustawić SVG jako maskę. W ten sposób ustawienie koloru tła będzie działało jako kolor wypełnienia.

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

Sprawdź, czy Twoja przeglądarka obsługuje tę funkcję: https://caniuse.com/#search=mask

André Kuhlmann
źródło
3
Tak więc do niczego poza wewnętrzną stroną internetową nie nadaje się do użytku.
Henrik Vendelbo
9
89% globalnego wsparcia na dzień 29 maja 2016 r.
Gajus
1
Jest to niesamowite rozwiązanie w sytuacjach takich jak opisana tutaj , gdzie używanie cs innych niż dane uris w css jest trochę uciążliwe. Dzięki!
Gark Garcia
3
to nie działa. mówi się, że maskjest invalid property value. testuję to w chrome.
Eren555
1
@MadMac Używam tej samej wersji Chrome, ale nie byłem w stanie powtórzyć tego zachowania. Czy to JSFiddle, którego wypróbowałeś, czy kod?
André Kuhlmann
78

Wypróbuj czysty CSS:

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

Więcej informacji w tym artykule https://blog.union.io/code/2017/08/10/img-svg-fill/

Feri
źródło
Otrzymałem inny kolor na Edge'u niż w innych przeglądarkach dzięki jednej z moich ostatnich prób.
Julix
4
Działa to w większości przeglądarek, ale miałem pewne problemy z przeglądarką IOS-Safari.
Simon Ludwig
30

2018: Jeśli chcesz dynamiczny kolor, nie chcesz używać javascript i nie chcesz wstawiać SVG, użyj zmiennej CSS. Działa w Chrome, Firefox i Safari. edit: i Edge

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

W swojej SVG, zastąpić wszystkie wystąpienia style="fill: #000"z style="fill: var(--color_fill)".

północno Amerykański
źródło
1
Jaka jest obsługa tego przez przeglądarkę
Kevin Goedecke
@KevinGoedecke Chrome, Firefox, Safari i Edge
północnoamerykański
4
Wydaje się przestarzałe w SVG 2
vsync
5
@northamerican - linki do innych odpowiedzi typu stackoverflow, ponieważ „dowody” są nieistotne. każdy może napisać cokolwiek na tej platformie. 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"
vsync,
8
Wydaje się, że xlink:hrefjest to przestarzałe na korzyść href. Więc to może nadal działać.
Benjamin Intal
20

Najpierw będziesz musiał wstrzyknąć SVG do HTML DOM.

Istnieje biblioteka open source o nazwie SVGInject, która robi to za Ciebie. Używa tego onloadatrybutu do uruchomienia zastrzyku.

Oto minimalny przykład użycia SVGInject:

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

Po załadowaniu obrazu onload="SVGInject(this)uruchomi się zastrzyk, a <img>element zostanie zastąpiony zawartością pliku SVG podanego w plikusrc atrybucie.

Rozwiązuje kilka problemów z wtryskiem SVG:

  1. Pliki SVG można ukryć do momentu zakończenia wstrzykiwania. Jest to ważne, jeśli styl jest już zastosowany w czasie ładowania, co w przeciwnym razie spowodowałoby krótkie „niestylizowane flashowanie zawartości”.

  2. Te <img>elementy automatycznie wstrzykiwać sobie. Jeśli dodajesz pliki SVG dynamicznie, nie musisz się martwić o ponowne wywołanie funkcji wstrzykiwania.

  3. Losowy ciąg jest dodawany do każdego identyfikatora w pliku SVG, aby uniknąć wielokrotnego posiadania tego samego identyfikatora w dokumencie, jeśli plik SVG zostanie wstrzyknięty więcej niż jeden raz.

SVGInject to zwykły Javascript i działa ze wszystkimi przeglądarkami obsługującymi SVG.

Oświadczenie: Jestem współautorem SVGInject

Waruyama
źródło
3
To najprostsza odpowiedź. Przetestowałem to w Chrome, Firefox i Edge i działa idealnie.
Sébastien Lorion
15

Odpowiedź od @Praveen jest solidna.

Nie mogłem zmusić go do zareagowania w mojej pracy, więc utworzyłem dla niego funkcję przeciągania 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');
});
Matt Wujek
źródło
1
czy nie zadziałałoby to tylko, gdyby SVG był na początku liniowy?
Daniel Thompson
Tak - ale jeśli pracujesz z wieloma plikami SVG lub regularnie je aktualizujesz, zarządzanie nimi jest uciążliwe.
Matt Wujek,
15

Dlaczego nie utworzyć strony internetowej z obrazem lub obrazami svg, zaimportować stronę internetową do css, a następnie po prostu zmienić kolor glifu za pomocą atrybutu koloru css? Nie wymaga javascript

gringo
źródło
5
Jeśli twój plik svg ma kilka elementów o różnych kolorach, to rozwiązanie staje się bardzo hackerskie (kilka elementów wstawionych).
kakaja
1
@kakaja Jest to rozwiązanie tylko dla obrazów wektorowych, które mają 1 kolor. więcej szczegółów można znaleźć w odpowiedzi bpulecio
gringo
1
Ponieważ ikona nie jest tekstem. Czcionki są przeznaczone dla tekstu. Pliki SVG są przeznaczone do ikon.
Lazar Ljubenović
2
@ LazarLjubenović - technicznie tekst składa się ze znaków, które są symbolami, a ikony są również symbolami, dlatego wiele osób nie ma problemu z używaniem czcionek ikon. przypomina tworzenie „innego” języka tekstowego. Mandaryński używa również „ikon”, a nie liter, ludzkość nie jest rzadkością używać ikon jako „tekstu”
vsync
1
choć wydaje się to ciekawym rozwiązaniem, naprawdę polecam rozwinąć odpowiedź w coś bardziej jak „jak” zamiast „dlaczego nie”
JakowL,
15

Ta odpowiedź jest oparta na odpowiedzi https://stackoverflow.com/a/24933495/3890888, ale ze zwykłą wersją skryptu JavaScript używanego tam.

Musisz ustawić SVG jako wbudowany plik SVG . Możesz skorzystać z tego skryptu, dodając klasę svgdo obrazu:

/*
 * 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);

    });

});

A teraz, jeśli to zrobisz:

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

Albo może:

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

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

Seb3736
źródło
1
Świetnie .. działa. ponadto, jeśli nasza strona ma wiele plików svg, będziemy musieli umieścić blok pobierania w IIFE.
Sandeep Sharma
1
Świetny! Działa dobrze z ES6. Jeśli nie zależy ci na IE 9, możesz nawet użyć: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi
Nie działa w UIWebView na iOS 9.3.5. Myślę , że może to wynikać z zastosowania, fetchktóre zostało dodane do Safari w 10.1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). Powyższa wersja jQuery działa.
Maria-Ines Carrera
7

Użyj filtrów, aby przekształcić na dowolny kolor.

Niedawno znalazłem to rozwiązanie i mam nadzieję, że ktoś może go użyć. Ponieważ rozwiązanie wykorzystuje filtry, można go używać z dowolnym rodzajem obrazu. Nie tylko SVG.

Jeśli masz obraz jednokolorowy, którego chcesz tylko zmienić kolor, możesz to zrobić za pomocą niektórych filtrów. Działa również na obrazach wielokolorowych, ale nie można kierować na określony kolor. Tylko cały obraz.

Filtry pochodzą ze skryptu zaproponowanego w Jak przekształcić czerń na dowolny kolor przy użyciu tylko filtrów CSS. Jeśli chcesz zmienić biel na dowolny kolor, możesz dostosować wartość odwracania w każdym filtrze.

.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
źródło
4

Aby rozwinąć odpowiedź @gringo, metoda Javascript opisana w innych odpowiedziach działa, ale wymaga od użytkownika pobrania niepotrzebnych plików graficznych, a IMO powoduje rozdęcie kodu.

Myślę, że lepszym rozwiązaniem byłoby migrowanie całej jednokolorowej grafiki wektorowej do pliku webfont. W przeszłości korzystałem z Fort Awesome i świetnie się łączy twoje niestandardowe ikony / obrazy w formacie SVG, a także dowolne ikony innych firm (Font Awesome, ikony Bootstrap itp.) W jednym pliku webfont użytkownik musi pobrać. Możesz go również dostosować, abyś zawierał tylko ikony innych firm, których używasz. Zmniejsza to liczbę żądań strony i generuje całkowitą wagę strony, zwłaszcza jeśli dołączasz już biblioteki ikon stron trzecich.

Jeśli wolisz opcję bardziej zorientowaną na programistów, możesz napisać w Google „npm svg webfont” użyć i użyć jednego z modułów węzłów, który jest najbardziej odpowiedni dla twojego środowiska.

Kiedyś zrobiłeś jedną z tych dwóch opcji, możesz łatwo zmienić kolor za pomocą CSS, i najprawdopodobniej przyspieszyłeś swoją stronę.

bpulecio
źródło
Powinieneś spróbować sprite'ów SVG. Z mojego doświadczenia wynika, że ​​czcionki internetowe mają przypadkowe problemy między wydaniami przeglądarki. Spróbuj tego: fontastic.me - ale używaj wersji sprite SVG - i zobacz, co myślisz. :)
sheriffderek
4

Jeśli przełączasz tylko obraz między rzeczywistym kolorem a czarno-białym, możesz ustawić jeden selektor jako:

{filter: none;}

i inny jako:

{filter:grayscale(100%);}
wcb1
źródło
3

Prosty..

Możesz użyć tego kodu:

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

Najpierw określ ścieżkę svg, a następnie wpisz jej identyfikator, w tym przypadku „Capa_1”. Możesz uzyskać identyfikator svg, otwierając go w dowolnym edytorze.

W css:

.logo {
  fill: red;
}
Hamza Jamal
źródło
kabrice, Możesz użyć tego kodu codepen.io/hmzajmal/pen/ZEGvWYa
Hamza Jamal
2

Głównym problemem w twoim przypadku jest to, że importujesz plik svg ze <img>znacznika, który ukryje strukturę SVG.

Musisz użyć <svg>znacznika w połączeniu z, <use>aby uzyskać pożądany efekt. Aby to działało, musisz podać idścieżkę, której chcesz użyć w pliku SVG, <path id='myName'...>a następnie móc pobrać je ze <use xlink:href="#myName"/>znacznika. Spróbuj wyciąć poniżej.

Pamiętaj, że możesz wstawić dowolny URL przed fragmentem, #jeśli chcesz załadować SVG z zewnętrznego źródła (i nie osadzać go w swoim HTML). Ponadto zwykle nie określasz wypełnienia w CSS. Lepiej rozważyć użycie fill:"currentColor"w samym SVG. Wówczas zostanie zastosowana wartość koloru odpowiedniego elementu CSS.

Flavien Volken
źródło
2

Ponieważ SVG jest w zasadzie kodem, potrzebujesz tylko zawartości. Użyłem PHP, aby uzyskać zawartość, ale możesz użyć, co chcesz.

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

Następnie wydrukowałem zawartość „tak jak jest” w pojemniku div

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

Aby ostatecznie ustawić regułę dla elementów potomnych SVG kontenera w CSS

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

Mam wyniki z ikoną materiału SVG:

Mozilla Firefox 59.0.2 (64-bitowy) Linux

wprowadź opis zdjęcia tutaj

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

wprowadź opis zdjęcia tutaj

Opera 53.0.2907.37 Linux

wprowadź opis zdjęcia tutaj

Benzoes
źródło
Nie mogę przegłosować, ale proszę, nigdy nie róbcie tego nigdy.
sander
5
Dlaczego? Alternatywy?
Benjamin
Powodem, dla którego tego nie zrobiłem, jest to, że przeglądarka nie buforuje SVG w pamięci podręcznej. Alternatywą jest użycie wtryskiwacza SVG wymienionego w kilku innych odpowiedziach tutaj. Plik SVG nadal będzie przechowywany w pamięci podręcznej przeglądarki, a wstrzyknięty plik SVG można nadal stylizować za pomocą CSS. Ale nie głosuję cię.
Sơn Trần-Nguyễn
Rozumiem, ale zresztą pamięć podręczna nie jest wspomniana. Najlepsza odpowiedź ma kod JavaScript, który można ponownie załadować (lub nie) za każdym razem, gdy nagłówek wygasa manipulację lub wymusza skrót za linkiem do nazwy pliku. Dzięki za nie głosuj, ale nadal uważam, że moja odpowiedź rozwiązuje zmianę SVG za pomocą atrybutu wypełnienia CSS.
Benjamin,
2

Może to być pomocne dla osób używających PHPw połączeniu z .svgobrazami, którymi chcą manipulować za pomocą CSS.

Nie można nadpisywać właściwości wewnątrz tagu img za pomocą CSS. Ale kiedy kod źródłowy svg jest osadzony w kodzie HTML, na pewno możesz. Lubię rozwiązać ten problem za pomocą require_oncefunkcji, w której dołączam .svg.phpplik. To jest jak importowanie obrazu, ale nadal możesz nadpisywać style za pomocą CSS!

Najpierw dołącz plik svg:

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

I zawiera na przykład tę ikonę:

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

Teraz możemy łatwo zmienić kolor wypełnienia w ten sposób za pomocą CSS:

svg path {
  fill: blue;
}

Najpierw próbowałem rozwiązać ten problem, file_get_contents()ale powyższe rozwiązanie jest znacznie szybsze.

Floris
źródło
0

Wiedz, że to stare pytanie, ale ostatnio natknęliśmy się na ten sam problem i rozwiązaliśmy go od strony serwera. To jest odpowiedź specyficzna dla php, ale jestem przekonany, że inne envs mają coś podobnego. zamiast używać znacznika img, renderujesz svg jako svg od samego początku.

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

teraz, gdy wyrenderujesz plik, otrzymasz kompletny plik svg

Nechemya Ungar
źródło
0

otwórz ikonę svg w edytorze kodu i dodaj klasę po znaczniku ścieżki:

<path class'colorToChange' ...

Możesz dodać klasę do pliku svg i zmienić kolor w następujący sposób:

codepen

Hamza Jamal
źródło
-2

Jeśli masz dostęp do JQuery, to w odpowiedzi na odpowiedź Praveen można programowo zmienić kolor różnych zagnieżdżonych elementów w SVG poprzez:

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

W ramach find możesz wymienić różne elementy, które należy zmienić na kolor.

manyu
źródło