SVG'yi harici CSS ile nasıl biçimlendirebilirim?


102

Harici stil sayfalarım aracılığıyla renklerini değiştirmek istediğim birkaç SVG grafiğim var - doğrudan her SVG dosyasında değil. Grafikleri sıraya koymuyorum, onları resimlerim klasöründe depoluyorum ve onlara işaret ediyorum.

Araç ipuçlarının çalışmasına izin vermek için bunları bu şekilde uyguladım ve ayrıca <a>bir bağlantıya izin vermek için her birini bir etiketle sarmaladım.

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

Ve işte SVG grafiğinin kodu:

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

Aşağıdakileri harici CSS dosyama (main.css) koydum:

.socIcon g {fill:red;}

Yine de grafik üzerinde hiçbir etkisi yoktur. Ayrıca .socIcon g yolunu {} ve .socIcon yolunu {} denedim.

Bir şeyler doğru değil, belki benim uygulamam harici CSS değişikliklerine izin vermiyor veya bir adımı kaçırdım? Yardımın için gerçekten minnettarım! Yalnızca SVG grafiğinin renklerini harici stil sayfam aracılığıyla değiştirme yeteneğine ihtiyacım var, ancak araç ipucunu ve bağlantı yeteneğini kaybedemem. (Yine de ipucu olmadan yaşayabilirim.) Teşekkürler!



svg { fill:red; }Yolunuza bir sınıf adı verin veya deneyin . Örneğin, <path class="socIcon" d="M28.44 ..... />bu hile yapmalı.
Dwza

Yanıtlar:


92

Main.css dosyanız, SVG dosyasının HTML'de satır içi olarak yer alması durumunda yalnızca SVG'nin içeriği üzerinde etkili olacaktır:

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>

SVG'nizi dosyalarda tutmak istiyorsanız, CSS'nin SVG dosyasının içinde tanımlanması gerekir.

Bunu bir stil etiketiyle yapabilirsiniz:

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>

Etkin stile bağlı olarak stil etiketini güncellemek için sunucu tarafında bir araç kullanabilirsiniz. Ruby'de bunu Nokogiri ile başarabilirsiniz. SVG yalnızca XML'dir. Dolayısıyla, muhtemelen bunu başarabilecek birçok XML kitaplığı vardır.

Bunu yapamıyorsanız, onları PNG'lermiş gibi kullanmanız gerekecek; her stil için bir set oluşturmak ve stillerini satır içinde kaydetmek.


17
Bu, SVG'yi önbelleğe almaktan ve çeşitli stiller uygulamaktan yararlanacak bir yöntem olmadığı anlamına mı geliyor? Satır içi iyi önbellekleme yapmıyor gibi görünürken, diğer yöntemler görüntünün birçok sürümünü oluşturmayı gerektirir ve önbelleğe almanın herhangi bir faydasını ortadan kaldırır.
msg45f

Başka bir yol da, SVG'leri arka plan görüntüsü veri urisi olarak her sürümde farklı renklerle kodlamak ve çoğaltmadan dolayı dosya boyutunu küçültmek için gzip'e güvenmektir.
Ruskin

1
Benim durumumda SVG'deki öğe stillerini geçersiz kılmak istedim. CSS'im çalışmadı çünkü öğe stilleri daha yüksek önceliğe sahipti. En basit çözüm, SVG için CSS stiline bir! Sonra her şey yolundaydı. Önemli! 'Den kaçınmak istiyorsanız, öğe stillerini CSS'ye taşımanız gerekir.
David Gausmann

utanç verici bir URL'den bir
svg'nin

1
@clayRay, SVG2 taslağı tamamlandığında bunu bu şekilde yapabilirsiniz w3.org/TR/SVG2/styling.html#LinkElement
RGB

51

İstediğinizi bir (önemli) uyarı ile yapabilirsiniz: sembolünüzdeki yollar harici CSS aracılığıyla bağımsız olarak stilize edilemez - bu yöntemle yalnızca tüm sembolün özelliklerini ayarlayabilirsiniz. Dolayısıyla, sembolünüzde iki yol varsa ve bunların farklı dolgu renklerine sahip olmasını istiyorsanız, bu işe yaramaz, ancak tüm yollarınızın aynı olmasını istiyorsanız, bu çalışmalıdır.

