Bagaimana cara mendesain SVG dengan CSS eksternal?

102

Saya memiliki beberapa grafik SVG yang ingin saya ubah warnanya melalui style sheets eksternal saya - tidak secara langsung di dalam setiap file SVG. Saya tidak meletakkan grafik sebaris, tetapi menyimpannya di folder gambar saya dan mengarahkannya.

Saya telah menerapkannya dengan cara ini untuk memungkinkan tooltips bekerja, dan saya juga membungkus masing-masing dengan <a>tag untuk memungkinkan tautan.

<a href='http://youtube.com/...' target='_blank'><img class='socIcon' src='images/socYouTube.svg' title='View my videos on YouTube' alt='YouTube' /></a>

Dan berikut adalah kode grafik 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>

Saya meletakkan yang berikut ini di file CSS eksternal saya (main.css):

.socIcon g {fill:red;}

Namun itu tidak berpengaruh pada grafik. Saya juga mencoba jalur .socIcon g {} dan jalur .socIcon {}.

Ada yang tidak beres, mungkin penerapan saya tidak mengizinkan modifikasi CSS eksternal, atau saya melewatkan satu langkah? Saya sangat menghargai bantuan Anda! Saya hanya perlu kemampuan untuk mengubah warna grafik SVG melalui stylesheet eksternal saya, tetapi saya tidak bisa kehilangan kemampuan tooltip dan tautan. (Saya mungkin bisa hidup tanpa tooltips.) Terima kasih!

Jordan H
sumber
Coba svg { fill:red; }atau beri nama kelas pada jalur Anda. Misalnya <path class="socIcon" d="M28.44 ..... />ini harus melakukan trik.
Dwza

Jawaban:

92

File main.css Anda hanya akan berpengaruh pada konten SVG jika file SVG disertakan sebaris dalam 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>

Jika Anda ingin menyimpan SVG dalam file, CSS perlu ditentukan di dalam file SVG.

Anda dapat melakukannya dengan tag gaya:

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>

Anda dapat menggunakan alat di sisi server untuk memperbarui tag gaya bergantung pada gaya aktif. Di ruby ​​Anda bisa mencapai ini dengan Nokogiri. SVG hanyalah XML. Jadi mungkin ada banyak pustaka XML yang tersedia yang mungkin bisa mencapai ini.

Jika Anda tidak dapat melakukan itu, Anda hanya perlu menggunakannya seolah-olah mereka adalah PNG; membuat satu set untuk setiap gaya, dan menyimpan gaya mereka sebaris.

RGB
sumber
17
Apakah ini berarti bahwa tidak ada metode untuk memanfaatkan cache SVG dan menerapkan gaya yang bervariasi? Inline tampaknya tidak melakukan cache dengan baik, sementara metode lain memerlukan pembuatan banyak versi gambar, menghilangkan manfaat apa pun dari cache.
msg45f
Cara lain adalah dengan menyandikan SVG sebagai uris data gambar latar belakang, dengan warna berbeda pada setiap versi dan bergantung pada gzip untuk mengurangi ukuran file akibat duplikasi.
Ruskin
1
Dalam kasus saya, saya ingin mengganti gaya elemen dari SVG. CSS saya tidak berfungsi, karena gaya elemen memiliki prioritas yang lebih tinggi. Solusi paling sederhana adalah menambahkan! Penting ke gaya CSS untuk SVG. Kemudian semuanya baik-baik saja. Jika Anda ingin menghindari! Penting, Anda perlu memindahkan gaya elemen ke dalam CSS.
David Gausmann
sayang sekali Anda tidak dapat memuat stylesheet di dalam svg dari URL
clayRay
1
@clayRay Anda akan dapat melakukannya dengan cara itu setelah SVG2 menyelesaikan draf w3.org/TR/SVG2/styling.html#LinkElement
RGB
51

Anda dapat melakukan apa yang Anda inginkan, dengan satu peringatan (penting): jalur di dalam simbol Anda tidak dapat diberi gaya secara independen melalui CSS eksternal - Anda hanya dapat menyetel properti untuk seluruh simbol dengan metode ini. Jadi, jika Anda memiliki dua jalur dalam simbol Anda dan ingin mereka memiliki warna isian yang berbeda, ini tidak akan berhasil, tetapi jika Anda ingin semua jalur Anda sama, ini seharusnya berfungsi.

