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.