img src SVG mengubah gaya dengan CSS

374

html

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

css

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

Svg di atas memuat dan secara asli fill: #ffftetapi ketika saya menggunakan di atas cssuntuk mencoba mengubahnya menjadi hitam itu tidak berubah, ini adalah pertama kalinya saya bermain dengan SVG dan saya tidak yakin mengapa itu tidak berfungsi.

ngplayground
sumber
25
Anda tidak dapat memengaruhi gambar SVG seperti itu ... hanya elemen SVG sebaris
Paulie_D
Periksa jawaban saya di sini untuk menggunakan konten SVG dan CSS. stackoverflow.com/questions/11978995/…
Benjamin

Jawaban:

153

Jika tujuan Anda hanya untuk mengubah warna logo, dan Anda tidak perlu PERLU menggunakan CSS, maka jangan gunakan javascript atau jquery seperti yang disarankan oleh beberapa jawaban sebelumnya.

Untuk menjawab pertanyaan awal dengan tepat, cukup:

  1. Buka logo.svgeditor teks Anda.

  2. mencari fill: #fffdan menggantinya denganfill: #000

Misalnya, Anda logo.svgmungkin terlihat seperti ini ketika dibuka di editor teks:

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

... ganti saja isi dan simpan.

Rowe Morehouse
sumber
6
... dan jika tidak ada "isi", Anda bisa menambahkannya ke item pathatau circlesuka <path fill="#777777" d="m129.774,74.409c-5.523,....
SaeX
1
bagaimana jika logo saya memiliki satu warna di header dan warna lain di footer?
rubens.lopes
. @ ruben.lopes dua file berbeda, atau dua inline berbeda akan menjadi paling sederhana
Rowe Morehouse
11
Anda dapat menggunakan juga fill="currentColor"kemudian gunakan colorpada elemen induk css-tricks.com/cascading-svg-fill-color
Serge
10
Ini jelas mungkin dan bukan jawaban yang sangat membantu.
Timmmm
101

Anda bisa mengatur SVG Anda sebagai topeng. Dengan cara mengatur warna latar akan bertindak sebagai warna isi Anda.

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

Silakan periksa apakah browser Anda mendukung fitur ini: https://caniuse.com/#search=mask

André Kuhlmann
sumber
3
Jadi untuk apa pun kecuali situs web internal tidak dapat digunakan.
Henrik Vendelbo
9
89% dukungan global per 29 Mei 2016.
Gajus
1
Ini adalah solusi yang luar biasa untuk situasi seperti yang dijelaskan di sini , di mana menggunakan apa pun selain data uris dalam css agak menyusahkan. Terima kasih!
Gark Garcia
3
ini tidak bekerja. katanya maskadalah invalid property value. saya menguji ini di chrome.
Eren555
1
@MadMac Saya menjalankan versi Chrome yang sama, tetapi saya tidak dapat meniru perilaku itu. Apakah itu JSFiddle yang Anda coba atau kode Anda?
André Kuhlmann
78

Coba CSS murni:

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

info lebih lanjut dalam artikel ini https://blog.union.io/code/2017/08/10/img-svg-fill/

Feri
sumber
Sudah mendapatkan warna yang berbeda di Edge daripada di browser lain dengan salah satu upaya saya baru-baru ini.
Julix
4
Ini berfungsi di sebagian besar browser tetapi saya memiliki beberapa masalah dengan browser iOS-Safari.
Simon Ludwig
30

2018: Jika Anda ingin warna yang dinamis, tidak ingin menggunakan javascript dan tidak ingin SVG inline, gunakan variabel CSS. Bekerja di Chrome, Firefox, dan Safari. edit: dan Edge

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

Di SVG Anda, ganti instance style="fill: #000"dengan style="fill: var(--color_fill)".

Amerika Utara
sumber
1
Apa dukungan browser untuk ini
Kevin Goedecke
@KevinGoedecke Chrome, Firefox, Safari dan Edge
northamerican
4
Tampak usang dalam SVG 2
vsync
5
@northamerican - tautan ke jawaban stackoverflow lainnya karena "bukti" tidak relevan. siapa pun dapat menulis apa pun di platform ini. 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
Tampaknya xlink:hrefsudah usang mendukung href. Jadi ini mungkin masih berfungsi.
Benjamin Intal
20

