Robert B.: SVG-Sprites in CSS

Hallo Forum,

nachdem ich die Tage immer mal wieder von SVG-Sprites gelesen habe, wollte ich mich auch ans Werk machen und das mal ausprobieren. Ich binde zur Zeit SVG-Icons als separate Dateien per CSS-generiertem Content bzw. Hintergrundgrafik ein. Wenn ich Artikel wie diesen richtig verstehe, kann ich SVG auch direkt in CSS einbauen. Meine naive Heransgehensweise funktioniert allerdings im Firefox 42 unter Ubuntu nicht:

<!doctype html>
<html>
<head>
<title>Icon Sprite</title>
<meta charset="utf-8"/>
<style type="text/css">
li {
        list-style-type: none;
        list-style-image: url(icon.png);    /* Hier sollte eigentlich die SVG hin. */
        padding-right: 32px;
        border: 1px solid black;
        /* Hier würde das Hintergrundbild angezeigt:
        background-image: url(icon.png);
        */
        background-image: url('data:image/svg+xml;<?xml version="1.0" encoding="utf-8"?><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect x="0" y="0" width="32" height="32" style="fill:none;stroke:black"/><rect x="2" y="2" width="28" height="28" style="fill:none;stroke:#333333"/><rect x="4" y="4" width="24" height="24" style="fill:none;stroke:#666666"/><rect x="6" y="6" width="20" height="20" style="fill:none;stroke:#999999"/><rect x="8" y="8" width="16" height="16" style="fill:none;stroke:#cccccc"/><rect x="10" y="10" width="12" height="12" style="fill:none;stroke:white"/></svg>');
}
</style>
</head>
<body>
<h1>Icon Sprite</h1>
<p>Jedes Element dieser Liste ist mit einer eigenen „Bullet“ versehen:</p>
<ul>
<li>Also, erstens</li>
<li>… außerdem …</li>
<li>… und schließlich!</li>
</ul>
</body></html>

Deshalb vermute ich, dass mit dem data-URI etwas nicht stimmt. Wo ist mein Denkfehler? Weiterhin müsste ja dem SVG-Element use auch eigentlich ein Verweis „nach draußen“ auf eine externe SVG möglich sein, oder nicht?

