배경 이미지로 제공 될 때 SVG 채우기 색상 수정


270

SVG 출력을 페이지 코드와 직접 인라인으로 배치하면 CSS를 사용하여 채우기 색상을 간단하게 수정할 수 있습니다.

polygon.mystar {
    fill: blue;
}​

circle.mycircle {
    fill: green;
}

이것은 훌륭하게 작동하지만 SVG가 배경 이미지로 제공 될 때 SVG의 "채우기"속성을 수정하는 방법을 찾고 있습니다.

html {      
    background-image: url(../img/bg.svg);
}

지금 색상을 어떻게 바꿀 수 있습니까? 가능합니까?

참고로 외부 SVG 파일의 내용은 다음과 같습니다.

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve">
<polygon class="mystar" fill="#3CB54A" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 
    118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/>
<circle class="mycircle" fill="#ED1F24" cx="202.028" cy="58.342" r="12.26"/>
</svg>

나는 내 대답에 대한 소품으로 자주 타격을 받는다. 놓칠 수 없도록 허용 된 답변으로 변경하는 것을 고려해야합니다.
Ryan

답변:


75

이를 수행하는 한 가지 방법은 일부 서버 측 메커니즘에서 svg를 제공하는 것입니다. GET 매개 변수에 따라 svg를 출력하는 자원 서버 측을 작성하고 특정 URL에이를 제공하십시오.

그런 다음 CSS에서 해당 URL을 사용하십시오.

배경 이미지로서 DOM의 일부가 아니므로이를 조작 할 수 없습니다. 또 다른 가능성은 정기적으로 사용하고 정상적인 방법으로 페이지에 포함 시키지만 절대로 배치하고 페이지의 전체 너비 및 높이를 만든 다음 z-index css 속성을 사용하여 다른 모든 DOM 요소 뒤에 배치하는 것입니다 페이지에.


7
서버 측 스크립트에서 SVG를 제공하고 있는지 확인하고 올바른 MIME 헤더 도 보내야합니다 . PHP에서 이것은 다음과 같습니다 :<?php header('Content-type: image/svg+xml'); ?>
Saul Fautley

4
svg 이미지를 마스크로 사용하고 요소의 배경색을 조작 할 수 있습니다. 채우기를 변경하는 것과 같은 효과가 있습니다. (자세한 대답은 제공)
widged

16
이 답변은 2012 년 기준으로 훌륭했지만 이제는 모든 브라우저에서 CSS 마스크 및 / 또는 필터가 한동안 지원되었습니다. 이 글을 읽는 사람은 이제 아래의 widged 답변에서 링크를 확인하거나 여기 에서 CSS 마스크로 건너 뛰는 것이 좋습니다. 이 방법은 정말 쉬운 해결책입니다. 현재 여전히 -webkit- 접두사가있는 규칙의 2 가지 버전이 필요 합니다. 시각. Microsoft Edge의 경우 현재 CSS 필터는 지원되지만 아직 마스크는 아닙니다.
joelhardi

2
요즘 작동하는 많은 솔루션이 있습니다.이 답변이 더 이상 현재 가능성 상태를 반영하지 않는다는 데 동의합니다.
David Neto

148

비슷한 것이 필요했고 CSS를 고수하고 싶었습니다. 다음은 LESS 및 SCSS 믹스 인과이를 지원하는 일반 CSS입니다. 불행히도 브라우저 지원은 약간 느슨합니다. 브라우저 지원에 대한 자세한 내용은 아래를 참조하십시오.

덜 믹스 인 :

.element-color(@color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="@{color}" ... /></g></svg>');
}

적은 사용량 :

