img src SVG modifica gli stili con CSS


374

html

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

css

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

Lo svg sopra si carica ed è nativo fill: #fffma quando uso quanto sopra cssper provare a cambiarlo in nero non cambia, questa è la prima volta che gioco con SVG e non sono sicuro del perché non funzioni.


25
Non puoi influenzare le immagini SVG in quel modo ... solo elementi SVG
incorporati


Controlla qui la mia risposta per utilizzare i contenuti di SVG e CSS. stackoverflow.com/questions/11978995/…
Benjamin,

Risposte:


153

Se il tuo obiettivo è solo quello di cambiare il colore del logo e non devi necessariamente utilizzare i CSS, non utilizzare javascript o jquery come suggerito da alcune risposte precedenti.

Per rispondere con precisione alla domanda originale, basta:

  1. Apri il tuo logo.svgin un editor di testo.

  2. cercalo fill: #fffe sostituiscilo confill: #000

Ad esempio, logo.svgpotresti apparire così quando viene aperto in un editor di testo:

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

... basta cambiare il riempimento e salvare.


6
... e se non c'è "riempimento", puoi semplicemente aggiungerlo a patho circleelementi come <path fill="#777777" d="m129.774,74.409c-5.523,....
SaeX,

1
cosa succede se il mio logo ha un colore nell'intestazione e un altro colore nel piè di pagina?
rubens.lopes,

. @ ruben.lopes due file diversi, o due diversi inline sarebbero i più semplici
Rowe Morehouse,

11
puoi anche usare fill="currentColor"poi colorsull'elemento genitore css-tricks.com/cascading-svg-fill-color
Serge

10
Questo è ovviamente possibile e non è davvero una risposta utile.
Timmmm

101

Puoi impostare il tuo SVG come maschera. In questo modo l'impostazione di un colore di sfondo fungerebbe da colore di riempimento.

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

Verifica se il tuo browser supporta questa funzione: https://caniuse.com/#search=mask


3
Quindi per tutto tranne che per il sito Web interno inutilizzabile.
Henrik Vendelbo,

9
89% di supporto globale al 29 maggio 2016.
Gajus

1
Questa è una soluzione straordinaria per situazioni come quella qui descritta , in cui l'utilizzo di qualsiasi cosa diversa dall'uris di dati in CSS è un po 'una seccatura. Grazie!
Gark Garcia,

3
la sua non funziona. dice maskè un invalid property value. lo sto testando in Chrome.
Eren555,

1
@MadMac Sto eseguendo la stessa versione di Chrome, ma non sono stato in grado di replicare quel comportamento. È il JSFiddle che hai provato o il tuo codice?
André Kuhlmann,

78

Prova CSS puro:

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

maggiori informazioni in questo articolo https://blog.union.io/code/2017/08/10/img-svg-fill/


Stavo ottenendo un colore diverso su Edge rispetto ad altri browser con uno dei miei tentativi di recente.
Julix

4
Funziona con la maggior parte dei browser ma ho avuto dei problemi con il browser IOS-Safari.
Simon Ludwig,

30

2018: se vuoi un colore dinamico, non vuoi usare javascript e non vuoi un SVG in linea, usa una variabile CSS. Funziona su Chrome, Firefox e Safari. modifica: e Edge

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

Nel tuo SVG, sostituisci tutte le istanze di style="fill: #000"con style="fill: var(--color_fill)".


1
Qual è il supporto del browser per questo
Kevin Goedecke,

@KevinGoedecke Chrome, Firefox, Safari and Edge
nordamericano

4
Sembra deprecato in SVG 2
vsync

5
@northamerican: i collegamenti ad altre risposte dello stackoverflow in quanto "prove" sono irrilevanti. chiunque può scrivere qualsiasi cosa su questa piattaforma. 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
Sembra che xlink:hrefsia deprecato a favore di href. Quindi potrebbe funzionare ancora.
Benjamin Intal,

20

Dovrai prima iniettare SVG nel DOM HTML.

C'è una libreria open source chiamata SVGInject che fa questo per te. Utilizza l' onloadattributo per attivare l'iniezione.

Ecco un esempio minimo usando SVGInject:

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

Dopo che l'immagine è stata caricata, onload="SVGInject(this)verrà innescata l'iniezione e l' <img>elemento verrà sostituito dal contenuto del file SVG fornito srcnell'attributo.

Risolve diversi problemi con l'iniezione SVG:

  1. Gli SVG possono essere nascosti fino al termine dell'iniezione. Questo è importante se uno stile è già applicato durante il tempo di caricamento, che altrimenti causerebbe un breve "flash di contenuto non stilato".

  2. Gli <img>elementi si iniettano automaticamente. Se aggiungi SVG in modo dinamico, non devi preoccuparti di chiamare nuovamente la funzione di iniezione.

  3. Una stringa casuale viene aggiunta a ciascun ID nel file SVG per evitare di avere lo stesso ID più volte nel documento se un SVG viene iniettato più di una volta.