Viele Grüße Robert

  1. Lieber Robert,

    1. Der data-URI benötigt eine Enkodierungsangabe (z.B. "base64" oder "US-ASCII"), gefolgt von einem Komma, nach dem die tatsächlichen Daten stehen.

    2. Ein URI benötigt maskierte Sonderzeichen. Wenn da "<?xml" steht, dann hat das Sonderzeichen eine besondere Bedeutung! Du möchtest also den kompletten SVG-Code durch eine Funktion jagen, wie PHPs rawdataurlencode oder JavaScripts encodeURIComponent.

    li {
            list-style-type: none;
            list-style-image: url(icon.png);    /* Hier sollte eigentlich die SVG hin. */
            padding-right: 32px;
            border: 1px solid black;
            /* Hier würde das Hintergrundbild angezeigt:
            background-image: url(icon.png);
            */
    
            background-image: url("data:image/svg+xml;US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2232%22%20height%3D%2232%22%20viewBox%3D%220%200%2032%2032%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2232%22%20height%3D%2232%22%20style%3D%22fill%3Anone%3Bstroke%3Ablack%22%2F%3E%3Crect%20x%3D%222%22%20y%3D%222%22%20width%3D%2228%22%20height%3D%2228%22%20style%3D%22fill%3Anone%3Bstroke%3A%23333333%22%2F%3E%3Crect%20x%3D%224%22%20y%3D%224%22%20width%3D%2224%22%20height%3D%2224%22%20style%3D%22fill%3Anone%3Bstroke%3A%23666666%22%2F%3E%3Crect%20x%3D%226%22%20y%3D%226%22%20width%3D%2220%22%20height%3D%2220%22%20style%3D%22fill%3Anone%3Bstroke%3A%23999999%22%2F%3E%3Crect%20x%3D%228%22%20y%3D%228%22%20width%3D%2216%22%20height%3D%2216%22%20style%3D%22fill%3Anone%3Bstroke%3A%23cccccc%22%2F%3E%3Crect%20x%3D%2210%22%20y%3D%2210%22%20width%3D%2212%22%20height%3D%2212%22%20style%3D%22fill%3Anone%3Bstroke%3Awhite%22%2F%3E%3C%2Fsvg%3E");
    
    }
    

    Deshalb vermute ich, dass mit dem data-URI etwas nicht stimmt.

    Richtig. Klappt's mit meiner Version?

    Liebe Grüße,

    Felix Riesterer.

    1. @@Felix Riesterer

      1. Der data-URI benötigt eine Enkodierungsangabe (z.B. "base64" oder "US-ASCII"), gefolgt von einem Komma, nach dem die tatsächlichen Daten stehen.

      Nein. [RFC 2397]

      1. Ein URI benötigt maskierte Sonderzeichen. Wenn da "<?xml" steht, dann hat das Sonderzeichen eine besondere Bedeutung! Du möchtest also den kompletten SVG-Code durch eine Funktion jagen, wie PHPs rawdataurlencode oder JavaScripts encodeURIComponent.

      RFC 2397 verlangt das wohl so. Besser gesagt RFC 2396, worin uric definiert wird (misbilligt in RFC 3986, aber das führt jetzt zu weit).

      Für IE ist das wohl notwendig, wie auch Sara sagte (die andere Sara). Firefox und WebKits kommen auch mit nicht escapeten < und > klar.

      Für Firefox muss allerdings # escapet werden, weil # einen fragment identifier einleitet. WebKits kommen auch mit nicht escapeten # klar.

      LLAP 🖖

      --
      „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
      „Hat auf dem Forum herumgelungert …“
      (Wachen in Asterix 36: Der Papyrus des Cäsar)
      1. @@Gunnar Bittersmann

        1. Der data-URI benötigt eine Enkodierungsangabe (z.B. "base64" oder "US-ASCII"), gefolgt von einem Komma, nach dem die tatsächlichen Daten stehen.

        Bin gerade wieder auf diesen Artikel gestoßen und meinen Kommentar dazu.

        Für IE ist das wohl notwendig, wie auch Sara sagte (die andere Sara). Firefox und WebKits kommen auch mit nicht escapeten < und > klar.

        Für Firefox muss allerdings # escapet werden, weil # einen fragment identifier einleitet. WebKits kommen auch mit nicht escapeten # klar.

        Huch, auch das alles wurde dort gesagt.

        Hätte ich mich dran erinnern sollen und mir die Blamage ersparen können. ;-)

        LLAP 🖖

        --
        „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
        „Hat auf dem Forum herumgelungert …“
        (Wachen in Asterix 36: Der Papyrus des Cäsar)
      2. @@Gunnar Bittersmann

        Für IE ist das wohl notwendig, wie auch Sara sagte (die andere Sara). Firefox und WebKits kommen auch mit nicht escapeten < und > klar.

        Der Vollständigkeit halber: Neben < und > müssen auch " und ' prozent-escapet werden.

        Ich hab den Pen ergänzt.

        LLAP 🖖

        --
        „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
        „Hat auf dem Forum herumgelungert …“
        (Wachen in Asterix 36: Der Papyrus des Cäsar)
        1. Hi,

          Für IE ist das wohl notwendig, wie auch Sara sagte (die andere Sara). Firefox und WebKits kommen auch mit nicht escapeten < und > klar.

          Der Vollständigkeit halber: Neben < und > müssen auch " und ' prozent-escapet werden.

          Wie ist es mit dem Fragezeichen? Das erste Fragezeichen in einer URL leitet ja den Query-String ein. Spielt das hier auch eine Rolle? Oder haben Data-URLs per Definition keinen Query-String?

          cu,
          Andreas a/k/a MudGuard

          1. Moin,

            Der Vollständigkeit halber: Neben < und > müssen auch " und ' prozent-escapet werden.

            Wie ist es mit dem Fragezeichen? Das erste Fragezeichen in einer URL leitet ja den Query-String ein. Spielt das hier auch eine Rolle? Oder haben Data-URLs per Definition keinen Query-String?

            gute Frage, aber ich habe mir jetzt ein kleines Tool geschrieben, das korrekt URL-En- und -Dekodiert:

            <form>
            <fieldset><legend>Data</legend>
            	<textarea id="txt" rows="10" cols="80"></textarea>
            </fieldset>
            <fieldset><legend>URL</legend>
            	<button type="button" onclick="code(this.form.txt, encodeURIComponent)">Enkodieren</button>
            	<button type="button" onclick="code(this.form.txt, decodeURIComponent)">Dekodieren</button>
            </fieldset>
            </form>
            

            mit der zugehörigen simplen Funktion

            function code(elem, how) {
            	elem.value = how(elem.value);
            }
            

            Viel Spaß Robert

    2. Hallo Felix,

      1. Der data-URI benötigt eine Enkodierungsangabe (z.B. "base64" oder "US-ASCII"), gefolgt von einem Komma, nach dem die tatsächlichen Daten stehen.

      Das ist interessant. Die Beispiele im Internet haben dies nicht, aber ohne funktioniert es zumindest bei mir lokal nicht.

      1. Ein URI benötigt maskierte Sonderzeichen. Wenn da "<?xml" steht, dann hat das Sonderzeichen eine besondere Bedeutung! Du möchtest also den kompletten SVG-Code durch eine Funktion jagen, wie PHPs rawdataurlencode oder JavaScripts encodeURIComponent.

      Darauf hätte ich auch selbst können können/müssen, schließlich heißt das Kontrukt darum ja auch schon url ;-)

              background-image: url("data:image/svg+xml;US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2232%22%20height%3D%2232%22%20viewBox%3D%220%200%2032%2032%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2232%22%20height%3D%2232%22%20style%3D%22fill%3Anone%3Bstroke%3Ablack%22%2F%3E%3Crect%20x%3D%222%22%20y%3D%222%22%20width%3D%2228%22%20height%3D%2228%22%20style%3D%22fill%3Anone%3Bstroke%3A%23333333%22%2F%3E%3Crect%20x%3D%224%22%20y%3D%224%22%20width%3D%2224%22%20height%3D%2224%22%20style%3D%22fill%3Anone%3Bstroke%3A%23666666%22%2F%3E%3Crect%20x%3D%226%22%20y%3D%226%22%20width%3D%2220%22%20height%3D%2220%22%20style%3D%22fill%3Anone%3Bstroke%3A%23999999%22%2F%3E%3Crect%20x%3D%228%22%20y%3D%228%22%20width%3D%2216%22%20height%3D%2216%22%20style%3D%22fill%3Anone%3Bstroke%3A%23cccccc%22%2F%3E%3Crect%20x%3D%2210%22%20y%3D%2210%22%20width%3D%2212%22%20height%3D%2212%22%20style%3D%22fill%3Anone%3Bstroke%3Awhite%22%2F%3E%3C%2Fsvg%3E");
      

      Klappt's mit meiner Version?

      Dem ist in der Tat so, besten Dank!

      Als nächstes muss ich jetzt mal ausprobieren, ob auch das SVG-Element use in CSS funktioniert. Damit könnte ich dann ja auf ein symbol „Sprite“ zugreifen und hätte nur noch eine SVG-Datei, die geladen werden muss.

      Viele Grüße Robert

      1. Moin,

        Als nächstes muss ich jetzt mal ausprobieren, ob auch das SVG-Element use in CSS funktioniert. Damit könnte ich dann ja auf ein symbol „Sprite“ zugreifen und hätte nur noch eine SVG-Datei, die geladen werden muss.

        Zumindest im Firefox kann ich scheinbar kein use-Element innerhalb der url-Klausel von CSS verwenden. Schade.

        Viele Grüße Robert

        1. @@Robert B.

          Als nächstes muss ich jetzt mal ausprobieren, ob auch das SVG-Element use in CSS funktioniert. Damit könnte ich dann ja auf ein symbol „Sprite“ zugreifen und hätte nur noch eine SVG-Datei, die geladen werden muss.

          Zumindest im Firefox kann ich scheinbar kein use-Element innerhalb der url-Klausel von CSS verwenden. Schade.

          Warum willst du SVG auch unbedingt über CSS als Hintergrundbild einbinden? Üblicherweise gehören Icons zum Inhalt, also SVG ins HTML. Dann klappt das auch mit dem Nachb use.

          LLAP 🖖

          --
          „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
          „Hat auf dem Forum herumgelungert …“
          (Wachen in Asterix 36: Der Papyrus des Cäsar)
          1. Moin Gunnar,

            Warum willst du SVG auch unbedingt über CSS als Hintergrundbild einbinden? Üblicherweise gehören Icons zum Inhalt, also SVG ins HTML. Dann klappt das auch mit dem Nachb use.

            Es war eine fixe Idee um Requests zu sparen: Ich packe alle oft benutzten Vektorgrafiken als symbol in eine SVG und kann die dann entweder direkt in HTML mittels svg/use (Icons, Banner, o.ä.) oder in CSS (Link-Icons per generiertem Inhalt, Hintergrundbilder, …) einbinden.

            Viele Grüße Robert

            1. @@Robert B.

              Warum willst du SVG auch unbedingt über CSS als Hintergrundbild einbinden? Üblicherweise gehören Icons zum Inhalt, also SVG ins HTML. Dann klappt das auch mit dem Nachb use.

              Es war eine fixe Idee um Requests zu sparen: Ich packe alle oft benutzten Vektorgrafiken als symbol in eine SVG

              Ja, schon klar. Ist ja auch gut so.

              und kann die dann entweder direkt in HTML mittels svg/use (Icons, Banner, o.ä.)

              Eben.

              oder in CSS (Link-Icons per generiertem Inhalt, Hintergrundbilder, …) einbinden.

              Warum das denn?

              LLAP 🖖

              --
              „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
              „Hat auf dem Forum herumgelungert …“
              (Wachen in Asterix 36: Der Papyrus des Cäsar)