Pertama-tama Anda harus menyuntikkan SVG ke HTML DOM.

Ada pustaka sumber terbuka bernama SVGInject yang melakukan ini untuk Anda. Ini menggunakan onloadatribut untuk memicu injeksi.

Berikut adalah contoh minimal menggunakan SVGInject:

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

Setelah gambar dimuat, onload="SVGInject(this)akan memicu injeksi dan <img>elemen akan diganti dengan isi file SVG yang disediakan dalam srcatribut.

Ini memecahkan beberapa masalah dengan injeksi SVG:

  1. SVG dapat disembunyikan sampai injeksi selesai. Ini penting jika gaya sudah diterapkan selama waktu pemuatan, yang jika tidak akan menyebabkan "flash konten tanpa gaya" singkat.

  2. <img>Unsur - unsur menyuntikkan diri secara otomatis. Jika Anda menambahkan SVG secara dinamis, Anda tidak perlu khawatir tentang memanggil fungsi injeksi lagi.

  3. String acak ditambahkan ke setiap ID dalam SVG untuk menghindari memiliki ID yang sama beberapa kali dalam dokumen jika SVG disuntikkan lebih dari satu kali.

SVGInject adalah Javascript biasa dan bekerja dengan semua browser yang mendukung SVG.

Penafian: Saya adalah rekan penulis SVGInject

Waruyama
sumber
3
Ini adalah jawaban yang paling mudah. Saya mengujinya di Chrome, Firefox dan Edge dan berfungsi dengan baik.
Sébastien Lorion
15

Jawaban dari @Praveen solid.

Saya tidak bisa membuatnya merespons dalam pekerjaan saya, jadi saya membuat fungsi jquery hover untuk itu.

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
sumber
1
tidakkah ini hanya bekerja jika SVG inline untuk memulai?
Daniel Thompson
Ya — tetapi jika Anda bekerja dengan banyak file SVG atau memperbaruinya secara teratur, itu sulit untuk dikelola.
Matt Wujek
15

Mengapa tidak membuat webfont dengan gambar svg Anda atau gambar, mengimpor webfont di css dan kemudian hanya mengubah warna mesin terbang menggunakan atribut warna css? Tidak diperlukan javascript

gringo
sumber
5
Jika svg Anda memiliki beberapa elemen warna yang berbeda, solusi ini menjadi sangat rumit (beberapa elemen dimasukkan).
kakaja
1
@ kakaja Ini adalah solusi hanya untuk gambar vektor yang memiliki 1 warna di dalamnya. lihat jawaban bpulecio untuk lebih jelasnya
gringo
1
Karena ikon bukan teks. Font adalah untuk teks. Svgs adalah untuk ikon.
Lazar Ljubenović
2
@ LazarLjubenović - secara teknis teks terbuat dari karakter yang merupakan simbol, dan ikon juga simbol, jadi inilah mengapa banyak yang tidak memiliki masalah menggunakan ikon-font. itu seperti menciptakan bahasa teks "lain". Mandarin menggunakan "ikon" dan bukan huruf juga, tidak jarang dalam manusia menggunakan ikon sebagai "teks"
vsync
1
sementara ini terdengar sebagai solusi yang menarik, saya benar-benar merekomendasikan untuk menguraikan jawaban menjadi sesuatu yang lebih seperti "bagaimana" daripada "mengapa tidak"
YakovL
15

Jawaban ini didasarkan pada jawaban https://stackoverflow.com/a/24933495/3890888 tetapi dengan skrip JavaScript versi biasa yang digunakan di sana.

Anda perlu membuat SVG menjadi SVG sebaris . Anda dapat menggunakan skrip ini, dengan menambahkan kelas svgke gambar:

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

    });

});

Dan kemudian, sekarang jika Anda melakukannya:

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

Atau mungkin:

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

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