SVGInject è semplice Javascript e funziona con tutti i browser che supportano SVG.

Disclaimer: sono il coautore di SVGInject


3
Questa è la risposta più semplice. L'ho provato su Chrome, Firefox ed Edge e funziona perfettamente.
Sébastien Lorion,

15

La risposta di @Praveen è solida.

Non riuscivo a farlo rispondere nel mio lavoro, quindi ho creato una funzione di passaggio del mouse per esso.

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
questo non funzionerebbe solo se l'SVG fosse in linea per cominciare?
Daniel Thompson,

Sì, ma se lavori con molti file SVG o li aggiorni regolarmente, è un problema da gestire.
Matt Wujek,

15

Perché non creare un webfont con l'immagine o le immagini svg, importare il webfont nel CSS e quindi cambiare semplicemente il colore del glifo usando l'attributo color CSS? Non è necessario JavaScript


5
Se il tuo svg ha diversi elementi di diversi colori, questa soluzione diventa molto confusa (diversi elementi interposti).
Kakaja,

1
@kakaja Questa è una soluzione solo per le immagini vettoriali che contengono 1 colore. vedi la risposta di bpulecio per maggiori dettagli
gringo,

1
Perché l'icona non è testo. I caratteri sono per il testo. Svg sono per le icone.
Lazar Ljubenović,

2
@ LazarLjubenović - tecnicamente il testo è fatto di caratteri che sono simboli e le icone sono anche simboli, quindi questo è il motivo per cui molti non hanno problemi ad usare i caratteri icona. è come creare "un altro" linguaggio testuale. Il mandarino usa "icone" e non anche lettere, non è raro nell'umanità usare le icone come "testo"
vsync

1
mentre questa suona come una soluzione interessante, consiglio vivamente di elaborare la risposta in qualcosa di più simile a "come fare" invece di "perché no"
YakovL

15

Questa risposta si basa sulla risposta https://stackoverflow.com/a/24933495/3890888 ma con una versione JavaScript semplice dello script utilizzato lì.

Devi rendere SVG un SVG in linea . Puoi utilizzare questo script aggiungendo una classe svgall'immagine:

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

    });

});

E poi, ora se lo fai:

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

O forse:

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

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


1
Ottimo .. funziona. Inoltre, se la nostra pagina ha più svg, dovremo inserire il blocco fetch nell'IIFE.
Sandeep Sharma,

1
Grande! Funziona bene con ES6. Se non ti interessa IE 9 puoi anche usare: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi il

Non funziona in UIWebView su iOS 9.3.5. Io penso che potrebbe essere dovuto all'uso di fetchche è stato aggiunto a Safari a 10,1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). La versione jQuery sopra funziona.
Maria-Ines Carrera,

7

Usa i filtri per trasformarti in qualsiasi colore.

Di recente ho trovato questa soluzione e spero che qualcuno possa usarla. Poiché la soluzione utilizza filtri, può essere utilizzata con qualsiasi tipo di immagine. Non solo svg.

Se hai un'immagine a un colore di cui vuoi solo cambiare il colore, puoi farlo con l'aiuto di alcuni filtri. Funziona anche su immagini multicolori, ma non puoi scegliere come target un colore specifico. Solo l'intera immagine.

I filtri provenivano dallo script proposto in Come trasformare il nero in un dato colore usando solo i filtri CSS Se vuoi cambiare il bianco in qualsiasi colore, puoi regolare il valore invertito in ciascun filtro.

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


4

Per espandere la risposta di @gringo, il metodo Javascript descritto in altre risposte funziona, ma richiede all'utente di scaricare file di immagini non necessari e, IMO, blocca il codice.

Penso che un approccio migliore sarebbe quello di migrare tutta la grafica vettoriale a 1 colore in un file webfont. Ho usato Fort Awesome in passato e funziona benissimo per combinare le tue icone / immagini personalizzate in formato SVG, insieme a qualsiasi icona di terze parti che potresti utilizzare (Font Awesome, icone Bootstrap, ecc.) In un singolo file webfont l'utente deve scaricare. Puoi anche personalizzarlo, in modo da includere solo le icone di terze parti che stai utilizzando. Ciò riduce il numero di richieste che la pagina deve effettuare e il peso complessivo della pagina, soprattutto se si stanno già includendo librerie di icone di terze parti.

Se preferisci un'opzione più orientata allo sviluppo, potresti Google "npm svg webfont" e utilizzare uno dei moduli del nodo più appropriato per il tuo ambiente.

Una volta, hai fatto una di queste due opzioni, quindi potresti facilmente cambiare il colore tramite CSS e, molto probabilmente, hai velocizzato il tuo sito nel processo.


