SVG填充CSS变量

7bsow1i6  于 2023-06-25  发布在  其他
关注(0)|答案(8)|浏览(174)

我试图使用CSS变量在我的SVG(这是设置为背景图像)的填充颜色,但我有困难,让它的工作。它显示默认的黑色,但当我检查它时,我可以看到css变量在那里,并显示我想要的颜色。
HTML

<div class="test">
  Testing the css variable color
</div>

<div class="icon">

</div>

CSS

:root {
  --primary-color: hsl(332, 61%, 78%);
}

div {
  width: 100px;
  height: 100px; 
}

.test {
  background: var(--primary-color);
}

.icon {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='var(--primary-color)' /%3E%3C/svg%3E");
}

Here is a codepen to check out!
我见过在SVG here中使用CSS变量,但我不确定是否可以使用背景图像?我对使用SVG和CSS变量都是新手,所以我不确定我是否做错了什么。会喜欢一些见解,为什么它没有正确渲染颜色!

xzlaal3s

xzlaal3s1#

您可以将SVG包含为mask-image,而不是background-image。记住,将background-color设置为.icon块的CSS变量。

.icon {
  background: var(--primary-color);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' /%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' /%3E%3C/svg%3E");
}
bprjcwpo

bprjcwpo2#

好了,我们走吧……我将首先解释为什么它不起作用,然后我将展示一个替代方案。

为什么你的方法行不通

在您的示例中,svg不是DOM的一部分。所以你不能使用css来修改svg的属性。
你正在做的是在你的url中添加一个inline-style到svg中。由于浏览器无法识别--primary-color为颜色,因此无法正常工作。

另一种方法

另一种方法是将svg放在html中并伪造一个背景。我通过绝对定位svg并使用z-index将其移动到背景中来做到这一点。
请注意,您将不得不修改svg或定位,以按照您想要的方式放置背景。通常,你会使用background-size来实现这一点。但是通过一些努力,你可以在svg中复制这种行为,或者通过使用css更好地定位它。

:root {
  --primary-color: hsl(332, 61%, 78%);
}

div {
  width: 100px;
  height: 100px; 
}

.test {
  background: var(--primary-color);
}
.icon{ /*postion relative for absolute positioning to work*/
  position: relative; 
}
.icon>svg{
  position: absolute;
  top: 0px;
  right: 0px;
  left: 0px;
  bottom: 0px;
  z-index: -1;
}
.icon>svg>path{ /*target the image with css*/
  fill: var(--primary-color);
}
<div class="test">
  Testing the css variable color
</div>

<div class="icon">
  <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129' id='background'><path d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z'/> </svg>
  <p>Text goes here...</p>
</div>
fruv7luv

fruv7luv3#

不要将svg作为背景,这样做你就无法控制它的填充,而是尝试在html中内联添加它,通过css你可以通过css变量控制填充,请查看下面的工作示例,希望它有帮助:)

:root {
  --primary-color: hsl(332, 61%, 78%);
}

div {
  width: 100px;
  height: 100px;
}

.test {
  background: var(--primary-color);
}

.icon {
  color: var(--primary-color);
  fill: currentColor;
  width: 64px;
  height: 64px;
}
<div class="test">
  Testing the css variable color
</div>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 129 129">
  <path d="m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z"/>
</svg>
z4iuyo4d

z4iuyo4d4#

使用<symbol>标签和CSS变量

CSS变量继承fill属性。因此,可以在<symbol>标签中分配(声明)一个变量,该变量的值随后可以为svg元素的每个示例更改多次。

<symbol id="monstr"> 
<rect width="100%" height="100%" fill="transparent" />
<path id="face" fill="var(--color-face)" d="M15.4,34.1L24,37l8.6-2.9c1.9-0.6,3-2.6,2.6-4.6L33,20H15l-2.2,9.5C12.3,31.5,13.5,33.5,15.4,34.1z"/>
<path  id="nose" fill="var(--color-nose)" d="M29,30l-3-3h-4l-3,3v7c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V30z"/>

