Вбудований SVG в CSS


284

Чи можливо використовувати вбудоване визначення SVG у CSS?

Я маю на увазі щось на кшталт:

.my-class {
  background-image: <svg>...</svg>;
}

1
Що ви намагаєтеся зробити, додати зображення "джерело" до таблиці стилів?
Зуул

1
Остерігайтеся , що пропоновані рішення не буде працювати на CSS зображення, HTML - <img>теги і інші випадки , якщо SVG являє собою суміш з декількох зображень (якщо не вбудовано), см SVG фонового зображення з маскою , використовуючи зовнішній чином не працює , і в зокрема обмеження на SVG використовується як зображення .
Skippy le Grand Gourou

Відповіді:


376

Так, можливо. Спробуйте це:

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

(Зауважте, що вміст SVG потрібно не використовувати URL, щоб це працювало, наприклад, #його замінювали %23.)

Це працює в IE 9 (який підтримує SVG) . URL-адреси даних також працюють у старих версіях IE (з обмеженнями), але вони не підтримують SVG.


8
Єдиний браузер, в якому, здається, працює добре, це Safari (5.1.4). В Opera 11.62 градієнт чорний, у IE 9 та Firefox 12 - білий. У Chrome 19 він працює НЕ БЕЗПЛАТНО ви вказуєте ширину / висоту SVG у% одиниць. Я б сказав, що це більше дива, ніж реальна особливість. Хоча це крута знахідка.
toniedzwiedz

4
Так ... все ж мені дуже хочеться побачити обличчя моїх колег, коли я показую їм таке миле маленьке чудовисько, тому ще раз дякую за те, що показав, що це можливо. Я просто перейшов до стандартної специфікації і заявив, що це практично неможливо, що виявилося помилкою (свого роду)
toniedzwiedz

18
Тут "несумісність із браузером" - це здебільшого лише відсутність належної URL-адреси, а все, що знаходиться всередині, url()має бути закрито URL-адресою. Див. Jsfiddle.net/6WAtQ для прикладу, який добре працює в Opera, Firefox та Safari.
Ерік Дальстрем

3
Чи є різниця сумісності між кодованим svg, кодованим base64, до non-base64? Base64 роздуває мій файл css, я думаю, що я просто використовую inline svgs ..
enapupe

4
Зауважте, стандартним способом визначення набору символів є "; charset = UTF-8" замість "; utf8". tools.ietf.org/html/rfc2397
Кіт Шоу

240

Трохи пізно, але якщо хтось із вас зійшов з розуму, намагаючись використати вбудований SVG як фон , подані вище пропозиції не дуже працюють. Для одного він не працює в 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 = '# fcc', перетворений у color = '% 23fcc', вам слід повернутися до #.

Причина, чому base64 працює краще, полягає в тому, що вона усуває всі проблеми за допомогою одинарних та подвійних лапок та усунення URL-адрес

Якщо ви використовуєте JS, ви можете використовувати window.btoa()для створення базового64 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/

Сподіваюсь, це допомагає

Майк


2
Спасибі, чоловіче. Рішення з Base64 спрацювало чудово, тоді як у мене виникли проблеми з прийнятою відповіддю.
Марсель

1
Ти врятував мені життя. У мене було зображення межі SVG, яке працювало в хромі, але не на FF. Тепер це працює! : D
Папіпо

Допомагав і мені (після втрати часу на випробування прийнятої відповіді) - це безумовно має бути прийнятою відповіддю.
Катаї

Якщо це все ще не працює для вас - переконайтеся, що ви встановили xmlnsатрибут для svgелемента перед тим, як базувати6464-кодування, як <svg xmlns="http://www.w3.org/2000/svg">...</svg>браузери, іноді збивають його без нього, коли svg знаходиться безпосередньо в HTML - це НЕ так:
jave.web

Якщо хтось все ще дивиться на цю відповідь через 6 років: Ви, мабуть, не повинні базувати64 SVGs css-tricks.com/probably-dont-base64-svg
Volker E.

38

Людям, які все ще борються, мені вдалося налагодити роботу над усіма сучасними браузерами IE11 і вище.

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

Про це потрібно пам’ятати три речі:

  1. URL ЗАКОНУЙТЕ СВІЙ SVG Як запропонували інші, вам потрібно кодувати URL-адресу всієї стрічки SVG, щоб вона працювала в IE11. У моєму випадку я залишив значення кольорів у таких полях, як fill="#00FF00"та stroke="#FF0000"і замінив їх змінною SASS, fill="#{$color-rgb}"щоб вони могли бути замінені потрібним кольором. Ви можете використовувати будь-який онлайн-конвертер для URL-кодування решти рядка. Ви закінчите такий рядок SVG:

    % 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.104L3.825 % 20464.586c345% 2012.797% 2041.813% 2012.797% 2015.467% 200% 2029.872-4.721% 2041.813-12.797v158.184z% 27% 20заповнення% 3D% 27 # {$ color-rgb} % 27% 2F% 3E% 3C% 2Fsvg% 3Е


  1. ОМІТУЙТЕ ЧАСУ UTF8 В URL-адресі ДАНИХ Під час створення URL-адреси даних потрібно залишити шаблони для роботи в IE11.

    НЕ background-image: url (дані: image / svg + xml; utf-8,% 3Csvg% 2 ....)
    АЛЕ фонове зображення: url (дані: image / svg + xml,% 3Csvg% 2 ... .)


  1. ВИКОРИСТОВУЙТЕ RGB () ВСТАНОВИТИ HEX кольорів Firefox не любить # у SVG-коді. Тому вам потрібно замінити свої значення шестигранних кольорів на RGB.

    NOT fill = "# FF0000",
    але 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-файл.


1
До речі, виправте мене, якщо я помиляюся, але колись rgb(255,0,0)слід стати rgb(255%2C0%2C0)кодованим.
Капсула

1
Я мав на увазі, що не кодую рядок RGB, і він все ще працює. Але, мабуть, краще кодувати його, як ви згадали.
Дейві Баерт

1
Ну, насправді, я щойно перевірив і %23ff0000добре працює #ff0000в Firefox
Capsule

1
@Capsule Я не знаю, що відбувається, але% 23ff0000 - це єдиний метод, який працює для мене як на Chrome, так і на FF. # ff0000 не працює, а також методи RGB (255,0,0) та rgb (255% 2C0% 2C0).
Ідеограма

1
Метод (включаючи код SCSS), який вимагає меншої кодування: codepen.io/jakob-e/pen/doMoML
Sphinxxx

26

У Mac / Linux ви можете легко перетворити файл SVG в кодоване значення base64 для атрибута CSS background за допомогою цієї простої команди 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 .


2
Читачам: будь ласка, коментуйте свою думку замість того, щоб просто проголосувати, щоб цю відповідь можна було покращити у співпраці! Співпраця є важливою на таких питаннях як питання. Дякую!
аракс

2
@LorDex посилання, яке ви вказали у своєму коментарі, таке саме, як у моїй відповіді :)
araks