Seb3736
sumber
1
Hebat .. bekerja. selain itu jika halaman kita memiliki beberapa svgs maka kita harus meletakkan fetch block ke IIFE.
Sandeep Sharma
1
Bagus! Bekerja dengan baik dengan ES6. Jika Anda tidak peduli dengan IE 9, Anda bahkan dapat menggunakan: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi
Tidak bekerja di UIWebView di iOS 9.3.5. Saya pikir itu mungkin karena penggunaan fetchyang ditambahkan ke Safari di 10.1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). Versi jQuery di atas tidak berfungsi.
Maria-Ines Carrera
7

Gunakan filter untuk mengubah warna apa pun.

Saya baru-baru ini menemukan solusi ini, dan berharap seseorang mungkin dapat menggunakannya. Karena solusi menggunakan filter, maka dapat digunakan dengan semua jenis gambar. Bukan hanya svg.

Jika Anda memiliki gambar satu warna yang hanya ingin Anda ubah warnanya, Anda dapat melakukannya dengan bantuan beberapa filter. Ini berfungsi pada gambar multicolor juga tentu saja, tetapi Anda tidak dapat menargetkan warna tertentu. Hanya seluruh gambar.

Filter berasal dari skrip yang diajukan dalam Cara mengubah warna hitam menjadi warna apa pun yang hanya menggunakan filter CSS. Jika Anda ingin mengubah warna putih menjadi warna apa pun, Anda dapat menyesuaikan nilai invert di setiap filter.

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

Untuk memperluas jawaban @ gringo, metode Javascript yang dijelaskan dalam jawaban lain berfungsi, tetapi mengharuskan pengguna untuk mengunduh file gambar yang tidak perlu, dan IMO, itu menggembungkan kode Anda.

Saya pikir pendekatan yang lebih baik adalah dengan memigrasikan semua grafik vektor 1-warna ke file webfont. Saya telah menggunakan Fort Awesome di masa lalu, dan bekerja sangat baik untuk menggabungkan ikon / gambar khusus Anda dalam format SVG, bersama dengan ikon pihak ke-3 yang mungkin Anda gunakan (Font Awesome, ikon Bootstrap, dll.) Ke dalam satu file webfont pengguna harus mengunduh. Anda juga dapat menyesuaikannya, sehingga Anda hanya menyertakan ikon pihak ke-3 yang Anda gunakan. Ini mengurangi jumlah permintaan yang harus dibuat halaman, dan Anda secara keseluruhan berat halaman, terutama jika Anda sudah termasuk ikon pihak ketiga perpustakaan.

Jika Anda lebih suka opsi yang lebih berorientasi pada dev, Anda dapat Google "npm svg webfont" , dan menggunakan salah satu modul simpul yang paling tepat untuk lingkungan Anda.

Setelah, Anda melakukan salah satu dari dua opsi itu, maka Anda dapat dengan mudah mengubah warna melalui CSS, dan kemungkinan besar, Anda telah mempercepat situs Anda dalam proses.

bpulecio
sumber
Anda harus mencoba sprite SVG. Dalam pengalaman saya, font web memiliki masalah acak antara rilis browser. Coba ini: fontastic.me - tetapi gunakan versi sprite SVG - dan lihat apa yang Anda pikirkan. :)
sheriffderek
4

Jika Anda hanya mengganti gambar antara warna asli dan hitam-putih, Anda dapat menetapkan satu pemilih sebagai:

{filter: tidak ada;}

dan lainnya sebagai:

{filter:grayscale(100%);}
wcb1
sumber
3

Sederhana..

Anda dapat menggunakan kode ini:

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

Pertama tentukan path svg dan kemudian tulis ID-nya, Dalam hal ini "Capa_1". Anda bisa mendapatkan ID svg dengan membukanya di editor apa pun.

Dalam css:

.logo {
  fill: red;
}
Hamza Jamal
sumber
kabrice, Anda dapat menggunakan kode ini codepen.io/hmzajmal/pen/ZEGvWYa
Hamza Jamal
2

Masalah utama dalam kasus Anda adalah bahwa Anda mengimpor svg dari <img>tag yang akan menyembunyikan struktur SVG.

Anda harus menggunakan <svg>tag bersamaan dengan <use>untuk mendapatkan efek yang diinginkan. Untuk membuatnya berfungsi, Anda perlu memberikan idjalur yang ingin Anda gunakan dalam file SVG <path id='myName'...>untuk kemudian dapat mengambilnya dari <use xlink:href="#myName"/>tag. Cobalah potongan di bawah ini.