.element-color(#fff);

SCSS 믹스 인 :

@mixin element-color($color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{$color}" ... /></g></svg>');
}

SCSS 사용법 :

@include element-color(#fff);

CSS :

// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');

전체 SVG 코드를 CSS 파일에 포함시키는 방법에 대한 자세한 내용은 다음과 같습니다 . 또한 실행 가능한 옵션이 되기에는 브라우저 호환성이 너무 작습니다.


약간의 오버 헤드가 있지만 모든 svg 항목을 하드 코딩해야하기 때문에 이것이 최선의 해결책이라고 생각합니다. 감사합니다
Adriano Rosa

이런 식으로 사용하려면 Sass 또는 Less와 같은 CSS 프리 프로세서를 사용해야합니다. 하나를 사용하지 않는다면 각 색상마다 그 배경 이미지 라인을 사용하면됩니다
Friendly Code

36
#Firefox에서이 작업을 수행하려면 16 진수 색상 의 문자를 urlencode해야합니다 . 그래서 같은 <svg fill="#ffffff" ...></svg>것이됩니다 <svg fill="%23ffffff" ...></svg>.
Swen

1
달콤한 방법. svg를 그런 배경 이미지로 하드 인코딩해야합니까? 어떻게 든 그것에 연결할 수 있습니까?
luke

2
이 사이트는 완벽하게 인코딩 된 URL을 사용할 수 있도록 준비하는 데 유용하다는 것을 알았습니다. yoksel.github.io/url-encoder-SVG 코드를 복사하여 반환 된 CSS를 복사하십시오. :-)
Friendly Code

95

CSS 마스크를 사용할 수 있습니다. 'mask'속성을 사용하면 요소에 적용되는 마스크를 만듭니다.

.icon {
    background-color: red;
    -webkit-mask-image: url(icon.svg);
    mask-image: url(icon.svg);
}

자세한 내용은이 훌륭한 기사를 참조하십시오 : https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images


3
이것은 좋지만 입력 필드 내의 아이콘에 적용되면 모든 입력 텍스트가 숨겨집니다.
raison

14
IE에서 지원되지 않음
Kareem

매우 멋진 답변이지만 더 이상 호버 등에서 배경색을 사용할 수 없습니다.
Paul Kruger

너무 많은 사용자가 늦게 2018 년에 가능한 오늘 그것을이를 볼 수 없을 것 - 이것은 거의 모든의 경우 지원 될 것으로 보인다 caniuse.com/#feat=css-masks
크리스 Moschini

3
여름 2019 :이 행성 지원 "마스크 이미지"OR "-webkit-마스크 이미지"스타일의 브라우저의 94 %
드미트리 Kulahin

57

또 다른 방법은 마스크를 사용하는 것입니다. 그런 다음 마스크 된 요소의 배경색을 변경합니다. 이는 svg의 fill 속성을 변경하는 것과 동일한 효과를 갖습니다.

HTML :

<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>

CSS :

glyph {
    display: inline-block;
    width:  24px;
    height: 24px;
}

glyph.star {
  -webkit-mask: url(star.svg) no-repeat 100% 100%;
  mask: url(star.svg) no-repeat 100% 100%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: yellow;
}

glyph.heart {
  -webkit-mask: url(heart.svg) no-repeat 100% 100%;
  mask: url(heart.svg) no-repeat 100% 100%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: red;
}

http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images (내 자신의 것이 아님) 전체 자습서를 찾을 수 있습니다. 다양한 접근 방식을 제안합니다 (마스크에만 국한되지 않음).


11
이것에 주목해야 할 것은 브라우저 지원입니다. 나는 IE (일반적으로)가 이것보다 뒤떨어져 있다고 생각합니다.
Matthew Johnson

9
불행히도 maskIE는 물론 Edge도 지원하지 않습니다 : caniuse.com/#search=mask
alpipego 8

Chrome에서도 작동하지 않습니다. 편집 : 오 nvm ... 자동 접두사가 활성화되어 있지 않습니다. 벤더가 접두사 사용을 중단해야한다고 생각 했습니까?!
mpen

최신 크롬 및 파이어 폭스에서 작동
tic

16

Sass로 가능합니다! 당신이해야 할 유일한 것은 svg 코드를 URL 인코딩하는 것입니다. 그리고 이것은 Sass의 도우미 기능으로 가능합니다. 이를 위해 코드 펜을 만들었습니다. 이거 봐요:

http://codepen.io/philippkuehn/pen/zGEjxB

// choose a color

$icon-color: #F84830;


// functions to urlencode the svg string

@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }
  @return $string;
}

@function url-encode($string) {
  $map: (
    "%": "%25",
    "<": "%3C",
    ">": "%3E",
    " ": "%20",
    "!": "%21",
    "*": "%2A",
    "'": "%27",
    '"': "%22",
    "(": "%28",
    ")": "%29",
    ";": "%3B",
    ":": "%3A",
    "@": "%40",
    "&": "%26",
    "=": "%3D",
    "+": "%2B",
    "$": "%24",
    ",": "%2C",
    "/": "%2F",
    "?": "%3F",
    "#": "%23",
    "[": "%5B",
    "]": "%5D"
  );
  $new: $string;
  @each $search, $replace in $map {
    $new: str-replace($new, $search, $replace);
  }
  @return $new;
}

@function inline-svg($string) {
  @return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}


// icon styles
// note the fill="' + $icon-color + '"

