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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40010597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 12:12:06  来源:igfitidea点击:

How do I apply opacity to a CSS color variable?

csscolorscss-variables

提问by JoshyRobot

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

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

:root {
  --color: #f0f0f0;
}

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

我想在 中使用这种颜色main.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 opacitybecause I am using a background image that should not be transparent.

我无法使用,opacity因为我使用的背景图像不应该是透明的。

回答by BoltClock

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 通道。也就是说,您不能采用现有的十六进制值,例如#f0f0f0,给它一个 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(),将该值存储在自定义属性中(包括逗号!),将该值 using 替换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.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>

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

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

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

神奇之处在于,在计算属性值之前,自定义属性的值在替换属性值中的引用时按原样替换。这意味着,只要自定义属性而言,价值在你的例子是不是在所有的颜色值,直到一个表达式出现的地方,需要一个颜色值(也只有在这种情况下)。来自css-variables 规范的第 2.1 节var()--colorvar(--color)

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 "!".

自定义属性允许的语法非常宽松。<declaration-value> 产生式匹配一个或多个标记的任何序列,只要该序列不包含 <bad-string-token>、<bad-url-token>、不匹配的 <)-token>、<]- token> 或 <}-token> 或顶级 <semicolon-token> 标记或 <delim-token> 值为“!”的标记。

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.

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

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

虽然这个值作为变量显然没有用,因为它在任何普通属性中都是无效的,它可能会被 JavaScript 读取和操作。

And section 3:

第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, 240value you see above gets substituted directly into the rgba()function beforethe declaration is computed. So this:

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

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

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

起初似乎不是有效的 CSS,因为rgba()期望不少于四个逗号分隔的数值,变成这样:

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

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.8;
}

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.

1好吧,如果您在不支持自定义属性的浏览器中运行代码片段。

回答by SimplyPhy

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 函数,例如lighten(),因为生成的代码不是功能性 CSS。尽管如此,它仍然是有效的 scss,因此您在编译时不会收到任何错误。

回答by Springrbua

I was in a similar situation, but unfortunately the given solutions did not work for me, as the variables could be anything from rgbto hslto hexor even color names.
I solved this issue now, by applying the background-colorand the opacityto a pseudo :afteror :beforeelement:

我处于类似的情况,但不幸的是,给定的解决方案对我不起作用,因为变量可以是从rgbtohsl到 tohex甚至颜色名称的任何内容。
我现在解决了这个问题,通过将 thebackground-color和 theopacity应用于伪:after:before元素:

.container {
    position: relative;
}

.container:before {
    content: "";
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    background-color: var(--color);
    opacity: 0.3;
}

The styles might need to be changed a little, depending on the element the background should be applied to.
Also it might not work for all situations, but hopefully it helps in some cases, where the other solutions can't be used.

样式可能需要稍作更改,具体取决于应应用背景的元素。
此外,它可能不适用于所有情况,但希望它在某些情况下有所帮助,而其他解决方案无法使用。

Edit:I just noticed, that this solution obviously also impacts the text color, as it creates an element in front of the target element and applies a transparent background color to it.
This might be a problem in some cases.

编辑:我刚刚注意到,此解决方案显然也会影响文本颜色,因为它会在目标元素前面创建一个元素并对其应用透明背景色。
在某些情况下,这可能是一个问题。

回答by roberrrt-s

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>

回答by Pizza lord

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

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

where you replace opacity with anything between 0 and 1

用 0 到 1 之间的任何值替换不透明度

回答by Stefan Rein

SCSS / SASS

SCSS / SASS

Advantage:You can just use Hex color values, instead to use the 8 Bit for every channel (0-255).

优点:您可以只使用十六进制颜色值,而不是为每个通道(0-255)使用 8 位。

This is how I did it with the initial idea of: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

这就是我最初的想法:https: //codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

Edit:You could also modify the alpha function to just use #{$color-name}-rgband omit the generated *-r, *-g, *-b CSS variables.

编辑:您还可以修改 alpha 函数以仅使用#{$color-name}-rgb和省略生成的 *-r、*-g、*-b CSS 变量。



Result

结果

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);
}

Usage:

用法:

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 and functions

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);
}

Hopefully this will save someone some time.

希望这会为某人节省一些时间。

回答by Dekel

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>

回答by Dani Fadli

For using rgba() with general css variable, try this:

要将 rgba() 与通用 css 变量一起使用,请尝试以下操作:

  1. Declare your color inside :root, but don't use rgb() as other answers do. just write the value
  1. 在 :root 中声明您的颜色,但不要像其他答案那样使用 rgb()。只写值

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

  1. Use --color variable using var() as other answers
  1. 使用 --color 变量使用 var() 作为其他答案

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

回答by Patrick H.

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;    
}

回答by Seth M

If you love hex colors like me there is another solution. The hex value is 6 digits after that is the alpha value. 00 is 100% transparency 99 is about 75% then it uses the alphabet 'a1-af' then 'b1-bf' ending with 'ff' which is 100% opaque.

如果你像我一样喜欢十六进制颜色,还有另一种解决方案。十六进制值为 6 位,之后是 alpha 值。00 是 100% 透明度 99 是大约 75% 然后它使用字母表 'a1-af' 然后'b1-bf' 以 'ff' 结尾,这是 100% 不透明。

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}