programing

CSS의 인라인 SVG

minimums 2023. 8. 1. 20:23
반응형

CSS의 인라인 SVG

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

내 말은 다음과 같은 것을 의미합니다.

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

네, 가능합니다.사용해 보십시오.

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

를 들어, 의 URL과 #는 로대됨으로 됩니다.%23.)

는 SVG를 지원하는 IE 9에서 작동합니다.데이터 URL은 이전 버전의 IE에서도 작동하지만(제한이 있음) SVG는 기본적으로 지원하지 않습니다.

만약 여러분 중에 인라인 SVG를 배경으로 사용하려고 미친 사람이 있다면, 위의 탈출 제안은 제대로 작동하지 않습니다.하나는 IE에서 작동하지 않으며 SVG의 내용에 따라 FF와 같은 다른 브라우저에서 문제가 발생합니다.

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

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

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

base64로 변환하기 전에 URL 이스케이프를 제거해야 합니다.즉, 위의 예에서 color='#color'가 color='%23'로 변환된 것으로 나타났으므로 #로 돌아가야 합니다.

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/ 입니다.

제 해결책은 https://yoksel.github.io/url-encoder/ 이었습니다. 당신은 그저 당신의 svg를 넣고 배경 이미지 코드를 얻기만 하면 됩니다.

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

저는 SASS를 사용하여 주어진 색상에 따라 SVG 아이콘을 생성하고 싶었기 때문에 base64는 옵션이 아니었습니다. 예:@include svg_icon(heart, #FF0000);이런 식으로 저는 어떤 색상의 특정 아이콘을 만들 수 있으며, SVG 모양을 CSS에 한 번만 내장하면 됩니다. (base64에서는 사용하고자 하는 모든 색상에 SVG를 내장해야 합니다.)

다음 세 가지 사항에 유의해야 합니다.

  1. URL 인코딩 SVG 다른 사람들이 제안한 것처럼 IE11에서 작동하려면 전체 SVG 문자열을 URL 인코딩해야 합니다.제 경우, 다음과 같은 필드에 색상 값을 생략했습니다.fill="#00FF00"그리고.stroke="#FF0000" SAS로 했습니다.fill="#{$color-rgb}"그래서 이것들은 제가 원하는 색으로 대체될 수 있습니다.온라인 변환기를 사용하여 나머지 문자열을 URL로 인코딩할 수 있습니다.다음과 같은 SVG 문자열이 표시됩니다.

    %3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org %2F2000%2Fsvg%27%20 보기박스%3D%270%200%20494.572%20494.572%27%폭20%3D%27512%27높이20%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%20021.808%20105.33%2021.808%20235.266c0% 2041.012% 2010.535% 2079.541% 2028.973% 20113.104L3.825% 20464.586c345% 2012.797% 2041.813% 2015.797% 2015.467% 200% 2029.872-4.721% 2041.813-12.797v158.184z% 27% 20% 3D% 27#{$color-rgb}% 27% 2F% 3C% 2Fsvg% 3E%


  1. 데이터 URL에서 UTF8 문자 집합 생략 데이터 URL을 만들 때 IE11에서 작동하려면 문자 집합을 생략해야 합니다.

    NOT background-image: url(데이터: image/svg+xml;utf-8,%3Csvg%2...)
    BUT 백그라운드-image: url(데이터: image/svg+xml, %3Csvg%2...)


  1. SVG 코드에서 Firefox가 #을 좋아하지 않는 16진수 색상 대신 RGB()를 사용합니다.따라서 색상 16진수 값을 RGB 값으로 대체해야 합니다.

    채우지 않음="#FF0000"
    BUT fill="but (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는 그런 경우에는 결코 존재하지 않음)에 대한 최상의 솔루션이 아닐 수도 있다는 것을 알고 있지만, 몇 가지 색상만 있는 플랫 아이콘에는 정말로 효과적입니다.

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

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 파일을 인코딩하는 base64는 크기가 커집니다. css-tricks.com 블로그 게시물을 참조하십시오.

인라인 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;
}

나침반에서 사용할 수 있는 도우미 기능도 있지만 CodePen에서 지원되지 않기 때문에 이 솔루션이 유용할 수 있습니다.

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

