如何对CSS颜色变量应用不透明度?

时间:2022-11-21 20:30:24

I am designing an app in electron, so I have access to CSS variables. I have defined a color variable in vars.css:

我正在设计一个电子应用程序,所以我可以访问CSS变量。我在var .css中定义了一个颜色变量:

:root {
  --color: #f0f0f0;
}

I want to use this color in main.css, but with some opacity applied:

我想用这个颜色为主色。css,但使用一些不透明:

#element {
  background: (somehow use var(--color) at some opacity);
}

How would I go about doing this? I am not using any preprocesser, only CSS. I would prefer an all-CSS answer, but I will accept JavaScript/jQuery.

我该怎么做呢?我不使用任何预处理程序,只使用CSS。我更喜欢全css的答案,但我会接受JavaScript/jQuery。

I cannot use opacity because I am using a background image that should not be transparent.

我不能使用不透明度,因为我使用的背景图像不应该是透明的。

6 个解决方案

#1


51  

You can't take an existing color value and apply an alpha channel to it. Namely, you can't take an existing hex value such as #f0f0f0, give it an alpha component and use the resulting value with another property.

您不能使用现有的颜色值并对其应用alpha通道。换句话说,您不能取一个现有的十六进制值,比如# f0f0f0f0,给它一个alpha组件,然后将结果值与另一个属性一起使用。

However, custom properties allow you to convert your hex value into an RGB triplet for use with rgba(), store that value in the custom property (including the commas!), substitute that value using var() into an rgba() function with your desired alpha value, and it'll just work:

但是,自定义属性允许您将十六进制值转换为RGB三元组,以便与rgba()一起使用,将该值存储在自定义属性(包括逗号!)中,使用var()将该值替换为rgba()函数,并使用所需的alpha值,它就会工作:

: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>

This seems almost too good to be true.1 How does it work?

这似乎好得令人难以置信。它是如何工作的?

The magic lies in the fact that the values of custom properties are substituted as is when replacing var() references in a property value, before that property's value is computed. This means that as far as custom properties are concerned, the value of --color in your example isn't a color value at all until a var(--color) expression appears somewhere that expects a color value (and only in that context). From section 2.1 of the css-variables spec:

其神奇之处在于,在计算属性值之前,自定义属性的值被替换为替换属性值中的var()引用。这意味着,就自定义属性而言,在出现一个需要颜色值的var(—color)表达式之前,您的示例中的-color的值根本不是颜色值(而且仅在该上下文中)。从css-variables规范第2.1节中:

The allowed syntax for custom properties is extremely permissive. The <declaration-value> production matches any sequence of one or more tokens, so long as the sequence does not contain <bad-string-token>, <bad-url-token>, unmatched <)-token>, <]-token>, or <}-token>, or top-level <semicolon-token> tokens or <delim-token> tokens with a value of "!".

允许的自定义属性语法是非常允许的。< declare -value>生成匹配一个或多个令牌的任何序列,只要该序列不包含 、unmatched <)-token>、<]-token>或<}-token>,或* <分号令牌> 令牌或< delim-_value >令牌" 令牌>

For example, the following is a valid custom property:

例如,以下是一个有效的自定义属性:

--foo: if(x > 5) this.width = 10;

While this value is obviously useless as a variable, as it would be invalid in any normal property, it might be read and acted on by JavaScript.

虽然这个值作为变量显然是无用的,因为它在任何普通属性中都是无效的,但是它可能被JavaScript读取并执行。

And section 3:

第三节:

If a property contains one or more var() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after var() functions have been substituted.

如果一个属性包含一个或多个var()函数,并且这些函数在语法上是有效的,那么必须假定整个属性的语法在解析时是有效的。它只在计算值时进行语法检查,在替换var()函数之后。

This means that the 240, 240, 240 value you see above gets substituted directly into the rgba() function before the declaration is computed. So this:

这意味着在计算声明之前,您上面看到的240、240、240的值将被直接替换到rgba()函数中。所以这个:

#element {
  background-color: rgba(var(--color), 0.5);
}

which doesn't appear to be valid CSS at first because rgba() expects no less than four comma-separated numeric values, becomes this:

首先,由于rgba()期望不少于四个逗号分隔的数值,所以它看起来不是有效的CSS:

#element {
  background-color: rgba(240, 240, 240, 0.5);
}

which, of course, is perfectly valid CSS.

当然,这是完全有效的CSS。

Taking it one step further, you can store the alpha component in its own custom property:

