CSS의 인라인 SVG


284

CSS에서 인라인 SVG 정의를 사용할 수 있습니까?

나는 다음과 같은 것을 의미한다 :

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

1
무엇을하려고합니까? 이미지 "source"를 스타일 시트에 추가 하시겠습니까?
Zuul

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

이것은 SVG를 지원하는 IE 9에서 작동합니다 . 데이터 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()해야합니다. Opera, Firefox 및 Safari에서 잘 작동하는 예제는 jsfiddle.net/6WAtQ 를 참조하십시오 .
Erik Dahlström

3
base64로 인코딩 된 svg와 non-base64 사이의 호환성 차이가 있습니까? Base64가 내 CSS 파일을 부풀려서, 그냥 인라인 svgs를 사용하려고 생각합니다.
enapupe

4
문자 집합을 지정하는 표준 방법은 "; utf8"대신 "; charset = UTF-8"을 사용하는 것입니다. tools.ietf.org/html/rfc2397
Keith Shaw

240

조금 늦었지만 인라인 SVG를 배경으로 사용하려고 미쳤다면 위의 탈출 제안이 제대로 작동하지 않습니다. 하나는 IE에서 작동하지 않으며 SVG의 내용에 따라이 기술은 FF와 같은 다른 브라우저에서 문제를 일으킬 수 있습니다.

svg (전체 URL이 아니라 svg 태그와 내용 만!)를 base64로 인코딩하면 모든 브라우저에서 작동합니다. 다음은 base64의 동일한 jsfiddle 예제입니다. http://jsfiddle.net/vPA9z/3/

CSS는 이제 다음과 같습니다 :

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

base64로 변환하기 전에 URL 이스케이프를 제거해야합니다. 즉, 위의 예에서는 color = '# fcc'를 color = '% 23fcc'로 변환 한 것으로 표시되었으므로 #으로 돌아 가야합니다.

base64가 더 잘 작동하는 이유는 작은 따옴표와 큰 따옴표 및 URL 이스케이프와 관련된 모든 문제를 제거하기 때문입니다.

JS를 사용 window.btoa()하는 경우 base64 svg를 생성 하는 데 사용할 수 있습니다 . 작동하지 않으면 (문자열에서 유효하지 않은 문자에 대해 불평 할 수 있음) https://www.base64encode.org/ 를 사용하면됩니다 .

사업부 배경을 설정하는 예 :

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의 솔루션은 훌륭하게 작동했지만 승인 된 답변에 문제가 발생했습니다.
Marcel

1
당신은 내 생명을 구했습니다. 크롬에서는 작동하지만 FF에서는 작동하지 않는 SVG 테두리 이미지가 있습니다. 이제 작동합니다! : D
Papipo

(응답을 시도하는 시간을 잃어버린 후) 나에게도 도움이되었습니다.
Katai

이 여전히 당신을 위해 작동하지 않는 경우 - 당신이 있는지 확인 xmlns하는 속성 세트 svg요소를 하기 전에 같은 base64로 인코딩 당신 <svg xmlns="http://www.w3.org/2000/svg">...</svg>이 :하지의 경우 - SVG는 HTML에 바로 때없이 때때로 브라우저 덩어리를
jave.web

누군가 6 년 후에도 여전히이 답변을보고있는 경우 : 아마도 base64 SVGs css-tricks.com/probably-dont-base64-svg
Volker E.

38

여전히 어려움을 겪고있는 사람들을 위해 모든 최신 브라우저 IE11 이상 에서이 작업을 수행 할 수있었습니다.