SVG에 대한 해결책을 하나 찾았습니다.하지만 웹킷에서만 작업할 수 있습니다. 저는 제 해결 방법을 여러분과 공유하고 싶습니다.내 예에서는 필터를 통해 DOM의 SVG 요소를 백그라운드로 사용하는 방법을 보여줍니다(background-image:url('#glyph')이 작동하지 않습니다).

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

  1. CSS를 사용하여 SVG 필터 효과를 HTML 요소에 적용(IE 및 Edge는 지원하지 않음)
  2. fe이미지 fragment 로드 지원(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>

타사 소스(예: Google 차트)에서 제공되는 인라인 SVG에는 XML 네임스페이스 특성이 포함되지 않을 수 있습니다.xmlns="http://www.w3.org/2000/svg"SVG 요소의 경우(또는 SVG가 렌더링되면 제거될 수 있음 - 브라우저 콘솔의 브라우저 검사기나 jQuery 명령 모두 SVG 요소의 네임스페이스를 표시하지 않음).

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

Postcs를 사용하는 경우 다음을 시도할 수 있습니다.postcss-inline-svg플러그인 https://www.npmjs.com/package/postcss-inline-svg

.up {
    background: svg-load('img/arrow-up.svg', fill: #000, stroke: #fff);
}
.down {
    background: svg-load('img/arrow-down.svg', fill=#000, stroke=#fff);
}

이미 언급한 https://github.com/yoksel/url-encoder/ 의 접근 방식을 기반으로 프로그래밍 방식으로 수행:

// Svg (string)

const hexagon = `
<svg
width="100"
height="20"
viewBox="0 0 100 20"
xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient
      id="redyel"
      gradientUnits="objectBoundingBox"
      x1="0"
      y1="0"
      x2="1"
      y2="1"
    >
      <stop offset="0%" stop-color="#ff0000" />
      <stop offset="100%" stop-color="#ffff00" />
    </linearGradient>
  </defs>
  <polygon
    points="0,10 5,0 95,0 100,10 95,20 5,20"
    fill="#eee"
    stroke="url(#redyel)"
  />
</svg>
`

// svgToBackgroundImage

const symbols = /[%#()<>?[\\\]^`{|}]/g;

const newLine = /\r?\n/;

const notEmptyString = (str) => str.length;
const trim = (str) => str.trim();

const toOneLine = (str) =>
  str.split(newLine).filter(notEmptyString).map(trim).join(" ");

function addNameSpace(svgString) {
  if (svgString.indexOf(`http://www.w3.org/2000/svg`) < 0) {
    svgString = svgString.replace(
      /<svg/g,
      `<svg xmlns="http://www.w3.org/2000/svg"`
    );
  }

  return svgString;
}

function encodeSVG(svgString) {
  svgString = svgString.replace(/>\s{1,}</g, `><`);
  svgString = svgString.replace(/\s{2,}/g, ` `);

  // Using encodeURIComponent() as replacement function
  // allows to keep result code readable
  return svgString.replace(symbols, encodeURIComponent);
}

const svgToBackgroundImage = (svgString) =>
  `url('data:image/svg+xml,${encodeSVG(addNameSpace(toOneLine(svgString)))}')`;

// DOM

const element = document.querySelector("#hexagon");
element.style.backgroundImage = svgToBackgroundImage(hexagon);
#hexagon {
  width: 100px;
  height: 20px;
}
<div id="hexagon"/>

다음과 같은 작업도 수행할 수 있습니다.

<svg viewBox="0 0 32 32">
      <path d="M11.333 13.173c0-2.51 2.185-4.506 4.794-4.506 2.67 0 4.539 2.053 4.539 4.506 0 2.111-0.928 3.879-3.836 4.392v0.628c0 0.628-0.496 1.141-1.163 1.141s-1.163-0.513-1.163-1.141v-1.654c0-0.628 0.751-1.141 1.419-1.141 1.335 0 2.571-1.027 2.571-2.224 0-1.255-1.092-2.224-2.367-2.224-1.335 0-2.367 1.027-2.367 2.224 0 0.628-0.546 1.141-1.214 1.141s-1.214-0.513-1.214-1.141zM15.333 23.333c-0.347 0-0.679-0.143-0.936-0.404s-0.398-0.597-0.398-0.949 0.141-0.689 0.398-0.949c0.481-0.488 1.39-0.488 1.871 0 0.257 0.26 0.398 0.597 0.398 0.949s-0.141 0.689-0.398 0.949c-0.256 0.26-0.588 0.404-0.935 0.404zM16 26.951c-6.040 0-10.951-4.911-10.951-10.951s4.911-10.951 10.951-10.951c6.040 0 10.951 4.911 10.951 10.951s-4.911 10.951-10.951 10.951zM16 3.333c-6.984 0-12.667 5.683-12.667 12.667s5.683 12.667 12.667 12.667c6.984 0 12.667-5.683 12.667-12.667s-5.683-12.667-12.667-12.667z"></path>
</svg>

언급URL : https://stackoverflow.com/questions/10768451/inline-svg-in-css

반응형