更进一步,您可以将alpha组件存储在它自己的自定义属性中:

:root {
  --color: 240, 240, 240;
  --alpha: 0.5;
}

and substitute it, with the same result:

代入,得到相同的结果:

#element {
  background-color: rgba(var(--color), var(--alpha));
}

This allows you to have different alpha values that you can swap around on-the-fly.

这允许你有不同的alpha值,你可以随时交换。


1Well, it is, if you're running the code snippet in a browser that doesn't support custom properties.

如果你在一个不支持自定义属性的浏览器中运行代码片段,那么它就是。

#2


3  

I know the OP isn't using a preprocessor, but I would have been helped if the following information was part of the answer here (I can't comment yet, otherwise I would have commented @BoltClock answer.

我知道OP没有使用预处理器,但是如果下面的信息是答案的一部分(我还不能评论,否则我将注释@BoltClock答案。

If you are using, e.g. scss, the answer above will fail, because scss attempts to compile the styles with a scss-specific rgba()/hsla() function, which requires 4 parameters. However, rgba()/hsla() are also native css functions, so you can use string interpolation to bypass the scss function.

如果您正在使用scss,那么上面的答案将会失败,因为scss试图使用scss特有的rgba()/hsla()函数来编译样式,这需要4个参数。然而,rgba()/hsla()也是本地css函数,因此可以使用字符串插值绕过scss函数。

Example (valid in sass 3.5.0+):

示例(在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>

Note that string interpolation will not work for non-CSS scss functions, such as lighten(), because the resulting code would not be functional CSS. It would still be valid scss though, so you would receive no error in compilation.

注意,字符串插补对于非CSS scss函数(如点亮())不起作用,因为生成的代码不是功能CSS。但是它仍然是有效的scss,所以您在编译时不会收到错误。

#3


1  

This is indeed possible with CSS. It's just a bit dirty, and you'll have to use gradients. I've coded a small snippet as example, take note that for dark backgrounds, you should use the black opacity, as for light- the white ones.:

这确实可以通过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>

#4


0  

In CSS you should be able to either use rgba values:

在CSS中,您应该能够使用rgba值:

#element {
  background: rgba(240, 240, 240, 0.5);
}

or just set the opacity:

或者设置不透明度:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}

#5


0  

You can set specific variable/value for each color - the original and the one with opacity:

您可以为每个颜色设置特定的变量/值——原始颜色和不透明颜色:

: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>

If you can't use this and you are ok with javascript solution, you can use this one:

如果你不能使用这个,你可以使用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


0  

:root{
--color: 255, 0, 0;
}

#element{
    background-color: rgba(var(--color), opacity);
}

where you replace opacity with anything between 0 and 1

在0和1之间替换不透明度?

#1


51  

You can't take an existing color value and apply an alpha channel to it. Namely, you can't take an existing hex value such as #f0f0f0, give it an alpha component and use the resulting value with another property.

您不能使用现有的颜色值并对其应用alpha通道。换句话说,您不能取一个现有的十六进制值,比如# f0f0f0f0,给它一个alpha组件,然后将结果值与另一个属性一起使用。

However, custom properties allow you to convert your hex value into an RGB triplet for use with rgba(), store that value in the custom property (including the commas!), substitute that value using var() into an rgba() function with your desired alpha value, and it'll just work:

但是,自定义属性允许您将十六进制值转换为RGB三元组,以便与rgba()一起使用,将该值存储在自定义属性(包括逗号!)中,使用var()将该值替换为rgba()函数,并使用所需的alpha值,它就会工作:

: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>

This seems almost too good to be true.1 How does it work?

这似乎好得令人难以置信。它是如何工作的?

The magic lies in the fact that the values of custom properties are substituted as is when replacing var() references in a property value, before that property's value is computed. This means that as far as custom properties are concerned, the value of --color in your example isn't a color value at all until a var(--color) expression appears somewhere that expects a color value (and only in that context). From section 2.1 of the css-variables spec:

其神奇之处在于,在计算属性值之前,自定义属性的值被替换为替换属性值中的var()引用。这意味着,就自定义属性而言,在出现一个需要颜色值的var(—color)表达式之前,您的示例中的-color的值根本不是颜色值(而且仅在该上下文中)。从css-variables规范第2.1节中:

The allowed syntax for custom properties is extremely permissive. The <declaration-value> production matches any sequence of one or more tokens, so long as the sequence does not contain <bad-string-token>, <bad-url-token>, unmatched <)-token>, <]-token>, or <}-token>, or top-level <semicolon-token> tokens or <delim-token> tokens with a value of "!".