Html dosyanızda şuna benzer bir şey istiyorsunuz:

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

Ve harici SVG dosyasında şuna benzer bir şey istiyorsunuz:

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

Üzerinde sınıfını takas svgdan (sizin html olarak) etiketi fill-rediçin fill-blueve ta-da ... Eğer kırmızı yerine mavi var.

Satır içi CSS öncelikli olacağından, harici CSS'yi belirli yollardaki bazı satır içi CSS'lerle karıştırarak ve eşleştirerek harici CSS ile yolları ayrı ayrı hedefleyebilme sınırlamasını kısmen aşabilirsiniz. Bu yaklaşım, renkli bir arka plana karşı beyaz bir simge gibi bir şey yapıyorsanız işe yarayacaktır, burada arka plan rengini harici CSS aracılığıyla değiştirmek istiyorsanız, ancak simgenin kendisi her zaman beyazdır (veya tam tersi). Yani, önceki ile aynı HTML ve bu svg kodu gibi bir şeyle, size kırmızı bir arka plan ve beyaz bir ön plan yolu elde edeceksiniz:

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

iyi cevap .. bence uyarı gerçekten şöyle olmalı: Tarayıcı Desteği, yine de! iyi referans (caniuse'den daha fazla ayrıntı): css-tricks.com/svg-fragment-identifiers-work
ptim

Bu bir çözüm! Aslında, svg içeriğinin tamamını bir symbolöğeye sarmaya gerek yoktur , yani idsvg öğesine bir verebilirsiniz , yani: "<svg id = example" xmlns = " w3.org/2000/svg " viewBox = "0 0 256256 "> <yol class =" background "d =" M120 ... "/> <yol class =" icon "style =" fill: white; "d =" M20 ... "/> </ svg > `
SimoneMSR

12

Aşağıdakileri kullanarak SVG dosyalarınıza harici css dosyasına bağlantı ekleyebilirsiniz:

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

Bunu açılış etiketinden sonra eklemeniz gerekir:

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

Mükemmel bir çözüm değil, çünkü svg dosyalarını değiştirmeniz gerekiyor, ancak onları bir kez değiştiriyorsunuz ve tüm stil değişiklikleri tüm svg dosyaları için tek bir css dosyasında yapılabilir.


1
Vay canına, bu işe yarıyor, ancak sadece 1 ek oy ... bu çözüm tüm durumlar için iyi mi? Çok basit, neden bu seçilmiş cevap değil?
Bruno Vincent

Bütün mesele stil tanımlarınızı merkezileştirmektir. Diyelim ki stil vermek istediğiniz 10 SVG'niz var. Şimdi CSS'ye bir referansı, etkilenmesi gereken tüm SVG'lere kopyalamanız gerekiyor. CSS'nizin dosya adı / konumu değişirse, onu 10 SVG'de güncellemeniz gerekir. Bir CSS sınıfı, fiziksel bir CSS dosyasına referanstan çok daha sembolik hisseder.
Frans

Olacak <img> etiketi üzerinden yüklenen bu svg Not değil dış içeriği (örneğin, stil) yükleyin.
Moose Ahlak

7

JavaScript'te dinamik olarak bir stil öğesi oluşturup bunu SVG öğesine ekleyerek bir SVG'nin stilini oluşturmak mümkündür. Hacky, ama işe yarıyor.

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

İsterseniz JavaScript'i dinamik olarak PHP'de oluşturabilirsiniz - bunun JavaScript'te mümkün olması sayısız olasılık açar.


hey, gerçekten hoşuma giden çözümü ve işe yarıyor ancak işletim sistemine yardım etmeye istekliysen, kendi durumumda benimsemem gerekiyor, <defs> içinde bir stil etiketim var, bunları manuel olarak silebilir ve bu kodu çalıştırarak oluşturabilirim bir stil, tanımları silip sonra öğeyi sizin yaptığınız gibi yeniden oluşturmamın veya sadece güncellememin bir yolu var mı ve ayrıca url'de bir hata var URL'si tanımlanmadı, lütfen yardım eder misiniz, teşekkür ederim
Kamel Mili,

6

Uygulayabileceğiniz bir yaklaşım, tarayıcıdaki SVG grafiklerinin görünümünü değiştirmek için CSS filtreleri kullanmaktır.

Örneğin, SVG kodunda kırmızı dolgu rengi kullanan bir SVG grafiğiniz varsa, bunu 180 derecelik ton döndürme ayarıyla maviye çevirebilirsiniz:

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

İstediğiniz renkleri bulmak için diğer ton döndürme ayarlarıyla denemeler yapın.

Açık olmak gerekirse, yukarıdaki CSS, HTML belgenize uygulanan CSS'ye gider. SVG kodunun stilini değil, HTML kodundaki img etiketini şekillendiriyorsunuz.

Ve bunun siyah veya beyaz veya gri dolgulu grafiklerde çalışmayacağını unutmayın. O rengin tonunu döndürmek için orada gerçek bir renge sahip olmalısınız.


4

Harici bir css stil sayfasıyla dinamik bir stile sahip olmak için çok hızlı bir çözüm, <object>Svg'nizi yerleştirmek için etiketi .

Bu örnek, köke bir sınıf ekleyecek <svg> , bir ana öğeye tıklandığında etiketine .

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

tıklandığında üst öğe:

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

o zaman css'nizi yönetebilirsiniz

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

işe yaramıyor gibi görünüyor, çalışan bir örnek ekleyebilir misiniz?
Jeanluca Scaljeri

4

Öncelikle harici svg görüntülerini satır içine alarak yapmak mümkün olmalıdır. Aşağıdaki kod, tüm SVG resimlerinin Jess Frazelle tarafından yazılan satır içi SVG ile değiştirilmesinden gelmektedir .

$('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);
  });
});

3
Bunun yalnızca, görüntüyü html ile aynı etki alanında barındırıyorsanız veya görüntü sunucusunda özel olarak yapılandırılmış bir çapraz etki alanı ilkesine sahipseniz işe yarayacağını not etmek önemlidir. $ .get ajax kullanacak ve geçerli bir izin erişim başlığı yoksa görüntüyü harici sunucudan
yükleyemeyecek


2

<image>SVG etiketinde kullanıldığında, gizlilik nedeniyle tek bir dosyada yer almalıdır. Bu bugzilla bug , bunun tam olarak neden böyle olduğuna dair daha fazla ayrıntıya sahiptir. Maalesef, gibi farklı bir etiket kullanamazsınız <iframe>çünkü bu bir bağlantı olarak çalışmaz, bu nedenle CSS'yi bir<style> dosyanın kendi içindeki etikete yerleştirmeniz gerekir.

Bunu yapmanın bir başka yolu da SVG verilerini ana html dosyasında bulundurmaktır.

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

HTML <link>etiketini kullanarak harici bir CSS dosyasıyla bunu biçimlendirebilirsiniz.


2
Stilleri dosyaların içine koyamıyorum. Aslında bu görsellerin renklerini, kullanıcının sitem için seçtiği renk düzenine göre değiştireceğim. Mevcut uygulamam, ana sayfaya varsayılan stillerin üzerine yazan bir stil sayfası eklemektir. Gömülü SVG grafiklerini etkilemek için renk değişikliklerini o dosyaya koymak istedim. Ancak bu işe yaramaz çünkü stil sayfasına SVG dosyası içinden bağlantı vermem gerekiyor (bu bağlantıyı JavaScript kullanan tüm SVG dosyalarına eklemenin bir yolu yoksa). Elbette harici SVG dosyalarına, harici CSS'ye, bağlantılara ve araç ipuçlarına izin vermenin bir yolu vardır.
Jordan H

1
Tarayıcının güvenlik modeli nedeniyle yapmak istediğinizi yapmanız mümkün değildir. Resim olarak kullanıldığında SVG'yi değiştirmek için javascript kullanamazsınız. SVG'yi resim olarak kullanıldığında, animasyonlu bir png veya gif dosyası gibi düşünün, hepsi tek bir dosyada ve komut dosyası erişimi yok.
Robert Longson

1

"Aslında bu resimlerin renklerini, kullanıcının sitem için seçtiği renk düzenine göre değiştireceğim." - Ürdün 10 saat önce

Bunun için PHP kullanmanızı öneririm. Bunu simge yazı tipleri olmadan yapmanın daha iyi bir yolu yoktur ve bunları kullanmaya direnirseniz, şunu deneyebilirsiniz:

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

Ve daha sonra filename.php?color=#ffffffsvg dosyasını istediğiniz renkte elde etmek için bu dosyayı kullanabilirsiniz .


6
Bu kodun kullanıcı girişini kontrol etmediğini unutmayın - herhangi bir şey renkli olarak sağlanabilir ve SVG'niz çok ilginç şekillerde işlenebilir ... Sizi etkileyip etkilemediğinden emin değilsiniz, ancak DAİMA kullanıcı girişini doğrulamayı alışkanlık haline getirmelisiniz . Bunun gibi bir şey yardımcı olabilir: if (!preg_match('/^[#][0-9a-f]{6}$/i', $_GET['color'])) die('Oops!');(bunu başlangıç ​​PHP bloğunda bir yere koyun).
johndodo

1

Benim için ne işe yarar: @import kuralı ile stil etiketi

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

1

Bunun eski bir gönderi olduğunu biliyorum, ancak bu sorunu gidermek için ... sınıflarınızı yanlış yerde kullanıyorsunuz: D

Her şeyden önce kullanabilirsin

svg { fill: red; }

senin main.cssiçinde kırmızı olsun. Bunun bir etkisi var. Belirli yolları elde etmek için muhtemelen düğüm seçicilerini de kullanabilirsiniz.

İkinci şey, sınıfı img-Tag olarak ilan ettin.

<img class='socIcon'....

Aslında bunu SVG'nizin içinde açıklamalısınız. farklı yollarınız varsa, elbette daha fazlasını tanımlayabilirsiniz.

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

Artık rengini main.cssbeğenebilirsin

.myClassForMyPath {
    fill: yellow;
}

Bunu denedim, diğer yanıtların çoğunun söylediği gibi işe yaramıyor. SVG içindeki sınıflara stil uygulayamazsınız.
Frans

@Frans, bir dosya olarak bir svg ekliyor musunuz veya yukarıdaki örnekte olduğu gibi svg kaynağınız var mı? Çünkü bunun svg'yi nasıl kullandığınıza bağlı olduğunu aklımda tutuyorum. İmg tarafından dahil olmak işe yaramaz.
Dwza

Tam olarak, yalnızca SVG'yi HTML'nizde satır içi yaparsanız çalışır. Ama örneğinizin yaptığı bu değil. Harici (yani satır içi olmayan) bir SVG kullanır. HTML'nizde harici bir SVG'yi CSS ile biçimlendirmenin bir yolu yok gibi görünüyor.
Frans

Örneğimi doğru denediğinizden emin misiniz? Demek istediğim, harici bir css dosyası dahil mi? <?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
Dwza

Tamam, şimdi anlıyorum, <?xml-stylesheet ... ?>SVG'nizde bir beyannameniz var . Sanırım bu işe yarayacak. <link rel="stylesheet" ... >SVG içinde bir öneren diğer yanıtlara benzer . Aynı sorunlara da sahiptir (her bir SVG'yi stil sayfasına işaret edecek şekilde güncellemeniz gerekir ve stil sayfasının adında veya konumunda herhangi bir değişiklik, tüm SVG'leri yeniden değiştirmek zorunda olmanız anlamına gelir).
Frans

1
  1. Harici stiller için

<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. İç Stiller için

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

Not: İçine SVG eklerseniz Harici Stiller çalışmayacaktır <img>. <div>Etiket içinde mükemmel çalışacak


0

@leo işte angularJS versiyonu, tekrar teşekkürler

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

                } );

            } );
        }

    }

}

} );

-1

Bu yöntem, svg bir web tarayıcısında görüntülenirse ancak bu kod sunucuya yüklenir yüklenmez ve svg simgesinin sınıfı, bir arka plan görüntüsü gibi kodlanırsa, renk kaybolur ve varsayılan renge geri döner. . Görünüşe göre hem renk için svg sınıfı hem de svg'nin görünümü ve konumu için en üst katman sınıfı aynı dizine eşlenmiş olsa bile, renk harici stil sayfasından değiştirilemez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.