Вопрос по html, css, svg – Встроенный SVG в CSS

213

Можно ли использовать встроенное определение SVG в CSS?

Я имею в виду что-то вроде:

.my-class {
  background-image: <svg>...</svg>;
}
Это само по себе отличная идея. Однако, если кому-то нужно продвигать ваш логотип / продукт / идею и не можете связаться с вами, он сделает снимок экрана вашего SVG и будет использовать его. Я просто сделал это, потому что у меня не было другого выбора ... MicroMachine
Остерегайтесь того, что предлагаемые решения не будут работать для изображений CSS, HTML<img> теги и другие случаи, если SVG представляет собой смесь нескольких изображений (если они не встроены), см.background image SVG with mask using external image not workingи конкретноrestrictions on SVG used as an image. Skippy le Grand Gourou
Что вы пытаетесь сделать, добавьте изображение & quot; источник & quot; к таблице стилей? Zuul

Ваш Ответ

7   ответов
24

в base64 значение для атрибута фона CSS с помощью этой простой команды bash:

echo "background: transparent url('data:image/svg+xml;base64,"$(openssl base64 < path/to/file.svg)"') no-repeat center center;"

Протестировано на Mac OS X. Таким образом, вы также избежите беспорядка URL.

Помните, что кодировка base64 SVG-файла увеличивает его размер, см.css-tricks.com сообщение в блоге.

Читателям: пожалуйста, прокомментируйте свое мнение, а не просто проголосуйте, так что этот ответ может быть улучшен с вашим сотрудничеством! Сотрудничество важно на таких сайтах, как этот. Спасибо!
@LorDex ссылка, которую вы указали в своем комментарии, такая же, как и в моем ответе :)
25

которые все еще борются, мне удалось заставить это работать на всех современных браузерах IE11 и выше.