base64는 SASS를 사용하여 주어진 색상을 기반으로 SVG 아이콘을 생성하기를 원했기 때문에 선택의 여지가 없었습니다. 예를 들어 : @include svg_icon(heart, #FF0000);이렇게하면 어떤 색상 으로든 특정 아이콘을 만들 수 있으며 CSS에 SVG 모양을 한 번만 포함하면됩니다. (base64를 사용하려면 사용하려는 모든 단일 색상으로 SVG를 포함해야합니다)

알아야 할 세 가지가 있습니다.

  1. SVG URL 인코딩 다른 사람들이 제안했듯이 IE11에서 작동하려면 전체 SVG 문자열을 URL 인코딩해야합니다. 필자의 경우는 다음과 같은 분야의 색상 값을 왼쪽 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 % 20fill % 3D % 27 # {$ color-rgb} % 27 % 2F % 3E % 3C % 2Fsvg % 3E


  1. 데이터 URL에서 UTF8 문자 세트 생략 데이터 URL을 작성할 때 IE11에서 작동하려면 문자 세트를 생략해야합니다.

    NOT background-image : url (data : image / svg + xml; utf-8, % 3Csvg % 2 ....)
    그러나 배경 이미지 : url (data : image / svg + xml, % 3Csvg % 2 ... .)


  1. RGB () INSTEAD OF HEX 색상 사용 Firefox는 SVG 코드에서 #을 좋아하지 않습니다. 따라서 색상 16 진수 값을 RGB 값으로 바꿔야합니다.

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

필자의 경우 SASS를 사용하여 주어진 16 진수를 유효한 rgb 값으로 변환합니다. 주석에서 지적했듯이 RGB 문자열도 URL 인코딩하는 것이 가장 좋습니다 (따라서 쉼표는 % 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는 결코 그런 경우)에 대한 최상의 솔루션이 아닐 수도 있지만 몇 가지 색상의 평면 아이콘의 경우 실제로 훌륭하게 작동합니다.

전체 스프라이트 비트 맵을 제외하고 CSS에서 인라인 SVG로 대체 할 수 있었으며 압축 후 약 25kb로 나타났습니다. 따라서 CSS 파일을 부 풀리지 않고 사이트에서 수행해야 할 요청의 양을 제한하는 좋은 방법입니다.


1
내가 틀렸다하지만 경우, BTW 날 수정 rgb(255,0,0)이되어야 rgb(255%2C0%2C0)인코딩하면.
Capsule

1
RGB 문자열을 인코딩하지 않고 여전히 작동한다는 것을 의미했습니다. 그러나 언급 한대로 인코딩하는 것이 좋습니다.
Davy Baert

1
글쎄, 실제로 방금 파이어 폭스에서 테스트를 거쳐 %23ff0000#ff0000
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에서는이 간단한 bash 명령을 사용하여 SVG 파일을 CSS 배경 속성의 base64로 인코딩 된 값으로 쉽게 변환 할 수 있습니다.

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

Mac OS X에서 테스트되었습니다.이 방법으로 URL 이스케이프 혼란을 피할 수 있습니다.

SVG 파일을 인코딩하는 SVG 파일은 크기가 커짐을 기억하십시오. css-tricks.com 블로그 게시물을 참조하십시오 .


2
독자들에게 : 투표 만하지 말고 의견을 말 해주세요.이 답변은 당신의 협력으로 향상 될 수 있습니다! 이와 같은 Q & A 사이트에서는 협업이 필수적입니다. 감사합니다!
araks

2
@LorDex 귀하의 의견에 제공 한 링크는 내 답변과 동일합니다 :)
araks

10

인라인 SVG를 CSS에 포함시키는 것과 동일한 문제가있는 CodePen 데모를 포크했습니다. SCSS와 함께 작동하는 솔루션은 간단한 URL 인코딩 기능을 구축하는 것입니다.

내장 된 str-slice, str-index 함수에서 문자열 대체 기능을 작성할 수 있습니다 ( Hugo Giraudel 덕분에 css-tricks 참조 ).

그런 다음, 바로 교체 %, <, >, ", ', 으로 %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-inlineCompass 에는 도우미 기능 도 있지만 CodePen에서는 지원되지 않으므로이 솔루션이 유용 할 수 있습니다.

CodePen 데모 : http://codepen.io/terabaud/details/PZdaJo/


1
나는 또한 당신이 적절한 CSS를 배경 값으로 SVG 문자열을 변환 할 수있는 펜을 만든 : s.codepen.io/LukyVj/debug/693cbcc30258bf67b8c30047cce060eb 그래서를, 기본적으로, 당신은 당신을 붙여 <svg><path></svg>상단의 텍스트 영역으로하고, 직접 출력 경로를 소독합니다 url()값 내에서 .
LukyVj

1
이것은 대단했다. 감사합니다. 하나의 메모. IE에서 작동하게하려면; charset = utf8을 사용해야합니다.
Daniel Lefebvre

4

Google 차트와 같은 타사 소스에서 제공되는 인라인 SVG에는 XML 네임 스페이스 속성 (xmlns="http://www.w3.org/2000/svg" 는 SVG 요소에 )을 (또는 SVG가 렌더링되면 제거 될 수 있습니다. 브라우저 콘솔의 브라우저 관리자 나 jQuery 명령은 SVG 요소에 네임 스페이스를 표시하지 않습니다).

다른 요구 사항 (CSS의 배경 이미지 또는 HTML의 img 요소)을 위해 이러한 svg 스 니펫을 재사용 해야하는 경우 누락 된 네임 스페이스를 조심하십시오. 네임 스페이스가 없으면 브라우저는 인코딩 utf8 또는 base64에 관계없이 SVG 표시를 거부 할 수 있습니다.


4

SVG에 대한 하나의 솔루션을 찾았습니다. 그러나 그것은 Webkit에서만 작동하며, 해결 방법을 당신과 공유하고 싶습니다. 내 예제에서는 DOM을 통해 SVG 요소를 필터를 통해 배경으로 사용하는 방법을 보여줍니다 (background-image : url ( '# glyph')가 작동하지 않음).

이 SVG 아이콘 렌더링에 필요한 기능 :

  1. CSS를 사용하여 HTML 요소에 SVG 필터 효과 적용 (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>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.