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

Posted

技术标签:

【中文标题】如何将不透明度应用于 CSS 颜色变量?【英文标题】:How do I apply opacity to a CSS color variable? 【发布时间】:2017-02-21 23:07:33 【问题描述】:

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

:root 
  --color: #f0f0f0;

我想在main.css 中使用这种颜色,但应用了一些不透明度:

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

我该怎么做呢?我没有使用任何预处理器,只有 CSS。我更喜欢全 CSS 的答案,但我会接受 javascript/jQuery。

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

【问题讨论】:

听起来你应该使用多个元素.... 我不想这样做,但似乎我可能不得不... :( 啊啊啊啊!!!!!!这太烦人了!现在快2020年了。颜色选择器获取#hex 颜色。 alpha / rgba 在 Sass/Stylus 中不起作用 - 因为它不是 rgb 值。我应该在我的 CMS 中为每种颜色放置 4 个滑块吗? 【参考方案1】:

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

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

或者只是设置不透明度:

#element 
  background: #f0f0f0;
  opacity: 0.5;    

【讨论】:

我无法硬编码 rgba 值,我正在使用颜色变量。我应该提到我不能使用不透明度,因为我将有一个不应该是透明的背景图像。 如果您只希望 BG 具有透明度但整个元素具有不透明度,那么这不是一个解决方案 b/c,那么为所有内容添加不透明度是没有帮助的。【参考方案2】:

您可以为每种颜色设置特定的变量/值 - 原始颜色和具有不透明度的颜色:

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

【讨论】:

不透明度值会发生变化,因此为每个不透明度创建一个变量会很烦人。【参考方案3】:

确实可以通过 CSS 实现。它只是有点脏,你必须使用渐变。我编写了一个小的 sn-p 作为示例,请注意,对于深色背景,您应该使用黑色不透明度,对于浅色 - 白色的。:

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

【讨论】:

您不需要指定背景大小 - 渐变没有固有大小,因此会自动拉伸。 @BoltClock 是的,当我发布它时,我真的想到了,这只是在代码笔中玩耍;)。现在清理了,谢谢! 这很聪明,当我去年回答similar question 时,我没有想到将纯色渐变层叠在一起。无论如何,这个问题的编写方式可能更笼统,我回答的是一个非常具体的用例。 当背景不同时它实际上不起作用,我现在假设在应用“不透明度”时是白色背景 (255,255,255)。它可能默认为 OP 的主要背景颜色。但话又说回来,白色背景可能适合大多数较浅颜色的需求,以至于人们不会注意到这一点。 我刚刚发现了一些非常不可思议的东西。我现在已经发布了答案。【参考方案4】:

您不能采用现有的颜色值并将 Alpha 通道应用到它。也就是说,您不能将现有的十六进制值(例如 #f0f0f0)赋予它一个 alpha 分量并将结果值与另一个属性一起使用。

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

:root 
  /* #f0f0f0 in decimal RGB */
  --color: 240, 240, 240;


body 
  color: #000;
  background-color: #000;


#element 
  background-color: rgba(var(--color), 0.8);
&lt;p id="element"&gt;If you can see this, your browser supports custom properties.&lt;/p&gt;

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

神奇之处在于,当替换属性值中的var() 引用时,按原样替换自定义属性的值,在计算该属性值之前 .这意味着就自定义属性而言,您示例中的--color 的值根本不是颜色值直到var(--color) 表达式出现在某个需要颜色值的地方(并且仅在这种情况下)。来自 css-variables 规范的 section 2.1:

自定义属性允许的语法非常宽松。 产生式匹配一个或多个令牌的任何序列,只要该序列不包含 、不匹配的 、 或 或*** 令牌或 具有“!”值的令牌。

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

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

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

还有section 3:

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

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

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

起初看起来不是有效的 CSS,因为 rgba() 需要不少于四个逗号分隔的数值,变成这样:

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

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

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

:root 
  --color: 240, 240, 240;
  --alpha: 0.8;

并替换它,结果相同:

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

这允许您拥有不同的 alpha 值,您可以随时交换它们。


1好吧,如果你在不支持自定义属性的浏览器中运行代码 sn-p。

【讨论】:

这很漂亮 @Roberrrt:事实上,正如我之前发布的these answers 那样,我应该早早意识到这一点。 很遗憾,"240, 240, 240" 的值无法使用颜色选择器进行编辑。当您需要为您的 GUI 找到正确的颜色时,这是一个巨大的失误。 @s3c 语法var(--hex-color)99 被转换为两个标记#333333 99(注意分隔标记的空间),这显然不是你想要的。自定义属性最初被定义为复制标记,而不是字符串,这是最终结果。现在解决这个问题为时已晚。 @s3c:好消息是 CSS Color 5 引入了一些很酷的新函数来操作现有的十六进制值,包括更改它们的 alpha 通道:drafts.csswg.org/css-color-5/#colormodify【参考方案5】:
:root
--color: 255, 0, 0;


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

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

【讨论】:

这是在尝试回答问题吗?因为如果是这样,代码就没有意义了。特别是rgba(var(--color), opacity) 位。特别是因为您的自定义属性值是整个 rgb() 符号。但也因为“不透明”关键字。 糟糕,rgb 部分不应该在 var 中【参考方案6】:

我知道 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)';
&lt;div&gt;&lt;/div&gt;

请注意,字符串插值不适用于非 CSS scss 函数,例如 lighten(),因为生成的代码不会是函数式 CSS。不过它仍然是有效的 scss,因此您在编译时不会收到任何错误。