.icon {
  display: inline-block;
  width: 50px;
  height: 50px;
  background: inline-svg('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
<path fill="' + $icon-color + '" d="M18.7,10.1c-0.6,0.7-1,1.6-0.9,2.6c0,0.7-0.6,0.8-0.9,0.3c-1.1-2.1-0.4-5.1,0.7-7.2c0.2-0.4,0-0.8-0.5-0.7
  c-5.8,0.8-9,6.4-6.4,12c0.1,0.3-0.2,0.6-0.5,0.5c-0.6-0.3-1.1-0.7-1.6-1.3c-0.2-0.3-0.4-0.5-0.6-0.8c-0.2-0.4-0.7-0.3-0.8,0.3
  c-0.5,2.5,0.3,5.3,2.1,7.1c4.4,4.5,13.9,1.7,13.4-5.1c-0.2-2.9-3.2-4.2-3.3-7.1C19.6,10,19.1,9.6,18.7,10.1z"/>
</svg>');
}

2
이것은 매우 잘 작동합니다. 유일한 문제 : IE10에서 아이콘이 너무 작습니다 (주어진 크기의 10 %를 생각합니다.
Henning Fischer

13
 .icon { 
  width: 48px;
  height: 48px;
  display: inline-block;
  background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/heart.svg) no-repeat 50% 50%; 
  background-size: cover;
}

.icon-orange { 
  -webkit-filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4); 
  filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4); 
}

.icon-yellow {
  -webkit-filter: hue-rotate(70deg) saturate(100);
  filter: hue-rotate(70deg) saturate(100);
}

코드 벤 기사 및 데모


1
이 방법은 자식을 포함하여 전체 개체에 필터를 적용합니다.
Krzysztof Antoniak

9

svg를 텍스트로 다운로드하십시오.

페인트 / 스트로크 / 채우기 색상을 변경하려면 자바 스크립트를 사용하여 svg 텍스트를 수정하십시오.

그런 다음 여기에 설명 된대로 수정 된 svg 문자열을 CSS에 인라인으로 포함시킵니다 .


9

이제 다음과 같이 클라이언트 측에서이를 수행 할 수 있습니다.

var green = '3CB54A';
var red = 'ED1F24';
var svg = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"  width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve"> <polygon class="mystar" fill="#'+green+'" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/><circle class="mycircle" fill="#'+red+'" cx="202.028" cy="58.342" r="12.26"/></svg>';      
var encoded = window.btoa(svg);
document.body.style.background = "url(data:image/svg+xml;base64,"+encoded+")";

여기에 바이올린!


1
SVG에 Base64를 사용하는 것은 불필요하므로 파일을 더 크게 만들고 GZIP가 이러한 코드 조각을 효과적으로 압축하지 못하게합니다.
inta

1
이 인코딩은 클라이언트 측에서 일어나고 있습니다. 아마도 이스케이프 처리를 위해서 일 것입니다.
diachedelic

JS로 무엇이든 할 수 있다는 것은 말할 것도 없습니다. 요점은 JS를 피하는 것입니다.
MarsAndBack

7

SVG를 변수에 저장할 수 있습니다. 그런 다음 필요에 따라 SVG 문자열을 조작하십시오 (예 : 너비, 높이, 색상 등 설정). 그런 다음 결과를 사용하여 배경을 설정하십시오.

$circle-icon-svg: '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" /></svg>';

$icon-color: #f00;
$icon-color-hover: #00f;

@function str-replace($string, $search, $replace: '') {
    $index: str-index($string, $search);

    @if $index {
        @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
    }

    @return $string;
}

@function svg-fill ($svg, $color) {
  @return str-replace($svg, '<svg', '<svg fill="#{$color}"');
}

@function svg-size ($svg, $width, $height) {
  $svg: str-replace($svg, '<svg', '<svg width="#{$width}"');
  $svg: str-replace($svg, '<svg', '<svg height="#{$height}"');

  @return $svg;
}

.icon {
  $icon-svg: svg-size($circle-icon-svg, 20, 20);

  width: 20px; height: 20px; background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color)}');

  &:hover {
    background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color-hover)}');
  }
}

http://sassmeister.com/gist/4cf0265c5d0143a9e734 데모도 만들었습니다 .

이 코드는 SVG에 대해 몇 가지 가정을합니다. 예를 들어 <svg />요소에 기존 채우기 색상이없고 너비 또는 높이 속성이 설정되어 있지 않습니다. 입력은 SCSS 문서에서 하드 코딩되므로 이러한 제약 조건을 적용하기가 매우 쉽습니다.

코드 복제에 대해 걱정하지 마십시오. 압축은 차이를 무시할 만하게 만듭니다.


중복 코드는 코드 냄새가 있으므로 예제의 경우 사람들이 중복 코드에 대해 걱정하지 말라고 제안하는 것은 좋은 생각이 아니지만 코드가 복제 된 위치를 볼 수 없다고 말했습니까? 주석을 모두 제거하면 더 잘 읽을 것이라고 생각합니다.
프로그래밍 교수