Dovresti provare gli sprite SVG. Nella mia esperienza, i font Web hanno problemi casuali tra le versioni del browser. Prova questo: fontastic.me - ma usa le versioni sprite di SVG - e vedi cosa ne pensi. :)
sheriffderek

4

Se stai semplicemente cambiando l'immagine tra il colore reale e il bianco e nero, puoi impostare un selettore come:

{Filtro: none;}

e un altro come:

{filter:grayscale(100%);}

3

Semplice..

Puoi usare questo codice:

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

Prima specifica il percorso di svg e poi scrivi il suo ID, in questo caso "Capa_1". È possibile ottenere l'ID di svg aprendolo in qualsiasi editor.

In css:

.logo {
  fill: red;
}

kabrice, puoi usare questo codice codepen.io/hmzajmal/pen/ZEGvWYa
Hamza Jamal

2

Il problema principale nel tuo caso è che stai importando lo svg da un <img>tag che nasconderà la struttura SVG.

È necessario utilizzare il <svg>tag insieme a <use>per ottenere l'effetto desiderato. Per farlo funzionare, è necessario indicare idil percorso che si desidera utilizzare nel file SVG <path id='myName'...>per poterli recuperare dal <use xlink:href="#myName"/>tag. Prova lo snipped di seguito.

Nota che puoi inserire qualsiasi URL prima del frammento #se desideri caricare SVG da una fonte esterna (e non incorporarlo nel tuo HTML). Inoltre, di solito non si specifica il riempimento nel CSS. È meglio considerare l'utilizzo fill:"currentColor"all'interno dello stesso SVG. Verrà quindi utilizzato il valore di colore CSS dell'elemento corrispondente.


2

Poiché SVG è fondamentalmente un codice, sono necessari solo i contenuti. Ho usato PHP per ottenere contenuti, ma puoi usare quello che vuoi.

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

Quindi, ho stampato il contenuto "così com'è" all'interno di un contenitore div

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

Per impostare in modo definitivo la regola sui figli SVG del container su CSS

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

Ho ottenuto questi risultati con un'icona materiale SVG:

Mozilla Firefox 59.0.2 (64-bit) Linux

inserisci qui la descrizione dell'immagine

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

inserisci qui la descrizione dell'immagine

Opera 53.0.2907.37 Linux

inserisci qui la descrizione dell'immagine


Non posso sottovalutare, ma per favore mai e poi mai.
levigatrice

5
Motivi? Alternative?
Benjamin,

La mia ragione per non farlo è che questo impedisce al browser di memorizzare nella cache l'SVG. L'alternativa è usare un iniettore SVG menzionato in alcune altre risposte qui. Il file SVG verrà comunque memorizzato nella cache dal browser e lo SVG iniettato può comunque essere disegnato con CSS. Ma non ti sottovaluto.
Sơn Trần-Nguyễn

Capisco, ma comunque, la cache non è menzionata. La migliore risposta ha un codice JavaScript che può essere ricaricato (o meno) ogni volta che l'intestazione scade la manipolazione o forza un hash dopo il collegamento al nome del file. Grazie per non sottovalutare, ma continuo a credere che la mia risposta risolva la modifica di un SVG utilizzando l'attributo fill CSS.
Benjamin

2

Questo potrebbe essere utile per le persone che usano PHPin combinazione con.svg immagini che vogliono manipolare con i CSS.

Non puoi sovrascrivere le proprietà all'interno di un tag img con CSS. Ma quando il codice sorgente svg è incorporato nell'HTML puoi sicuramente farlo. Mi piace risolvere questo problema con una require_oncefunzione in cui includo a.svg.php file. È come importare un'immagine ma puoi comunque sovrascrivere gli stili con i CSS!

Per prima cosa includi il file svg:

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

E include questa icona per esempio:

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

Ora possiamo facilmente cambiare il colore di riempimento in questo modo con CSS:

svg path {
  fill: blue;
}

Prima ho provato a risolvere questo problema, file_get_contents()ma la soluzione sopra è molto più veloce.


0

Sappi che questa è una vecchia domanda, ma recentemente abbiamo riscontrato lo stesso problema e l'abbiamo risolto dal lato server. Questa è una risposta specifica per php, ma sono certo che altri envs abbiano qualcosa di simile. invece di usare il tag img visualizzi lo svg come svg dall'inizio.

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

ora quando si esegue il rendering del file si otterrà svg completo in linea


0

apri l'icona svg nel tuo editor di codice e aggiungi una classe dopo il tag path:

<path class'colorToChange' ...

Puoi aggiungere classe a svg e cambiare il colore in questo modo:

codepen


-2

Se si ha accesso a JQuery, estendendosi alla risposta di Praveen si può cambiare programmaticamente il colore di diversi elementi nidificati all'interno di SVG:

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

All'interno di find, puoi citare diversi elementi che devono essere cambiati di colore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.