【讨论】:

如果您更喜欢在您的 Sass .scss 文件中使用原生 CSS 颜色函数,您可以在文件顶部包含以下函数定义以覆盖 Sass 的处理并使其通过:@987654325 @@function rgba($args...) @return #'rgba(#$args)'; @function hsl($args...) @return #'hsl(#$args)'; @function hsla($args...) @return #'hsla(#$args)'; ```` rgbargb 的同义词已经有一段时间了。因此你可以去掉“a”。 scss 文件的另一种解决方法是使用大写字母 (RGB),然后被 sass 忽略。例如:color: RGB(var(--color_rgb), 0.5);。来自GitHub 不错的答案!如果您已经定义了十六进制颜色,您只需添加以下代码即可将其转换为自定义 rgb 属性::root @each $color, $value in $colors --#$color_rgb: #red($value), green($value), blue($value); 在 npm 上使用最新的 sass 包,这种解决方法似乎不再需要【参考方案7】:

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

:root 
--color: #F00;


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

【讨论】:

不幸的是,我认为这行不通。 8 位十六进制代码支持开始普及,但看起来与接受的答案一起使用的技巧不适用于他们。示例:jsbin.com/nacuharige/edit?css,output 这行不通,但如果可以的话,这将是一个很好的解决方案。 截至我发帖时,现在近 94% 的当前使用的浏览器都可以使用此功能 [caniuse.com/css-rrggbbaa].我已经走这条路了,因为我所有的颜色变量都已经保存为 HEX 值,所以添加额外的 2 个字符来指示 alpha 是完美的解决方案。 @Rillus,您能提供工作示例吗?似乎不支持这种结构。 我现在意识到我的实现与这张海报使用的不匹配,并且 CSS 变量连接即 var(--color)f6 不起作用(在这种情况下产生的值是 #f0f0f0 f6,它是无效的)。我的成功工作结果是使用 Vue3 并引用 js 导入的颜色属性,例如:`background-color: v-bind(this.colourHex + 'f6');` 为混淆道歉。【参考方案8】:

我遇到了类似的情况,但不幸的是,给定的解决方案对我不起作用,因为变量可以是从 rgbhslhex 的任何东西,甚至是颜色名称。 我现在解决了这个问题,将background-coloropacity 应用于伪:after:before 元素:

.container 
    position: relative;


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

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

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

【讨论】:

这不仅具有允许更灵活地指定颜色的优点(例如,名称,或rgbHSL),而且还避免了原生 CSS 颜色函数和 Sass 的颜色之间的任何冲突职能。请参阅下面的SimplyPhy's answer。 我认为最好使用:before,这样您就可以在不使用z-index 的情况下获得正确的堆叠顺序。【参考方案9】:

要使用带有通用 css 变量的 rgba(),试试这个:

    在 :root 中声明你的颜色,但不要像其他答案那样使用 rgb()。只写值

:root
  --color : 255,0,0;
  
    使用 --color 变量使用 var() 作为其他答案

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

【讨论】:

【参考方案10】:

SCSS / SASS

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

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

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


结果

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

希望这可以节省一些时间。

【讨论】:

【参考方案11】:

如果您使用深色和浅色模式,我使用此示例。我更喜欢将颜色和 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>

【讨论】:

这是一篇令人难以置信的帖子!感谢所有这些代码。我基本上把它全部复制到我自己的项目中。对于任何来这里遇到问题的人,我确实必须改变一件事。最初声明 SASS 颜色变量时,您需要在名称周围加上引号,如下所示:$colors-light: ( 'color-primary': #2F302F, 'color-primary-variant': #4E4E4E,【参考方案12】:

您可以使用linear-gradient 破解颜色:

background: linear-gradient(to bottom, var(--your-color) -1000%, var(--mixin-color), 1000%)

$(() => 
  const setOpacity = () => 
    $('#canvas').css('--opacity', $('#opacity-value').val())
  
  const setColor = () => 
    $('#canvas').css('--color', $('#color-value').val());
  
  $('#opacity-value').on('input', setOpacity);
  $('#color-value').on('input', setColor);
  setOpacity();
  setColor();
)
#canvas 
  width: 100px;
  height: 100px;
  border: 2px solid #000;
  --hack: 10000%;
  background: linear-gradient( to bottom, var(--color) calc((var(--opacity) - 1) * var(--hack)), transparent calc(var(--opacity) * var(--hack)));


#container 
  background-image: linear-gradient(45deg, #b0b0b0 25%, transparent 25%), linear-gradient(-45deg, #b0b0b0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #b0b0b0 75%), linear-gradient(-45deg, transparent 75%, #b0b0b0 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
  padding: 10px;
  display: inline-block;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="container">
  <div id="canvas"></div>
</div>
<hr/>
<input type="range" id="opacity-value" min="0" max="1" step="0.1" value="0.5" />
<input type="color" id="color-value" />

【讨论】:

【参考方案13】:

如果您想使用 HEX 格式的原色并使用 SCSS,请尝试以下操作:

$primary-transparentize-08: transparentize($primary, 0.8);

然后

background-color: $primary-transparentize-08;

【讨论】:

这是 SCSS 变量,不适用于 CSS 变量

以上是关于如何将不透明度应用于 CSS 颜色变量?的主要内容,如果未能解决你的问题,请参考以下文章

理解CSS前景色和透明度

css中关于字体颜色的设置

如何将 alpha 值添加到 css 中的变量?

将不透明度设置为滑动标签布局?

如何设置Android中控件的颜色透明度

CSS3颜色不透明度如何设置?