324

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

:root {
  --color: #f0f0f0;
}

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

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

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

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

4

13 回答 13

501

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

但是,自定义属性允许您将十六进制值转换为 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.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>

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

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

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

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

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

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

第 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 好吧,如果您在不支持自定义属性的浏览器中运行代码片段。

于 2016-12-21T14:38:58.953 回答
37

我知道 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,因此您在编译时不会收到任何错误。

于 2017-12-04T02:17:17.467 回答
28

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

.container {
    position: relative;
}

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

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

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

于 2019-07-09T11:32:23.943 回答
7

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 和函数

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

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

于 2019-11-01T16:12:58.287 回答
6

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

于 2020-11-16T18:45:04.077 回答
5

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

于 2016-12-21T13:48:42.337 回答
3

相对颜色语法

有了这个允许颜色格式转换的新 CSS 功能(css-color-5),它还允许为任何格式的任何颜色添加不透明度,例如RGB(可以对任何其他格式进行相对转换):

html { --color: blue }
.with-opacity { background: rgb(from var(--color) r g b / 50%) }

(在撰写本文时,尚未在浏览器中可用。将在到达后更新)

于 2022-02-13T08:05:22.143 回答
2

你可以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" />

于 2021-05-31T04:02:15.310 回答
0
:root{
--color: 255, 0, 0;
}

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

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

于 2016-12-22T13:13:24.867 回答
-1

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

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

于 2016-10-13T00:59:23.287 回答
-4

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

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

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

  1. 使用 --color 变量使用 var() 作为其他答案

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

于 2019-08-07T05:03:01.817 回答
-4

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

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}
于 2018-08-24T16:20:32.720 回答
-9

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

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

或者只是设置不透明度:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}
于 2016-10-13T00:55:45.610 回答