10

Я розпрощав демонстрацію CodePen, яка мала ту ж проблему із вбудовою вбудованого SVG в CSS. Рішенням, що працює з SCSS, є побудова простої функції кодування URL-адреси.

Функція заміни рядків може бути створена із вбудованої str-slice, str-index-функції (див. Css-трюки , завдяки Hugo Giraudel).

Тоді, просто замінити %, <, >, ", ', з %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/


1
Я також створив перо, яке дозволяє перетворити SVG-рядки у відповідне фонове значення css: s.codepen.io/LukyVj/debug/693cbcc30258bf67b8c30047cce060eb Отже, в основному ви вставляєте свій текст <svg><path></svg>у верхню текстову область, і це безпосередньо виводить санітований шлях в межах url()значення.
LukyVj

1
Це спрацювало приголомшливо. Дякую. Одна примітка. Вам потрібно використовувати; charset = utf8, щоб це працювало в IE.
Даніель Лефевр

4

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

Коли вам потрібно призначити ці фрагменти svg для інших потреб (фонове зображення у CSS або елемент img у HTML), слідкуйте за відсутнім простором імен. Без простору імен браузери можуть відмовити у відображенні SVG (незалежно від кодування utf8 або base64).


4

Я знайшов одне рішення для SVG. Але це робота лише для Webkit, я просто хочу поділитися своїм вирішенням з вами. У моєму прикладі показано, як використовувати SVG-елемент з DOM як фон через фільтр (background-image: url ('# glyph') не працює).

Функції, необхідні для цього відображення значка SVG:

  1. Застосування ефектів SVG-фільтра до елементів HTML за допомогою CSS (IE та Edge не підтримує)
  2. Підтримка завантаження фрагмента feImage (Firefox не підтримує)

.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

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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.