Как применить прозрачность к цветовой переменной CSS?
Я разрабатываю приложение в электронном виде, поэтому у меня есть доступ к переменным CSS. Я определил цветовую переменную в vars.css
:
:root {
--color: #f0f0f0;
}
Я хочу использовать этот цвет в main.css
, но с некоторой непрозрачностью:
#element {
background: (somehow use var(--color) at some opacity);
}
Как бы я поступил так? Я не использую никакой препроцессор, только CSS. Я бы предпочел полностью CSS-ответ, но я приму JavaScript/jQuery.
Я не могу использовать opacity
потому что я использую фоновое изображение, которое не должно быть прозрачным.
22 ответа
Вы не можете взять существующее значение цвета и применить к нему альфа-канал. А именно, вы не можете принять существующее шестнадцатеричное значение, такое как #f0f0f0
, дайте ему альфа-компонент и используйте полученное значение с другим свойством.
Тем не менее, пользовательские свойства позволяют преобразовать шестнадцатеричное значение в триплет RGB для использования с rgba()
, сохраните это значение в пользовательском свойстве (включая запятые!), подставьте это значение, используя var()
в rgba()
Функция с вашим желаемым альфа-значением, и это будет просто работать:
:root {
/* #f0f0f0 in decimal RGB */
--color: 240, 240, 240;
}
body {
color: #000;
background-color: #000;
}
#element {
background-color: rgba(var(--color), 0.5);
}
<p id="element">If you can see this, your browser supports custom properties.</p>
Это кажется слишком хорошим, чтобы быть правдой. 1 Как это работает?
Волшебство заключается в том, что значения пользовательских свойств подставляются как есть при замене var()
ссылки в значении свойства до вычисления значения этого свойства. Это означает, что для пользовательских свойств значение --color
в вашем примере это не значение цвета вообще, пока var(--color)
выражение появляется где-то, что ожидает значение цвета (и только в этом контексте). Из раздела 2.1 спецификации css-переменных:
Разрешенный синтаксис для пользовательских свойств является чрезвычайно разрешающим. Продукция <объявление-значение> соответствует любой последовательности одного или нескольких токенов, при условии, что последовательность не содержит
, , unmatched <) - token>, <] - token>, или <} - token>, или токены верхнего уровня <точка с запятой>, или токены со значением "!".
Например, следующее является допустимым пользовательским свойством:
--foo: if(x > 5) this.width = 10;
Хотя это значение, очевидно, бесполезно в качестве переменной, так как оно будет недопустимым в любом обычном свойстве, оно может быть прочитано и обработано JavaScript.
И раздел 3:
Если свойство содержит одну или несколько функций var(), и эти функции синтаксически допустимы, грамматика всего свойства должна считаться действительной во время анализа. Он проверяется только на синтаксис во время вычисляемого значения после замены функций var().
Это означает, что 240, 240, 240
значение, которое вы видите выше, подставляется непосредственно в rgba()
Функция до объявления декларации. Итак, это:
#element {
background-color: rgba(var(--color), 0.5);
}
который на первый взгляд не является действительным CSS, потому что rgba()
ожидает не менее четырех числовых значений, разделенных запятыми, становится так:
#element {
background-color: rgba(240, 240, 240, 0.5);
}
что, конечно же, является совершенно правильным CSS.
Сделав еще один шаг вперед, вы можете сохранить альфа-компонент в его собственном пользовательском свойстве:
:root {
--color: 240, 240, 240;
--alpha: 0.5;
}
и подставим его с тем же результатом:
#element {
background-color: rgba(var(--color), var(--alpha));
}
Это позволяет вам иметь различные альфа-значения, которые вы можете менять на лету.
1 Хорошо, если вы запускаете фрагмент кода в браузере, который не поддерживает пользовательские свойства.
Синтаксис относительного цвета
Благодаря этой новой возможности CSS (css-color-5), которая позволяет преобразовывать формат цвета, она также позволяет добавлять непрозрачность к любому цвету в любом формате, например, к
RGB
(относительные преобразования могут быть выполнены для любого другого формата):
html { --color: blue }
.with-opacity { background: rgb(from var(--color) r g b / 50%) }
(На момент написания пока недоступно в браузерах. Будет обновлено после прибытия)
Я знаю, что OP не использует препроцессор, но мне бы помогли, если бы здесь ответом была следующая информация (я пока не могу комментировать, иначе я бы прокомментировал ответ @BoltClock.
Если вы используете, например, scss, ответ выше не даст результатов, потому что scss пытается скомпилировать стили с помощью специфичной для scss функции rgba()/hsla(), которая требует 4 параметра. Однако rgba()/hsla() также являются нативными функциями css, поэтому вы можете использовать интерполяцию строк, чтобы обойти функцию scss.
Пример (действует в sass 3.5.0+):
:root {
--color_rgb: 250, 250, 250;
--color_hsl: 250, 50%, 50%;
}
div {
/* This is valid CSS, but will fail in a scss compilation */
background-color: rgba(var(--color_rgb), 0.5);
/* This is valid scss, and will generate the CSS above */
background-color: #{'rgba(var(--color_rgb), 0.5)'};
}
<div></div>
Обратите внимание, что интерполяция строк не будет работать для не-CSS-функций scss, таких как lighten()
потому что полученный код не будет функциональным CSS. Это все равно будет действительным scss, так что вы не получите ошибки при компиляции.
Я был в аналогичной ситуации, но, к сожалению, данные решения не сработали для меня, так как переменные могут быть любыми из rgb
к hsl
к hex
или даже названия цветов.
Я решил эту проблему сейчас, применивbackground-color
и opacity
к псевдо :after
или :before
элемент:
.container {
position: relative;
}
.container:before {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 0;
background-color: var(--color);
opacity: 0.3;
}
Возможно, придется немного изменить стили, в зависимости от того, к какому элементу следует применить фон.
Также это может работать не во всех ситуациях, но, надеюсь, помогает в некоторых случаях, когда другие решения не могут быть использованы.
Изменить: я только что заметил, что это решение, очевидно, также влияет на цвет текста, поскольку оно создает элемент перед целевым элементом и применяет к нему прозрачный цвет фона.
В некоторых случаях это может быть проблемой.
Вы можете рассмотретьcolor-mix()
и смешайте свой цвет с прозрачным:
SCSS / SASS
Преимущество: вы можете просто использовать шестнадцатеричные значения цвета вместо 8 бит для каждого канала (0-255).
Вот как я сделал это с первоначальной идеей: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables
Изменить: вы также можете изменить альфа-функцию, чтобы просто использовать#{$color-name}-rgb
и опустите сгенерированные переменные CSS *-r, *-g, *-b.
Результат
body {
--main-color: rgb(170, 68, 204);
--main-color-rgb: 170,68,204;
--main-color-r: 170;
--main-color-g: 68;
--main-color-b: 204;
}
.button-test {
// Generated from the alpha function
color: rgba(var(--main-color-r), var(--main-color-g), var(--main-color-b), 0.5);
// OR (you wrote this yourself, see usage)
color: rgba(var(--main-color-rgb), 0.5);
}
Применение:
body {
@include defineColorRGB(--main-color, #aa44cc);
}
.button-test {
// With alpha function:
color: alpha(var(--main-color), 0.5);
// OR just using the generated variable directly
color: rgba(var(--main-color-rgb), 0.5);
}
Mixin и функции
@mixin defineColorRGB($color-name, $value) {
$red: red($value);
$green: green($value);
$blue: blue($value);
#{$color-name}: unquote("rgb(#{$red}, #{$green}, #{$blue})");
#{$color-name}-rgb: $red,$green,$blue;
#{$color-name}-r: $red;
#{$color-name}-g: $green;
#{$color-name}-b: $blue;
}
// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
@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 alpha($color, $opacity) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-r: var(#{$color+'-r'});
$color-g: var(#{$color+'-g'});
$color-b: var(#{$color+'-b'});
@return rgba($color-r, $color-g, $color-b, $opacity);
}
Надеюсь, это кому-то сэкономит время.
Если вы используете темный и светлый режим, я использую этот образец. Я предпочитаю разделять цвета и назначать переменные цветов rgb. Поэтому я использую по два на каждый цикл. Я понимаю, что это решение не сухой код. Если вы хотите высушить код, можете использовать один цикл.
$colors-light: (
white: #fff,
black: #0c0d0e,
orange: #f48024,
green: #5eba7d,
blue: #0077cc,
red: #d1383d,
red-100: #e2474c,
red-200: red,
);
$colors-dark: (
black: #fff,
white: #2d2d2d,
orange: #dd7118,
green: #5eba7d,
blue: #0077cc,
red: #aa1c21,
red-100: #c9292e,
red-200: red,
);
@function hexToRGB($hex) {
@return red($hex), green($hex), blue($hex);
}
@mixin generate_colors($colors) {
// Colors
@each $color, $value in $colors {
@if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
} @else {
--#{$color}: var(--#{$value});
}
}
// RGB Colors
@each $color, $value in $colors {
@if str-slice(#{$value}, 1, 1) == "#" {
--RGB_#{$color}: #{hexToRGB($value)};
} @else {
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
:root {
@include generate_colors($colors-light);
}
[data-theme="dark"] {
@include generate_colors($colors-dark);
}
сухой код
@mixin generate_colors($colors) {
// Colors, RGB Colors
@each $color, $value in $colors {
@if str-slice(#{$value}, 1, 1) == "#" {
--#{$color}: #{$value};
--RGB_#{$color}: #{hexToRGB($value)};
} @else {
--#{$color}: var(--#{$value});
--RGB_#{$color}: var(--RGB_#{$value});
}
}
}
css Вывод
:root {
--white: #fff;
--RGB_white: 255, 255, 255;
--black: #0c0d0e;
--RGB_black: 12, 13, 14;
--orange: #f48024;
--RGB_orange: 244, 128, 36;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #d1383d;
--RGB_red: 209, 56, 61;
--red-100: #e2474c;
--RGB_red-100: 226, 71, 76;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
[data-theme="dark"] {
--black: #fff;
--RGB_black: 255, 255, 255;
--white: #2d2d2d;
--RGB_white: 45, 45, 45;
--orange: #dd7118;
--RGB_orange: 221, 113, 24;
--green: #5eba7d;
--RGB_green: 94, 186, 125;
--blue: #0077cc;
--RGB_blue: 0, 119, 204;
--red: #aa1c21;
--RGB_red: 170, 28, 33;
--red-100: #c9292e;
--RGB_red-100: 201, 41, 46;
--red-200: var(--red);
--RGB_red-200: var(--RGB_red);
}
body {
background-color: var(--white);
}
.colors {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin: 50px 0 0 30px;
}
.box {
width: 100px;
height: 100px;
margin-right: 5px;
}
.black {
background-color: var(--black);
}
.white {
background-color: var(--white);
}
.orange {
background-color: var(--orange);
}
.green {
background-color: var(--green);
}
.blue {
background-color: var(--blue);
}
.red {
background-color: var(--red);
}
.red-200 {
background-color: var(--red-200);
}
.black-rgba {
background-color: rgba(var(--RGB_black), 0.5);
}
.white-rgba {
background-color: rgba(var(--RGB_white), 0.5);
}
.orange-rgba {
background-color: rgba(var(--RGB_orange), 0.5);
}
.green-rgba {
background-color: rgba(var(--RGB_green), 0.5);
}
.blue-rgba {
background-color: rgba(var(--RGB_blue), 0.5);
}
.red-rgba {
background-color: rgba(var(--RGB_red), 0.5);
}
.red-rgba-200 {
background-color: rgba(var(--RGB_red-200), 0.5);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div>
<input type="checkbox" id="dark-switch" name="theme" />
<label for="dark-switch">Dark / Light</label>
</div>
<div class="color-box">
<div class="colors">
<div class="box red-200"></div>
<div class="box black"></div>
<div class="box white"></div>
<div class="box orange"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box red"></div>
</div>
<br>
<h1>RGBA</h1>
<div class="colors">
<div class="box red-rgba-200"></div>
<div class="box black-rgba"></div>
<div class="box white-rgba"></div>
<div class="box orange-rgba"></div>
<div class="box green-rgba"></div>
<div class="box blue-rgba"></div>
<div class="box red-rgba"></div>
</div>
</div>
<script>
const dark_switch = document.getElementById("dark-switch");
dark_switch.addEventListener("change", (e) => {
e.target.checked
? document.documentElement.setAttribute("data-theme", "dark")
: document.documentElement.setAttribute("data-theme", "light");
});
</script>
</body>
</html>
ты можешь использовать
linear-gradient
взломать цвет:
background: linear-gradient(to bottom, var(--your-color) -1000%, var(--mixin-color), 1000%)
Это действительно возможно с CSS. Это немного грязно, и вам придется использовать градиенты. В качестве примера я кодировал небольшой фрагмент, обратите внимание, что для темного фона следует использовать непрозрачность черного цвета, а для светлого - белого.
:root {
--red: rgba(255, 0, 0, 1);
--white-low-opacity: rgba(255, 255, 255, .3);
--white-high-opacity: rgba(255, 255, 255, .7);
--black-low-opacity: rgba(0, 0, 0, .3);
--black-high-opacity: rgba(0, 0, 0, .7);
}
div {
width: 100px;
height: 100px;
margin: 10px;
}
.element1 {
background:
linear-gradient(var(--white-low-opacity), var(--white-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element2 {
background:
linear-gradient(var(--white-high-opacity), var(--white-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element3 {
background:
linear-gradient(var(--black-low-opacity), var(--black-low-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
.element4 {
background:
linear-gradient(var(--black-high-opacity), var(--black-high-opacity)) no-repeat,
linear-gradient(var(--red), var(--red)) no-repeat;
}
<div class="element1">hello world</div>
<div class="element2">hello world</div>
<div class="element3">hello world</div>
<div class="element4">hello world</div>
:root{
--color: 255, 0, 0;
}
#element{
background-color: rgba(var(--color), opacity);
}
где вы заменяете непрозрачность на что-нибудь между 0 и 1
Я попробовал перечисленные выше методы, но, к сожалению, ни один из них не сработал. Поскольку сейчас я использую sass (синтаксис scss), я решил использовать другой метод, в котором вместо помещения переменной в rgba я поместил ее в другую переменную с уже уменьшенной непрозрачностью.
:root {
--color-sass: hsla(331, 50%, 60%);
--color-sass-dimmed: hsla(331, 50%, 60%, 0.8);
}
Если вы хотите использовать свой основной цвет в формате HEX и использовать SCSS, попробуйте следующее:
$primary-transparentize-08: transparentize($primary, 0.8);
тогда
background-color: $primary-transparentize-08;
Просто хотел поделиться этим для тех, кто использует LESS
с Gulp
,
~
внутри LESS
гарантирует, что все, что вы вводите, интерпретируется и печатается буквально в конечном файле. Использование CSS внутри LESS
без ~
вызовет Gulp
выдать ошибку и предотвратить компиляцию вашего CSS. Следующие строки работают и скомпилированы без проблем.
:root {
--black: 0, 0, 0;
--alpha: 0.00;
}
.scrolled {
box-shadow: 0 2px 3px 0 ~'rgba('var(--black), var(--alpha)~')';
}
Используя scss вы можете сделать:
rgba(color($colors, colorVar), 0.5);
Причина, по которой это работает, заключается в том, что переменнаяcolor
возвращает значение0,125,250
в цвете RGBA. После рендеринга rgba возвращаетrgba(0,125,250,0.8)
Кажется, я нашел решение, которое меня устраивает.
Следующий код добавляет черный цвет фона с непрозрачностью 60 %:
background: color-mix(in lab, transparent 40%, black)
Думаю, вместо «черного» можно использовать любую переменную CSS.
Вы можете установить конкретную переменную / значение для каждого цвета - оригинал и тот с непрозрачностью:
:root {
--color: #F00;
--color-opacity: rgba(255, 0, 0, 0.5);
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color-opacity);
}
<div id="a1">asdf</div>
<div id="a2">asdf</div>
Если вы не можете использовать это, и вы в порядке с решением javascript, вы можете использовать это:
$(function() {
$('button').click(function() {
bgcolor = $('#a2').css('backgroundColor');
rgb_value = bgcolor.match(/\d+,\s?\d+,\s?\d+/)[0]
$('#a2').css('backgroundColor', 'rgba(' + rgb_value + ', 0.5)');
});
});
:root {
--color: #F00;
}
#a1 {
background: var(--color);
}
#a2 {
background: var(--color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1">asdf</div>
<div id="a2">asdf</div>
<button>Click to change opacity</button>
Если вы любите шестнадцатеричные цвета, как я, есть другое решение. Шестнадцатеричное значение составляет 6 цифр, после чего это альфа-значение. 00 - 100% прозрачность 99 - около 75%, затем он использует алфавит "a1-af", затем "b1-bf", заканчивающийся на "ff", который на 100% непрозрачен.
:root {
--color: #F00;
}
#element {
background: var(--color)f6;
}
Чтобы использовать rgba() с общей переменной css, попробуйте следующее:
- Объявите свой цвет внутри:root, но не используйте rgb(), как это делают другие ответы. просто напишите значение
:root{
--color : 255,0,0;
}
- Используйте переменную --color, используя var() в качестве других ответов
#some-element {
color : rgba(var(--color),0.5);
}
Пишу сюда первый раз..
Простое решение на JavaScript
Вот простая функция JavaScript, которая может добавить прозрачность именованным цветам цветов CSS, например'red'
Хотя .setFillColor() устарел, он все еще реализован в некоторых браузерах (blink и webkit). Если setFillColor() когда-либо будет полностью удален, надеюсь, к тому времени у нас будет синтаксис относительного цвета .
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
Использование с переменными CSS
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Add Transparency to a Color</title>
<style>
:root {
--color: lime;
--alpha: 0.5;
}
.test {
background-color: var(--color);
}
</style>
</head>
<body class='test'>
<script>
try{"use strict"
/* Use the getComputedStyle() method to get the current value of the CSS variable --color and the --alpha variable. */
const color = getComputedStyle(document.documentElement).getPropertyValue('--color')||'white'; //added fallback to color white
const alpha = getComputedStyle(document.documentElement).getPropertyValue('--alpha')||1; //added fallback to solid color value of 1
/* Call the addTransparency() function with the color and alpha values as arguments, and store the result in a variable. */
const transparentColor = addTransparency(color, alpha);
/* Use the setProperty() method of the CSSStyleDeclaration interface to set the value of the --color CSS variable to the value of the transparentColor variable. */
document.documentElement.style.setProperty('--color', transparentColor);
function addTransparency(color, alpha) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.setFillColor(color, alpha);
return ctx.fillStyle;
}
}catch(e){document.write(e);}
</script>
</body>
</html>
Ах, страница обновилась, и я потерял все, что набрал, опубликовав сохраненный черновик.
Я нашел простой обходной путь, но, признаюсь, не идеальный, используяfilter
.
определение:
:root {
--color: #f0f0f0;
}
переопределить:
#element {
background: var(--color);
filter: opacity(0.5);
}
В CSS вы можете использовать значения rgba:
#element {
background: rgba(240, 240, 240, 0.5);
}
или просто установите непрозрачность:
#element {
background: #f0f0f0;
opacity: 0.5;
}