Base64 не был для меня вариантом, потому что я хотел использовать SASS для генерации SVG-иконок на основе любого заданного цвета. Например:@include svg_icon(heart, #FF0000); Таким образом, я могу создать определенную иконку любого цвета, и мне нужно только внедрить форму SVG в CSS. (с base64 вам нужно будет встраивать SVG в каждый цвет, который вы хотите использовать)

Есть три вещи, о которых вам нужно знать:

URL ENCODE YOUR SVG As others have suggested, you need to URL encode your entire SVG string for it to work in IE11. In my case, I left out the color values in fields such as fill="#00FF00" and stroke="#FF0000" and replaced them with a SASS variable fill="#{$color-rgb}" so these can be replaced with the color I want. You can use any online converter to URL encode the rest of the string. You'll end up with an SVG string like this:

%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D%27512%27%20height%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%2041.012%2010.535%2079.541%2028.973%20113.10,4L3.825%20464.586c345%2012.797%2041.813%2012.797%2015.467%200%2029.872-4.721%2041.813-12.797v158.184z%27%20fill%3D%27#{$color-rgb}%27%2F%3E%3C%2Fsvg%3E

OMIT THE UTF8 CHARSET IN THE DATA URL When creating your data URL, you need to leave out the charset for it to work in IE11.

NOT background-image: url( data:image/svg+xml;utf-8,%3Csvg%2....)
BUT background-image: url( data:image/svg+xml,%3Csvg%2....)

USE RGB() INSTEAD OF HEX colors Firefox does not like # in the SVG code. So you need to replace your color hex values with RGB ones.

NOT fill="#FF0000"
BUT fill="rgb(255,0,0)"

В моем случае я использую SASS для преобразования данного гекса в действительное значение RGB. Как указано в комментариях, лучше всего URL-кодировать и вашу строку RGB (так что запятая становится% 2C)

@mixin svg_icon($id, $color) {
   $color-rgb: "rgb(" + red($color) + "%2C" + green($color) + "%2C" + blue($color) + ")";
   @if $id == heart {
      background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D%27512%27%20height%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%204%27%20fill%3D%27#{$color-rgb}%27%2F%3E%3C%2Fsvg%3E');
   }
}

Я понимаю, что это может быть не лучшим решением для очень сложных SVG (в этом случае встроенного SVG никогда не бывает), но для плоских иконок только с несколькими цветами это действительно прекрасно работает.

Мне удалось опустить весь растровый рисунок спрайта и заменить его встроенным SVG в моем CSS, который после сжатия оказался всего около 25 КБ. Так что это отличный способ ограничить количество запросов, которые должен выполнять ваш сайт, без раздувания вашего CSS-файла.

Кстати, поправьте меня, если я ошибаюсь, ноrgb(255,0,0) должен статьrgb(255%2C0%2C0) однажды закодирован.
Я имел в виду, что я не кодирую строку RGB, и она все еще работает. Но кодирование, как вы упомянули, возможно, лучше.
Ну, на самом деле, я только что проверил и%23ff0000 отлично работает для#ff0000 в Firefox
Это должен быть принятый ответ
@ Капсула Я не знаю, что происходит, но% 23ff0000 - ЕДИНСТВЕННЫЙ метод, который работает для меня как в Chrome, так и в FF. # ff0000 не работает, а также методы RGB (255,0,0) и rgb (255% 2C0% 2C0).
2

исходящий из сторонних источников (таких как диаграммы Google), может не содержать атрибут пространства имен XML (xmlns="http://www.w3.org/2000/svg") в элементе SVG (или, возможно, он удален после визуализации SVG - ни инспектор браузера, ни команды jQuery из консоли браузера не показывают пространство имен в элементе SVG).

Когда вам нужно переопределить эти фрагменты svg для других ваших нужд (background-image в CSS или элемент img в HTML), следите за отсутствующим пространством имен. Без пространства имен браузеры могут отказаться отображать SVG (независимо от кодировки utf8 или base64).

8

в которой возникла та же проблема с встраиванием встроенного SVG в CSS. Решение, которое работает с SCSS, заключается в создании простой функции кодирования URL.

Функция замены строки может быть создана из встроенных функций str-slice, str-index (см.CSS-уловокСпасибо Уго Жирауделю).

Затем просто замените%,<,>,",', с%xxкоды:

@function svg-inline($string){
  $result: str-replace($string, "<svg", "<svg xmlns='http://www.w3.org/2000/svg'");
  $result: str-replace($result, '%', '%25');
  $result: str-replace($result, '"', '%22');
  $result: str-replace($result, "'", '%27');
  $result: str-replace($result, ' ', '%20');
  $result: str-replace($result, '<', '%3C');
  $result: str-replace($result, '>', '%3E');
  @return "data:image/svg+xml;utf8," + $result;
}

$mySVG: svg-inline("<svg>...</svg>");

html {
  height: 100vh;
  background: url($mySVG) 50% no-repeat;
}

Также естьimage-inline вспомогательная функция доступна в Compass, но так как она не поддерживается в CodePen, это решение может быть полезным.

Демо на CodePen:http://codepen.io/terabaud/details/PZdaJo/

Это сработало потрясающе. Спасибо. Одна запись. Вам нужно использовать; charset = utf8, чтобы заставить это работать в IE.
Я также создал ручку, которая позволяет конвертировать строки SVG в правильное значение фона CSS:s.codepen.io/LukyVj/debug/693cbcc30258bf67b8c30047cce060eb  Итак, вы вставляете<svg><path></svg> в верхнюю текстовую область, и он будет напрямую выводить очищенный путь в пределахurl() значение.
188

но если кто-то из вас сходит с ума, пытаясь использоватьinline SVG as a backgroundвышеприведенные предложения не совсем работают. С одной стороны, он не работает в IE, и в зависимости от содержимого вашего SVG метод будет вызывать проблемы в других браузерах, таких как FF.

Если вы base64 кодируете svg (не весь URL, а только тег svg и его содержимое!), Это работает во всех браузерах. Вот тот же пример jsfiddle в base64:http://jsfiddle.net/vPA9z/3/

CSS теперь выглядит так:

body { background-image: 
    url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");

Не забудьте удалить любой URL-адрес перед преобразованием в base64. Другими словами, вышеприведенный пример показал color = 'a #; # fcc' apos; преобразовано в цвет = "% 23fcc", вам нужно вернуться к #.

Причина, по которой base64 работает лучше, состоит в том, что он устраняет все проблемы с одинарными и двойными кавычками и экранированием URL

Если вы используете JS, вы можете использоватьwindow.btoa() для создания вашего base64 SVG; и если он не работает (он может жаловаться на недопустимые символы в строке), вы можете просто использоватьhttps://www.base64encode.org/.

Пример установки фона div:

var mySVG = "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='#F00'/><stop offset='90%' stop-color='#fcc'/> </linearGradient><rect fill='url(#gradient)' x='0' y='0' width='100%' height='100%'/></svg>";
var mySVG64 = window.btoa(mySVG);
document.getElementById('myDiv').style.backgroundImage = "url('data:image/svg+xml;base64," + mySVG64 + "')";
html, body, #myDiv {
  width: 100%;
  height: 100%;
  margin: 0;
}
<div id="myDiv"></div>

С JS вы можете генерировать SVG на лету, даже изменяя его параметры.

Одна из лучших статей об использовании SVG находится здесь:http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

Надеюсь это поможет

Майк

Мне также помогли (после потери времени, пробуя принятый ответ) - это, безусловно, должен быть принятый ответ.
Будет ли это работать как встроенный источник данных?
Я положил ваш пример в коде!codepen.io/anon/pen/fBgsc
Спасибо чувак. Решение с Base64 сработало отлично, а у меня возникли проблемы с принятым ответом.
Вы спасли мою жизнь. У меня было изображение границы SVG, которое работало в Chrome, но не на FF. Теперь это работает! : D
279

body { background-image: 
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url(%23gradient)' x='0' y='0' width='100%' height='100%'/></svg>");
      }
http://jsfiddle.net/6WAtQ/

(Обратите внимание, что контент SVG должен быть экранирован по URL, чтобы это работало, например,# заменяется%23.)

Это работает в IE 9 (который поддерживает SVG), URL-адреса данных также работают в более старых версиях IE (с ограничениями), но изначально не поддерживают SVG.

Правильно ... все же мне не терпится увидеть взгляды моих коллег. лица, когда я показываю им такого милого маленького монстра, как этот, так что еще раз спасибо за то, что показали это возможно. Я просто пошел к стандартной спецификации и заявил, что это практически невозможно, что оказалось ошибкой (вроде)
Единственный браузер, в котором он работает хорошо, это Safari (5.1.4). В Opera 11.62 градиент черный, в IE 9 и Firefox 12 он белый. В Chrome 19 это работает, если вы не укажете ширину / высоту SVG в%. Я бы сказал, что это скорее странность, чем реальная особенность. Это крутая находка.
Есть ли разница в совместимости между SV64 в кодировке SVG и не Base64? Base64 раздувает мой css файл, я думаю просто использовать встроенные svgs ..
& Quot; несовместимость браузера & quot; в основном это просто отсутствие правильного экранирования URL, все внутриurl() должен быть экранирован. Увидетьjsfiddle.net/6WAtQ для примера, который прекрасно работает в Opera, Firefox и Safari.
Обратите внимание, что стандартным способом указания набора символов является & quot ;; charset = UTF-8 & quot; вместо & quot ;; utf8 & quot ;.tools.ietf.org/html/rfc2397
2

я просто хочу поделиться с вами своим обходным путем. В моем примере показано, как использовать элемент SVG из DOM в качестве фона через фильтр (background-image: url ("глиф" не работает).

Функции, необходимые для визуализации иконки SVG:

Applying SVG filter effects to HTML elements using CSS (IE and Edge not supports) feImage fragment load supporting (firefox not supports)

.test {
  /*  background-image: url('#glyph');
    background-size:100% 100%;*/
    filter: url(#image); 
    height:100px;
    width:100px;
}
.test:before {
   display:block;
   content:'';
   color:transparent;
}
.test2{
  width:100px;
  height:100px;
}
.test2:before {
   display:block;
   content:'';
   color:transparent;
   filter: url(#image); 
   height:100px;
   width:100px;
}
<svg style="height:0;width:0;" version="1.1" viewbox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
     <g id="glyph">
          <path id="heart" d="M100 34.976c0 8.434-3.635 16.019-9.423 21.274h0.048l-31.25 31.25c-3.125 3.125-6.25 6.25-9.375 6.25s-6.25-3.125-9.375-6.25l-31.202-31.25c-5.788-5.255-9.423-12.84-9.423-21.274 0-15.865 12.861-28.726 28.726-28.726 8.434 0 16.019 3.635 21.274 9.423 5.255-5.788 12.84-9.423 21.274-9.423 15.865 0 28.726 12.861 28.726 28.726z" fill="crimson"/>
     </g>
    <svg id="resized-glyph"  x="0%" y="0%" width="24" height="24" viewBox="0 0 100 100" class="icon shape-codepen">
      <use xlink:href="#glyph"></use>
    </svg>
     <filter id="image">
       <feImage xlink:href="#resized-glyph" x="0%" y="0%" width="100%" height="100%" result="res"/>
       <feComposite operator="over" in="res" in2="SourceGraphic"/>
    </filter>
 </defs>
</svg>
<div class="test">
</div>
<div class="test2">
</div>

Еще одно решение, это использовать url encode

var container = document.querySelector(".container");
var svg = document.querySelector("svg");
var svgText = (new XMLSerializer()).serializeToString(svg);
container.style.backgroundImage = `url(data:image/svg+xml;utf8,${encodeURIComponent(svgText)})`;
.container{
  height:50px;
  width:250px;
  display:block;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: contain;
}
<svg  height="100" width="500" xmlns="http://www.w3.org/2000/svg">
    <ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" />
</svg>
<div class="container"></div>

Похожие вопросы