Perhatikan bahwa Anda dapat meletakkan URL apa pun sebelum fragmen #jika Anda ingin memuat SVG dari sumber eksternal (dan tidak menanamkannya ke HTML Anda). Juga, biasanya Anda tidak menentukan isi ke dalam CSS. Lebih baik mempertimbangkan menggunakan fill:"currentColor"dalam SVG itu sendiri. Nilai warna CSS elemen yang sesuai kemudian akan digunakan.

Flavien Volken
sumber
2

Karena SVG pada dasarnya adalah kode, Anda hanya perlu konten. Saya menggunakan PHP untuk mendapatkan konten, tetapi Anda dapat menggunakan apa pun yang Anda inginkan.

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

Lalu, saya sudah mencetak konten "apa adanya" di dalam wadah div

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

Untuk menetapkan aturan untuk anak SVG kontainer di CSS

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

Saya mendapat hasil ini dengan ikon materi SVG:

Mozilla Firefox 59.0.2 (64-bit) Linux

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

Opera 53.0.2907.37 Linux

masukkan deskripsi gambar di sini

Benjamin
sumber
Saya tidak bisa mengundurkan diri tetapi tolong jangan pernah melakukan ini.
sander
5
Alasan? Alternatif?
Benjamin
Alasan saya untuk tidak melakukan ini adalah karena ini mencegah browser untuk men-cache SVG. Alternatifnya adalah dengan menggunakan injektor SVG yang disebutkan dalam beberapa jawaban lain di sini. File SVG masih akan di-cache oleh browser, dan SVG yang diinjeksi masih bisa ditata dengan CSS. Tapi saya tidak menurunkan suara Anda.
Sần Trần-Nguyễn
Saya mengerti, tapi bagaimanapun, cache tidak disebutkan. Jawaban terbaik memiliki kode JavaScript yang dapat dimuat ulang (atau tidak) setiap kali dengan manipulasi header kedaluwarsa atau memaksakan hash setelah tautan nama file. Terima kasih untuk tidak downvote, tapi saya masih percaya bahwa jawaban saya memecahkan perubahan SVG menggunakan atribut isi CSS.
Benjamin
2

Ini mungkin bermanfaat bagi orang yang menggunakan PHPdalam kombinasi dengan .svggambar yang ingin mereka manipulasi dengan CSS.

Anda tidak dapat menimpa properti di dalam tag img dengan CSS. Tetapi ketika kode sumber svg tertanam dalam HTML Anda pasti bisa. Saya suka mengatasi masalah ini dengan require_oncefungsi tempat saya menyertakan .svg.phpfile. Ini seperti mengimpor gambar tetapi Anda masih bisa menimpa gaya dengan CSS!

Pertama-tama termasuk file svg:

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

Dan itu termasuk ikon ini misalnya:

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

Sekarang kita dapat dengan mudah mengubah warna isian seperti ini dengan CSS:

svg path {
  fill: blue;
}

Saya pertama kali mencoba menyelesaikan masalah ini dengan file_get_contents()tetapi solusi di atas jauh lebih cepat.

Floris
sumber
0

Tahu ini adalah pertanyaan lama tetapi baru-baru ini kami menemukan masalah yang sama, dan kami menyelesaikannya dari sisi server. Ini adalah jawaban khusus php tetapi saya yakin bahwa env lain memiliki sesuatu yang serupa. alih-alih menggunakan tag img Anda membuat svg sebagai svg dari awal.

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

sekarang ketika Anda membuat file Anda akan mendapatkan svg inline lengkap

nechemya ungar
sumber
0

buka ikon svg di editor kode Anda dan tambahkan kelas setelah tag path:

<path class'colorToChange' ...

Anda dapat menambahkan kelas ke svg dan mengubah warna seperti ini:

codepen

Hamza Jamal
sumber
-2

Jika Anda memiliki akses ke JQuery, maka lanjutkan ke jawaban Praveen, orang dapat secara programatik mengubah warna elemen bersarang yang berbeda di dalam SVG dengan:

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

Dalam find, Anda dapat menyebutkan elemen berbeda yang perlu diubah warnanya.

manyu
sumber