Di file html Anda, Anda menginginkan sesuatu seperti ini:

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

Dan di file SVG eksternal Anda menginginkan sesuatu seperti ini:

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol id="example" viewBox="0 0 256 256">
    <path d="M120.... />
  </symbol>
</svg>

Tukar kelas pada svgtag (dalam html Anda) dari fill-redke fill-bluedan ta-da ... Anda memiliki warna biru, bukan merah.

Anda dapat menyiasati sebagian batasan untuk dapat menargetkan jalur secara terpisah dengan CSS eksternal dengan mencampur dan mencocokkan CSS eksternal dengan beberapa CSS sebaris di jalur tertentu, karena CSS sebaris akan diutamakan. Pendekatan ini akan bekerja jika Anda melakukan sesuatu seperti ikon putih dengan latar belakang berwarna, di mana Anda ingin mengubah warna latar belakang melalui CSS eksternal tetapi ikon itu sendiri selalu putih (atau sebaliknya). Jadi, dengan HTML yang sama seperti sebelumnya dan sesuatu seperti kode svg ini, Anda akan mendapatkan latar belakang merah dan jalur latar depan putih:

<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>
Adam Korman
sumber
jawaban yang bagus .. menurut saya peringatannya harus: Dukungan Browser, meskipun! referensi yang baik (lebih detail daripada caniuse): css-tricks.com/svg-fragment-identifiers-work
ptim
Ini solusinya! Sebenarnya tidak perlu untuk membungkus seluruh konten svg dalam sebuah symbolelemen, yaitu Anda dapat memberikannya idke elemen svg, jadi: `<svg id = example" xmlns = " w3.org/2000/svg " viewBox = "0 0256 256 "> <path class =" background "d =" M120 ... "/> <path class =" icon "style =" fill: white; "d =" M20 ... "/> </ svg > ``
SimoneMSR
12

Anda dapat memasukkan tautan file SVG ke file css eksternal menggunakan:

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

Anda harus meletakkan ini setelah tag pembuka:

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

Ini bukan solusi sempurna, karena Anda harus memodifikasi file svg, tetapi Anda memodifikasinya sekali dan semua perubahan gaya dapat dilakukan dalam satu file css untuk semua file svg.

Jacek Mamot
sumber
1
Wow, ini berhasil, namun hanya 1 suara positif ... apakah solusi ini bagus untuk semua situasi? Sangat sederhana, mengapa ini bukan jawaban yang dipilih?
Bruno Vincent
Intinya adalah memusatkan definisi gaya Anda. Katakanlah Anda memiliki 10 SVG yang ingin Anda gaya. Sekarang Anda perlu menyalin referensi ke CSS ke semua SVG yang perlu terpengaruh. Dan jika nama file / lokasi CSS Anda berubah, Anda perlu memperbaruinya dalam 10 SVG. Kelas CSS terasa jauh lebih simbolis daripada referensi ke file CSS fisik.
Frans
Perhatikan bahwa svg yang dimuat melalui tag <img> tidak akan memuat konten eksternal (misalnya, lembar gaya).
Moose Morals
7

Dimungkinkan untuk menata SVG dengan secara dinamis membuat elemen gaya dalam JavaScript dan menambahkannya ke elemen SVG. Hacky, tapi berhasil.

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

Anda dapat membuat JavaScript secara dinamis di PHP jika Anda mau - fakta bahwa hal ini dimungkinkan dalam JavaScript membuka banyak sekali kemungkinan.

Pete
sumber
hai saya benar-benar menyukai solusi Anda dan ini berfungsi tetapi saya perlu mengadopsinya pada situasi saya jika Anda bersedia membantu kursus os, saya memiliki di dalam <defs> tag gaya saya dapat menghapusnya secara manual dan menjalankan kode ini sehingga itu akan membuat sebuah gaya, apakah ada cara saya dapat menghapus defs kemudian membuat ulang elemen seperti yang Anda lakukan atau hanya memperbaruinya, dan juga url mendapat url kesalahan tidak ditentukan dapatkah Anda membantu, terima kasih
Kamel Mili
6

Salah satu pendekatan yang dapat Anda lakukan hanyalah menggunakan filter CSS untuk mengubah tampilan grafik SVG di browser.

Misalnya, jika Anda memiliki grafik SVG yang menggunakan warna isian merah di dalam kode SVG, Anda dapat mengubahnya menjadi ungu dengan pengaturan hue-rotate 180 derajat:

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

Bereksperimenlah dengan pengaturan hue-rotate lainnya untuk menemukan warna yang Anda inginkan.

Untuk memperjelas, CSS di atas masuk ke dalam CSS yang diterapkan ke dokumen HTML Anda. Anda memberi gaya pada tag img dalam kode HTML, bukan memberi gaya pada kode SVG.

Dan perhatikan bahwa ini tidak akan berfungsi dengan grafik yang memiliki isian hitam atau putih atau abu-abu. Anda harus memiliki warna sebenarnya di sana untuk memutar corak warna itu.

Simon White
sumber
4

Solusi yang sangat cepat untuk memiliki gaya dinamis dengan stylesheet css eksternal, jika Anda menggunakan <object>tag untuk menyematkan svg.

Contoh ini akan menambahkan kelas ke <svg>tag root saat diklik pada elemen induk.

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

pada elemen induk klik:

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="" class="selected">

lalu Anda dapat mengelola css Anda

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;
}
vhanahrni
sumber
sepertinya tidak berfungsi, dapatkah Anda menambahkan contoh yang berfungsi?
Jeanluca Scaljeri
4

Ini harus dapat dilakukan dengan terlebih dahulu membuat sebaris gambar svg eksternal. Kode di bawah ini berasal dari mengganti semua gambar SVG dengan SVG inline oleh Jess Frazelle.

$('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);
  });
});
Leo
sumber
3
Perlu diperhatikan bahwa ini hanya akan berfungsi jika Anda memiliki gambar yang dihosting di domain yang sama dengan html, atau memiliki kebijakan lintasdomain yang dikonfigurasi secara khusus di server gambar. $ .get akan menggunakan ajax dan gagal memuat gambar dari server eksternal jika tidak ada header allow-access yang valid
user151496
ini legendaris
Tino Costa 'El Nino'
2

Saat digunakan dalam <image>tag, SVG harus terkandung dalam satu file untuk alasan privasi. Bug bugzilla ini memiliki detail lebih lanjut tentang mengapa demikian. Sayangnya Anda tidak dapat menggunakan tag yang berbeda seperti <iframe>karena itu tidak akan berfungsi sebagai tautan sehingga Anda harus menyematkan CSS di <style>tag di dalam file itu sendiri.

Satu cara lain untuk melakukannya adalah dengan memiliki data SVG di dalam file html utama yaitu

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

Anda dapat mengatur gaya itu dengan file CSS eksternal menggunakan <link>tag HTML .

Robert Longson
sumber
2
Saya tidak bisa meletakkan gaya di dalam file. Saya sebenarnya akan mengubah warna gambar-gambar ini berdasarkan skema warna apa yang telah dipilih pengguna untuk situs saya. Implementasi saya saat ini adalah menambahkan stylesheet ke halaman utama yang menimpa gaya default. Saya ingin mengubah warna pada file itu untuk mempengaruhi grafik SVG yang disematkan. Tapi itu tidak akan berhasil karena saya harus menautkan ke stylesheet dari dalam file SVG (kecuali ada cara untuk menambahkan tautan itu ke semua file SVG menggunakan JavaScript juga). Tentunya ada cara untuk mengizinkan file SVG eksternal, CSS eksternal, tautan, dan tooltips.
Jordan H
1
Tidak mungkin melakukan apa yang ingin Anda lakukan karena model keamanan browser. Anda tidak dapat menggunakan javascript untuk memanipulasi SVG saat digunakan sebagai gambar. Bayangkan SVG saat digunakan sebagai gambar seperti file animasi png atau gif, semuanya dalam satu file dan tanpa akses skrip.
Robert Longson
1

"Saya sebenarnya akan mengubah warna gambar ini berdasarkan skema warna apa yang telah dipilih pengguna untuk situs saya." - Jordan 10 jam yang lalu

Saya menyarankan Anda untuk menggunakan PHP untuk ini. Benar-benar tidak ada cara yang lebih baik untuk melakukan ini tanpa font ikon, dan jika Anda menolak menggunakannya, Anda dapat mencoba ini:

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

Dan nanti Anda bisa menggunakan file ini filename.php?color=#ffffffuntuk mendapatkan file svg dengan warna yang diinginkan.

SeinopSys
sumber
6
Perhatikan bahwa kode ini tidak memeriksa masukan pengguna - apa pun dapat diberikan sebagai warna dan SVG Anda mungkin ditampilkan dalam beberapa cara yang sangat menarik ... Tidak yakin apakah itu memengaruhi Anda, tetapi Anda harus membiasakan SELALU memvalidasi masukan pengguna. Sesuatu seperti ini akan membantu: if (!preg_match('/^[#][0-9a-f]{6}$/i', $_GET['color'])) die('Oops!');(letakkan di suatu tempat di blok awal PHP).
johndodo
1

Apa yang berhasil untuk saya: tag gaya dengan aturan @import

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

Saya tahu ini posting lama, tetapi hanya untuk menyelesaikan masalah ini ... Anda hanya menggunakan kelas Anda di tempat yang salah: D

Pertama-tama Anda bisa menggunakan

svg { fill: red; }

di dalam dirimu main.cssuntuk membuatnya merah. Ini memang berpengaruh. Anda juga dapat menggunakan pemilih node untuk mendapatkan jalur tertentu.

Hal kedua adalah, Anda mendeklarasikan kelas ke img-Tag.

<img class='socIcon'....

Anda sebenarnya harus mendeklarasikannya di dalam SVG Anda. jika Anda memiliki jalur yang berbeda, tentu saja Anda dapat menentukan lebih lanjut.

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

sekarang Anda bisa mengubah warna dalam Anda main.cssseperti

.myClassForMyPath {
    fill: yellow;
}
Dwza
sumber
Mencoba ini, tidak berhasil, seperti yang sudah dikatakan banyak jawaban lain. Anda tidak dapat menerapkan gaya ke kelas di dalam SVG.
Frans
@Frans apakah Anda menyertakan svg sebagai file atau apakah Anda memiliki sumber svg seperti pada contoh di atas? Karena saya ada dalam pikiran saya bahwa ini tergantung pada bagaimana Anda menggunakan svg. Termasuk dengan img tidak akan berfungsi.
Dwza
Tepatnya, ini hanya berfungsi jika Anda menyebariskan SVG di HTML Anda. Tapi bukan itu yang dilakukan oleh teladan Anda. Ini menggunakan SVG eksternal (bukan inline). Sepertinya tidak ada cara untuk menata SVG eksternal dengan CSS di HTML Anda.
Frans
yakin Anda mencoba contoh saya benar? maksud saya, termasuk file css dari eksternal? <?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
Dwza
Oke, sekarang saya mengerti, Anda memiliki <?xml-stylesheet ... ?>deklarasi di dalam SVG Anda. Saya rasa itu akan berhasil. Ini mirip dengan jawaban lain yang merekomendasikan bagian <link rel="stylesheet" ... >dalam SVG. Ini juga memiliki masalah yang sama (Anda perlu memperbarui setiap SVG agar mengarah ke stylesheet, dan setiap perubahan nama atau lokasi stylesheet berarti harus mengubah semua SVG lagi).
Frans
1
  1. Untuk gaya Eksternal

<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. Untuk Gaya Internal

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

Catatan: Gaya Eksternal tidak akan berfungsi jika Anda menyertakan SVG di dalam <img>tag. Ini akan bekerja dengan sempurna di dalam <div>tag

Yuvraj Patil
sumber
0

@leo ini adalah versi angularJS, terima kasih lagi

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

                } );

            } );
        }

    }

}

} );
Tino Costa 'El Nino'
sumber
-1

Metode ini akan berfungsi jika svg dilihat di dalam browser web tetapi segera setelah kode ini diunggah ke server dan kelas untuk ikon svg diberi kode seolah-olah itu adalah gambar latar belakang warnanya hilang dan kembali ke warna default . Sepertinya warna tidak dapat diubah dari style sheet eksternal meskipun kelas svg untuk warna dan kelas lapisan atas untuk tampilan dan posisi dari svg keduanya dipetakan ke direktori yang sama.

HTMLGUY1999
sumber