3

이를 위해 고유 한 SCSS 기능을 만들 수 있습니다. config.rb 파일에 다음을 추가하십시오.

require 'sass'
require 'cgi'

module Sass::Script::Functions

  def inline_svg_image(path, fill)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    svg.gsub! '{color}', fill.value
    encoded_svg = CGI::escape(svg).gsub('+', '%20')
    data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

그런 다음 CSS에서 사용할 수 있습니다.

.icon {
  background-image: inline-svg-image('icons/icon.svg', '#555');
}

SVG 파일을 편집하고 마크 업의 채우기 속성을 fill = "{color}"로 바꿔야합니다.

아이콘 경로는 항상 동일한 config.rb 파일의 images_dir 매개 변수와 관련이 있습니다.

다른 솔루션 중 일부와 유사하지만 이것은 매우 깨끗하며 SCSS 파일을 깔끔하게 유지합니다!


1
이것은 github-issue에서 온 것 입니다. 누군가가 그곳에서 토론을 읽고 싶어하는 경우를 대비하여 여기에서 참조하십시오
MMachinegun

2

일부 매우 구체적인 상황에서는 필터 를 사용하여이를 달성 할 수 있습니다 . 예를 들어,을 사용하여 색조를 45도 회전하여 파란색 SVG 이미지를 자주색으로 변경할 수 있습니다 filter: hue-rotate(45deg);. 브라우저 지원은 최소한이지만 여전히 흥미로운 기술입니다.

데모


2

단색 배경의 경우 배경색을 표시 해야하는 마스크가있는 svg를 사용할 수 있습니다

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" preserveAspectRatio="xMidYMid meet" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;" >
    <defs>
        <mask id="Mask">
            <rect width="100%" height="100%" fill="#fff" />
            <polyline stroke-width="2.5" stroke="black" stroke-linecap="square" fill="none" transform="translate(10.373882, 8.762969) rotate(-315.000000) translate(-10.373882, -8.762969) " points="7.99893906 13.9878427 12.7488243 13.9878427 12.7488243 3.53809523"></polyline>
        </mask>
    </defs>
    <rect x="0" y="0" width="20" height="20" fill="white" mask="url(#Mask)" />
</svg>

이 CSS를 사용하는 것보다

background-repeat: no-repeat;
background-position: center center;
background-size: contain;
background-image: url(your/path/to.svg);
background-color: var(--color);


1

SVG 코드를 직접 편집 할 수 있다면 SVG 다각형에 채우기 색상을 추가 할 수 있었으므로 예를 들어 다음 svg는 기본 검정 대신 빨간색을 렌더링합니다. 그래도 Chrome 외부에서는 테스트하지 않았습니다.

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
    <polygon 


        fill="red"


        fill-rule="evenodd" clip-rule="evenodd" points="452.5,233.85 452.5,264.55 110.15,264.2 250.05,390.3 229.3,413.35 
47.5,250.7 229.3,86.7 250.05,109.75 112.5,233.5 "/>
</svg>

-2

이것은 내가 가장 좋아하는 방법이지만 브라우저 지원은 매우 진보적이어야합니다. 마스크 속성을 사용하면 요소에 적용되는 마스크를 만듭니다. 마스크가 불투명하거나 단색 인 모든 곳에서 기본 이미지가 표시됩니다. 투명하면 기본 이미지가 마스킹되거나 숨겨집니다. CSS 마스크 이미지의 구문은 배경 이미지와 유사합니다. 코드 펜을 봐mask


-5

많은 IF이지만 pre base64로 인코딩 된 SVG가 시작되는 경우 :

<svg fill="#000000

그런 다음 base64로 인코딩 된 문자열이 시작됩니다.

PHN2ZyBmaWxsPSIjMDAwMDAw

사전 인코딩 된 문자열이 시작되는 경우 :

<svg fill="#bfa76e

그런 다음이 인코딩

PHN2ZyBmaWxsPSIjYmZhNzZl

인코딩 된 두 문자열은 동일하게 시작됩니다.

PHN2ZyBmaWxsPSIj

base64 인코딩의 기발한 점은 3 입력 문자마다 4 출력 문자가됩니다. SVG가 이와 같이 시작되면 6 문자 16 진수 채우기 색상이 인코딩 블록 '경계'에서 정확하게 시작됩니다. 따라서 브라우저 간 JS 교체를 쉽게 수행 할 수 있습니다.

output = input.replace(/MDAwMDAw/, "YmZhNzZl");

그러나 위의 tnt-rox 답변은 앞으로 나아가는 길입니다.

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