每个pathcircleellips等可以为填充指定自己的变量fill = "var (- color-face)",然后在外部样式表中更改其值:
.monstr-colors { --color-face: #7986CB; --color-nose: #9FA8DA; }
这种技术为多色svg创建了强大而灵活的样式选项。
例如,对于一个图标的一个状态,我们可以指定一个配色方案,并使用: hover,为同一个图标指定不同的颜色集。

.monstr-colors {
  --color-face: #7986CB;
  --color-nose: #9FA8DA;
} 
.monstr-colors:hover {
  --color-face: #3F8B4D;  
  --color-nose: #58C46C;
)

下面是一个示例,根据您的口味,图像的配色方案很容易创建和更改:

.monstr-colors {
  --color-face: #7986CB;
  --color-nose: #9FA8DA;
  --color-hair-right:#3949AB;
  --color-hair-right2:#3949AB;
  --color-hair-left:#3949AB;
  --color-hair-left2:#3949AB;
  --color-eye-right:#1A237E;
  --color-pupil-right:#77006B;
  --color-eye-left:#1A237E;
  --color-pupil-left:#77006B;
  --color-ellipse1:#9FA8DA;
  --color-ellipse2:#7986CB;
  --color-ellipse3:#C5CAE9;
}  

.monstr-colors:hover {
  --color-face: #3F8B4D;  
  --color-nose: #58C46C;
  --color-hair-right:gold;
  --color-hair-right2:#FFBB00;
  --color-hair-left:gold;
  --color-hair-left2:#FFBB00;
  --color-eye-right:#77006B;
  --color-pupil-right:#FF4151;
  --color-eye-left:#77006B;
  --color-pupil-left:#FF4151;
  --color-ellipse1:#FFDD00;
  --color-ellipse2:#C1A700;
  --color-ellipse3:#FFEE7D;
}
<svg  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"  width="192" height="192" viewBox="0 0 48 48" > 
<symbol id="monstr"> 
<rect width="100%" height="100%" fill="transparent" />
<path id="face" fill="var(--color-face)" d="M15.4,34.1L24,37l8.6-2.9c1.9-0.6,3-2.6,2.6-4.6L33,20H15l-2.2,9.5C12.3,31.5,13.5,33.5,15.4,34.1z"/>
<path  id="nose" fill="var(--color-nose)" d="M29,30l-3-3h-4l-3,3v7c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V30z"/>

    <path id="hair-right" fill="var(--color-hair-right)" d="M31,7c-0.5,0-1,0.4-1,1c0,0,0,0,0,0c-0.4,0-0.8,0.2-0.9,0.6c-0.2,0.5,0,1.1,0.6,1.3   C30,10.1,40,14.4,40,32.4V37c0,0.6,0.4,1,1,1s1-0.4,1-1v-4.6c0-14.4-6.1-20.7-9.5-23.1C35.9,10.3,44,14.7,44,34c0,0.6,0.4,1,1,1   s1-0.4,1-1C46,7.7,31.6,7,31,7z"/>
    <path id="hair-right2" fill="var(--color-hair-right2)" d="M29.5,10.1c-0.5-0.3-1.1-0.1-1.3,0.4c-0.3,0.5-0.1,1.1,0.4,1.4c0.1,0,7.5,4.3,7.5,20.1v8c0,0.6,0.4,1,1,1   s1-0.4,1-1v-8C38,14.9,29.8,10.3,29.5,10.1z"/>
    <path id="hair-left" fill="var(--color-hair-left)" d="M18.4,9.9c0.5-0.2,0.8-0.8,0.6-1.3C18.8,8.2,18.4,8,18,8c0,0,0,0,0,0c0-0.6-0.5-1-1-1C16.4,7,2,7.7,2,34   c0,0.6,0.4,1,1,1s1-0.4,1-1c0-19.6,8.1-23.8,11.6-24.7C12.2,11.6,6,17.9,6,32.4V37c0,0.6,0.4,1,1,1s1-0.4,1-1v-4.6   C8,14.4,18,10.1,18.4,9.9z"/>
    <path id="hair-left" fill="var(--color-hair-left2)" d="M18.5,10.1C18.2,10.3,10,14.9,10,32v8c0,0.6,0.4,1,1,1s1-0.4,1-1v-8c0-15.8,7.4-20.1,7.5-20.1   c0.5-0.3,0.7-0.9,0.4-1.4C19.6,10,19,9.9,18.5,10.1z"/>

<path id="eye-right" fill="var(--color-eye-right)" d="M25,24.9c0,0,0.2,1.3,0.6,1.7s3.3,2.5,5.9-0.9c1.2-1.5,0.6-3.8,0.6-3.8S29.4,24.1,25,24.9z"/>
<circle id="pupil-right" cx="28" cy="25" r="1.5" fill="var(--color-pupil-right)" />
<path id="eye-left" fill="var(--color-eye-left)" d="M15.8,21.8c0,0-0.6,2.3,0.6,3.8c2.6,3.4,5.5,1.4,5.9,0.9c0.4-0.4,0.6-1.7,0.6-1.7  C18.6,24.1,15.8,21.8,15.8,21.8z"/> 
<circle id="pupil-left" fill="var(--color-pupil-left)" cx="20" cy="25" r="1.5" fill="red" />
<ellipse  id="ellipse1" fill="var(--color-ellipse1)" cx="24" cy="15" rx="12" ry="10"/>
<ellipse id="ellipse2" fill="var(--color-ellipse2)" cx="24" cy="13.8" rx="10" ry="7.8"/>
<ellipse id="ellipse3" fill="var(--color-ellipse3)" cx="24.2" cy="12.2" rx="8" ry="6.2"/> 

</symbol> 
 <svg class="monstr-colors">
  <use  xlink:href="#monstr" />
 </svg>
</svg>

下面是一个组合的示例,其中对同一个图像的三个示例进行样式化。

创建的<use xlink: href = "# monstr"/>的每个示例都有自己的配色方案,该配色方案链接到嵌套的svg类。

<div class="container">
<svg class="color-monstr">
<use xlink:href="#monstr" transform="scale(3)" />
</svg> 
 </div>
<div class="container2">
<svg class="color-monstr2">
<use xlink:href="#monstr" transform="scale(2)"  />
</svg> 
</div> 

<div class="container3">
<svg class="color-monstr3">
<use xlink:href="#monstr" transform="scale(3)"  />
</svg> 
</div>

使用:hover时,每个示例都使用相邻示例的配色方案替换配色方案。

.parent {
position:relative;
}
.container {
width:400px;
height:400px;
position:absolute;
top:0;
} 
.container2 {
position: absolute;
top:0;
left:150px;

} 

.container3 {
position: absolute;
top:0;
left:240px;

} 

.color-monstr {
  --color-ears: #459E48;
  --color-horn-right: #388E3C;
  --color-horn-left: #388E3C;
  --color-face:#4CAF50;
  --circle-horn-left:#8BC34A;
  --circle-horn-right:#8BC34A;
  --eye-right:#FFF9C4;
  --eye-left:#FFF9C4;
  --pupil-right:#263238;
  --pupil-left:#263238;
  --mouth:#173027;
  }  
  
  .color-monstr:hover {
  --color-ears: #504F7A;
  --color-horn-right: #504FF6;
  --color-horn-left: #504FF6;
  --color-face:#807FC4;
  --circle-horn-left:#FF00AE;
  --circle-horn-right:#FF00AE;
  --eye-right:#FFDBF4;
  --eye-left:#FFDBF4;
  --pupil-right:#263238;
  --pupil-left:#263238;
  --mouth:#FFDBF4;
  }  
  
  .color-monstr2 {
  --color-ears: #504F7A;
  --color-horn-right: #504FF6;
  --color-horn-left: #504FF6;
  --color-face:#807FC4;
  --circle-horn-left:#FF00AE;
  --circle-horn-right:#FF00AE;
  --eye-right:#FFDBF4;
  --eye-left:#FFDBF4;
  --pupil-right:#263238;
  --pupil-left:#263238;
  --mouth:#FFDBF4;
  }   
  
  .color-monstr2:hover {
  --color-ears: #770051;
  --color-horn-right: #388E3C;
  --color-horn-left: #388E3C;
  --color-face:#FFDD00;
  --circle-horn-left:#D0FF00;
  --circle-horn-right:#A0C400;
  --eye-right:#FFF9C4;
  --eye-left:#FFF9C4;
  --pupil-right:#263238;
  --pupil-left:#263238;
  --mouth:#FFF9C4;
  
  }  
  
  .color-monstr3 {
  --color-ears: #770051;
  --color-horn-right: #388E3C;
  --color-horn-left: #388E3C;
  --color-face:#FFDD00;
  --circle-horn-left:#D0FF00;
  --circle-horn-right:#A0C400;
  --eye-right:#FFF9C4;
  --eye-left:#FFF9C4;
  --pupil-right:#263238;
  --pupil-left:#263238;
  --mouth:#FFF9C4;
  } 
  
  .color-monstr3:hover {
  --color-ears: #459E48;
  --color-horn-right: #388E3C;
  --color-horn-left: #388E3C;
  --color-face:#4CAF50;
  --circle-horn-left:#8BC34A;
  --circle-horn-right:#8BC34A;
  --eye-right:#FFF9C4;
  --eye-left:#FFF9C4;
  --pupil-right:#263238;
  --pupil-left:#263238;
  --mouth:#173027;
  }
<div class="parent">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"   viewBox="0 0 48 48" > 
<symbol id="monstr">

<path id="ears"
 fill="var(--color-ears)"
  d="M12,31c-2.3,0-3.7-3.2-4-5c0.7-1.3,3.3-2,4-2c5.7-2.4,17.8-2.9,24,0c0.7,0,3.3,0.7,4,2c-0.3,1.8-1.7,5-4,5  C33.6,32.8,14.7,34.2,12,31z"/>
<g>
    <path id="horn-right"
   fill="var(--color-horn-right)" d="M40,8c-0.6,0-1,0.4-1,1c0,2.7-3.3,5-6,5c-0.6,0-1,0.4-1,1s0.4,1,1,1c3.7,0,8-3.1,8-7C41,8.4,40.6,8,40,8z"/>
    <path id="horn-left"
   fill="var(--color-horn-left)" d="M8,8c0.6,0,1,0.4,1,1c0,2.7,3.3,5,6,5c0.6,0,1,0.4,1,1s-0.4,1-1,1c-3.7,0-8-3.1-8-7C7,8.4,7.4,8,8,8z"/>
</g>
<path id="face"
 fill="var(--color-face)" d="M12,31v-7c0-9.2,5.3-16,12-16s12,6.8,12,16v7c-1.2,5.6-7,12-12,12S13.2,36.6,12,31z"/>
<g>
    <circle id="circle-horn-left" fill="var(--circle-horn-left)" cx="8" cy="9" r="3"/>
    <circle id="circle-horn-right" fill="var(--circle-horn-right)" cx="40" cy="9" r="3"/>
</g>
<g>
    <ellipse id="eye-right" fill="var(--eye-right)" cx="29" cy="26" rx="2" ry="4"/>
    <ellipse id="eye-left" fill="var(--eye-left)" cx="19" cy="26" rx="2" ry="4"/>
</g>
<g>
    <circle id="pupil-right" fill="var(--pupil-right)" cx="29" cy="27" r="1"/>
    <circle id="pupil-left" fill="var(--pupil-left)" cx="19" cy="27" r="1"/>
</g>
<path id="mouth" fill="var(--mouth)" d="M24,33c-4,0-5.8,3-5.8,3s2.6,0,5.8,0s5.8,0,5.8,0S28,33,24,33z"/>
</symbol> 
</svg>

<div class="container">
<svg class="color-monstr">
<use xlink:href="#monstr" transform="scale(3)" />
</svg> 
 </div>
<div class="container2">
<svg class="color-monstr2">
<use xlink:href="#monstr" transform="scale(2)"  />
</svg> 
</div> 

<div class="container3">
<svg class="color-monstr3">
<use xlink:href="#monstr" transform="scale(3)"  />
</svg> 
</div>

</div>
kx7yvsdv

kx7yvsdv5#

我偶然发现了一个非常相似的案例,并想分享一个完全不同的方法。
使用css多背景功能(MDN Docs
首先,您需要使用fill="transparent"将SVG中希望着色为透明的部分
现在您可以只指定多个背景,其中一个可以是您的变量,例如

body {
    background: url('path/to/your/svg/or/data-url'), var(--background);
}
mo49yndu

mo49yndu6#

这里是一个更好的方法或我如何着色我的SVG。由于内联SVG对其余代码的可读性有一个苦涩的味道,并将它们添加为背景或遮罩,它们不能通过深色主题开关着色。在外部包含它们并将它们加载到html对象中:

<object id="background-anim" class="svg" aria-hidden="true" data="./media/Background-fluid-lines-anim.svg" type="image/svg+xml"></object>

此SVG现在是外部添加的。要设置颜色,您需要为所需的颜色设置SVG***内部的类***。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080">
  <defs>
    <style>
        .svg-element__clrText{
            fill:rgb(255,255,255);
        }
        .svg-element__clrPrimary{
            fill:rgb(155,155,155);
        }
        .svg-element__clrBackground{
            fill:rgb(55,55,55);
        }
    </style>
  </defs>
  <path class="svg-element__clrText"></path>
</svg>

在路径中,将这些类设置为需要适应颜色的元素。现在,您将使用JavaScript操作这些填充值,并添加正确的CSS自定义属性:

/*Optional: Listening to the clicked switch if you have one*/
document.querySelectorAll('.theme-toggle').forEach((toggle) => {
   toggle.addEventListener('click', () => themeToggle);
});
window.themeToggle = function themeToggle() {
   document.documentElement.classList.toggle('darkMode');
   //this .darkmode{} class changes the values of my variables set to white mode in the ':root{}' in the css file
   loadTheme()
}
function loadTheme(){
   /* For loading more than just the colors */
   loadThemeIcon();
   loadSVGColors();
}

/* Now here comes the important part */
function loadSVGColors() {
   const svgs = document.querySelectorAll('.svg'); //getting NodeList of SVGs
   const style = getComputedStyle(document.body), //getting CSS variables inside of js
   svgs.forEach(svg => {
               element = svg.contentDocument; //get the actual svg that is loaded into the object element
         const clrText = svg.querySelectorAll('.svg-element__textClr'), //searching inside of the SVG after my classes
         textClr.forEach(element => { //NodeList to Array
              element.style.fill = style.getPropertyValue('--clr-text');//whatever variables you have set or you can toggle a class that has only this css variable inside
         });

         /* [...and so on]*/
         const primeClr = element.querySelectorAll('.svg-element__primeClr');
         primeClr.forEach(e => {
              e.style.fill = style.getPropertyValue('--clr-primary');
         });
   });
}

我想,当你用fill: var(--clr-text)在HTML中添加SVG时,性能会更好,但是在每个SVG有50kb代码后,会导致大量滚动
我知道这比问题更进一步,但我很高兴在这些SO职位之前找到这一点。

dgtucam1

dgtucam17#

如果只需要控制一种颜色,可以在fill属性中使用currentColor关键字,并通过css color属性进行更改。

.icon {
  color: var(--primary-color);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='currentColor' /%3E%3C/svg%3E");
}
envsm3lx

envsm3lx8#

<path class="class-name"/>

:root {
   --color : #123456;
}
.class-name {
   fill : var(--color)
}

试试这个

相关问题