SVG закраска (fill) с помощью CSS переменных
Я пытаюсь использовать переменные 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");
}
Я видел здесь CSS-переменные, используемые в SVG, но я не уверен, можно ли это сделать с фоновыми изображениями? Я новичок в использовании переменных SVG и CSS, поэтому я уверен, что делаю что-то не так ... Хотелось бы понять, почему он не отображает цвет правильно!
Свободный перевод вопроса SVG fill with css variables от участника @sammiepls.
Ответы (2 шт):
Хорошо, поехали ... Сначала я объясню, почему это не работает, а затем покажу альтернативу.
Почему ваше решение не работает
В вашем примере svg не является частью DOM. Таким образом, вы не можете использовать css для изменения атрибутов svg.
Что вы делаете, так это добавляете встроенный стиль к svg в вашем URL-адресе. Поскольку браузер не распознает переменную --primary-color как цвет, то он и не работает закраска.
Альтернативное решение
Альтернативный подход - поместить svg в html и подделать фон. Я сделал это, разместив svg в абсолютном положении и переместив его на задний план с помощью z-index.
Обратите внимание, что вам придется изменить svg или позиционирование, чтобы разместить фон так, как вы хотите. Обычно для этого используется размер фона. Но приложив некоторые усилия, вы можете воспроизвести это поведение в svg или лучше позиционировать его с помощью css.
:root {
--primary-color: hsl(332, 61%, 78%);
}
div {
width: 100px;
height: 100px;
}
.test {
background: var(--primary-color);
}
.icon{ /*Работает позиционирование относительное или абсолютное позиционирование */
position: relative;
}
.icon>svg{
position: absolute;
top: 0px;
right: 0px;
left: 0px;
bottom: 0px;
z-index: -1;
}
.icon>svg>path{ /*нацелить изображение с помощью CSS*/
fill: var(--primary-color);
}
<div class="test">
Тестирование цвета переменной css
</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>Здесь текст...</p>
</div>
Свободный перевод ответа от участника @Rob Monhemius.
Решение с помощью тега <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"/>
Каждому path, circle, ellips, и т.д можно присвоить для fill свою переменную fill="var(--color-face)" и в дальнейшем менять её значение во внешней таблице стилей:
.monstr-colors { --color-face: #7986CB; --color-nose: #9FA8DA; }
Этот прием создаёт мощные и гибкие возможности для стилизации многоцветных иконок.
Например для одного состояния иконки мы можем назначить одну цветовую схему, а при :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;
outline:1px solid green;
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>