允许的自定义属性语法是非常允许的。< declare -value>生成匹配一个或多个令牌的任何序列,只要该序列不包含 、unmatched <)-token>、<]-token>或<}-token>,或* <分号令牌> 令牌或< delim-_value >令牌" 令牌>

For example, the following is a valid custom property:

例如,以下是一个有效的自定义属性:

--foo: if(x > 5) this.width = 10;

While this value is obviously useless as a variable, as it would be invalid in any normal property, it might be read and acted on by JavaScript.

虽然这个值作为变量显然是无用的,因为它在任何普通属性中都是无效的,但是它可能被JavaScript读取并执行。

And section 3:

第三节:

If a property contains one or more var() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after var() functions have been substituted.

如果一个属性包含一个或多个var()函数,并且这些函数在语法上是有效的,那么必须假定整个属性的语法在解析时是有效的。它只在计算值时进行语法检查,在替换var()函数之后。

This means that the 240, 240, 240 value you see above gets substituted directly into the rgba() function before the declaration is computed. So this:

这意味着在计算声明之前,您上面看到的240、240、240的值将被直接替换到rgba()函数中。所以这个:

#element {
  background-color: rgba(var(--color), 0.5);
}

which doesn't appear to be valid CSS at first because rgba() expects no less than four comma-separated numeric values, becomes this:

首先,由于rgba()期望不少于四个逗号分隔的数值,所以它看起来不是有效的CSS:

#element {
  background-color: rgba(240, 240, 240, 0.5);
}

which, of course, is perfectly valid CSS.

当然,这是完全有效的CSS。

Taking it one step further, you can store the alpha component in its own custom property:

更进一步,您可以将alpha组件存储在它自己的自定义属性中:

:root {
  --color: 240, 240, 240;
  --alpha: 0.5;
}

and substitute it, with the same result:

代入,得到相同的结果:

#element {
  background-color: rgba(var(--color), var(--alpha));
}

This allows you to have different alpha values that you can swap around on-the-fly.

这允许你有不同的alpha值,你可以随时交换。


1Well, it is, if you're running the code snippet in a browser that doesn't support custom properties.

如果你在一个不支持自定义属性的浏览器中运行代码片段,那么它就是。

#2


3  

I know the OP isn't using a preprocessor, but I would have been helped if the following information was part of the answer here (I can't comment yet, otherwise I would have commented @BoltClock answer.

我知道OP没有使用预处理器,但是如果下面的信息是答案的一部分(我还不能评论,否则我将注释@BoltClock答案。

If you are using, e.g. scss, the answer above will fail, because scss attempts to compile the styles with a scss-specific rgba()/hsla() function, which requires 4 parameters. However, rgba()/hsla() are also native css functions, so you can use string interpolation to bypass the scss function.

如果您正在使用scss,那么上面的答案将会失败,因为scss试图使用scss特有的rgba()/hsla()函数来编译样式,这需要4个参数。然而,rgba()/hsla()也是本地css函数,因此可以使用字符串插值绕过scss函数。

Example (valid in sass 3.5.0+):

示例(在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>

Note that string interpolation will not work for non-CSS scss functions, such as lighten(), because the resulting code would not be functional CSS. It would still be valid scss though, so you would receive no error in compilation.

注意,字符串插补对于非CSS scss函数(如点亮())不起作用,因为生成的代码不是功能CSS。但是它仍然是有效的scss,所以您在编译时不会收到错误。

#3


1  

This is indeed possible with CSS. It's just a bit dirty, and you'll have to use gradients. I've coded a small snippet as example, take note that for dark backgrounds, you should use the black opacity, as for light- the white ones.:

这确实可以通过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>

#4


0  

In CSS you should be able to either use rgba values:

在CSS中,您应该能够使用rgba值:

#element {
  background: rgba(240, 240, 240, 0.5);
}

or just set the opacity:

或者设置不透明度:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}

#5


0  

You can set specific variable/value for each color - the original and the one with opacity:

您可以为每个颜色设置特定的变量/值——原始颜色和不透明颜色:

: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>

If you can't use this and you are ok with javascript solution, you can use this one:

如果你不能使用这个,你可以使用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


0  

:root{
--color: 255, 0, 0;
}

#element{
    background-color: rgba(var(--color), opacity);
}

where you replace opacity with anything between 0 and 1

在0和1之间替换不透明度?