ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在设计一个电子应用程序,所以我可以访问 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 个滑块吗?

C
Community

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

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

:root { /* #f0f0f0 十进制 RGB */ --color: 240, 240, 240; } 身体 { 颜色: #000;背景颜色:#000; } #element { 背景颜色:rgba(var(--color), 0.8); }

如果你能看到这个,你的浏览器支持自定义属性。

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

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

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

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


这很漂亮
遗憾的是,值 "240, 240, 240" 无法使用颜色选择器进行编辑。当您需要为您的 GUI 找到正确的颜色时,这是一个巨大的失误。
rgba() 现在是 rgb() 的同义词,因此您可以使用 color: rgb(var(--color), .4)。但我发现这个 SOQ 的原因是因为以下 工作::root { --hex-color: "#333333"; } element { background: var(--hex-color)99 /*this should be alpha 60%*/ },但不知何故,这两个字符串没有加入 #33333399,这将工作。
@s3c 语法 var(--hex-color)99 被转换为两个标记 #333333 99 (注意分隔标记的空间),这显然不是你想要的。自定义属性最初被定义为复制标记,而不是字符串,这是最终结果。现在解决这个问题为时已晚。
@s3c:好消息是 CSS Color 5 引入了一些很酷的新函数来操作现有的十六进制值,包括更改它们的 alpha 通道:drafts.csswg.org/css-color-5/#colormodify
S
SimplyPhy

我知道 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 { /* 这是有效的 CSS,但在 scss 编译中会失败 */ background-color: rgba(var(--color_rgb), 0.5); /* 这是有效的 scss,会生成上面的 CSS */ background-color: #{'rgba(var(--color_rgb), 0.5)'}; }

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


如果您更喜欢在 Sass .scss 文件中使用原生 CSS 颜色函数,您可以在文件顶部包含以下函数定义以覆盖 Sass 的处理并使其通过:@function rgb($args...) { @return #{'rgb(#{$args})'}; } @function rgba($args...) { @return #{'rgba(#{$args})'}; } @function hsl($args...) { @return #{'hsl(#{$args})'}; } { 4}````
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 包,此解决方法似乎不再需要
v
vsync

我遇到了类似的情况,但不幸的是,给定的解决方案对我不起作用,因为变量可以是从 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 的情况下获得正确的堆叠顺序。
v
vsync

相对颜色语法

借助这种允许颜色格式转换的新 CSS 功能 (css-color-5),它还允许为任何格式的任何颜色添加不透明度,例如,添加到 RGB(相对转换可以以任何其他格式完成):

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

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


S
Stefan Rein

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

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


r
roberrrt-s

这确实可以通过 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 { 宽度:100px;高度:100px;边距:10px; } .element1 { 背景:线性渐变(var(--white-low-opacity),var(--white-low-opacity))无重复,线性渐变(var(--red),var(- -red)) 不重复; } .element2 { 背景:线性渐变(var(--white-high-opacity),var(--white-high-opacity))无重复,线性渐变(var(--red),var(- -red)) 不重复; } .element3 { 背景:线性渐变(var(--black-low-opacity),var(--black-low-opacity))无重复,线性渐变(var(--red),var(- -red)) 不重复; } .element4 { 背景:线性渐变(var(--black-high-opacity),var(--black-high-opacity))无重复,线性渐变(var(--red),var(- -red)) 不重复; }

hello world
hello world
hello world
你好世界


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

如果您使用深色和浅色模式,我使用此示例。我更喜欢将颜色和 rgb 颜色变量分配分开。所以我每个循环使用两个。我意识到这个解决方案不是干代码。如果你想干代码,你可以使用一个循环。

$colors-light:(白色:#fff,黑色:#0c0d0e,橙色:#f48024,绿色:#5eba7d,蓝色:#0077cc,红色:#d1383d,red-100:#e2474c,red-200:红色,) ; $colors-dark:(黑色:#fff,白色:#2d2d2d,橙色:#dd7118,绿色:#5eba7d,蓝色:#0077cc,红色:#aa1c21,red-100:#c9292e,red-200:红色,) ; @function hexToRGB($hex) { @return red($hex), green($hex), blue($hex); } @mixin generate_colors($colors) { // 颜色 @each $color, $value in $colors { @if str-slice(#{$value}, 1, 1) == "#" { --#{$颜色}: #{$value}; } @else { --#{$color}: var(--#{$value}); } } // RGB 颜色 @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) { // 颜色,RGB 颜色 @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; --黑色:#0c0d0e; --RGB_black: 12, 13, 14; --橙色:#f48024; --RGB_橙色:244、128、36; --绿色:#5eba7d; --RGB_green:94、186、125; --蓝色:#0077cc; --RGB_blue: 0, 119, 204; --红色:#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; --白色:#2d2d2d; --RGB_white:45、45、45; --橙色:#dd7118; --RGB_橙色:221、113、24; --绿色:#5eba7d; --RGB_green:94、186、125; --蓝色:#0077cc; --RGB_blue: 0, 119, 204; --红色:#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); } 身体 { 背景颜色: var(--white); } .colors { 显示:-webkit-box;显示:-ms-flexbox;显示:弯曲; -webkit-box-orient:水平; -webkit-box-direction:正常; -ms-flex-direction:行;弹性方向:行; -ms-flex-wrap:换行;弹性包装:换行; -webkit-box-pack:开始; -ms-flex-pack:开始;证明内容:弹性开始; -webkit-box-align:居中; -ms-flex-align:居中;对齐项目:居中;边距:50px 0 0 30px; } .box { 宽度:100px;高度:100px;右边距:5px; } .black { 背景颜色:var(--black); } .white { 背景颜色:var(--white); } .orange { 背景颜色:var(--orange); } .green { 背景颜色:var(--green); } .blue { 背景颜色:var(--blue); } .red { 背景颜色:var(--red); } .red-200 { 背景颜色:var(--red-200); } .black-rgba { 背景颜色:rgba(var(--RGB_black), 0.5); } .white-rgba { 背景颜色:rgba(var(--RGB_white), 0.5); } .orange-rgba { 背景颜色:rgba(var(--RGB_orange), 0.5); } .green-rgba { 背景颜色:rgba(var(--RGB_green), 0.5); } .blue-rgba { 背景颜色:rgba(var(--RGB_blue), 0.5); } .red-rgba { 背景颜色:rgba(var(--RGB_red), 0.5); } .red-rgba-200 { 背景颜色:rgba(var(--RGB_red-200), 0.5); } Document


RGBA


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

您可以使用 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;高度:100px;边框:2px 实心#000; --黑客:10000%;背景:线性渐变(到底部,var(--color)计算((var(--opacity)-1)* var(--hack)),透明计算(var(--opacity)* var(--黑客))); } #container { 背景图像:线性渐变(45deg,#b0b0b0 25%,透明 25%),线性渐变(-45deg,#b0b0b0 25%,透明 25%),线性渐变(45deg,透明 75% , #b0b0b0 75%), 线性渐变(-45deg, 透明 75%, #b0b0b0 75%);背景尺寸:20px 20px;背景位置:0 0、0 10px、10px -10px、-10px 0px;填充:10px;显示:内联块; }



P
Pizza lord
:root{
--color: 255, 0, 0;
}

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

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


这是试图回答这个问题吗?因为如果是这样,代码就没有意义了。特别是 rgba(var(--color), opacity) 位。特别是因为您的自定义属性值是整个 rgb() 表示法。也是因为“不透明”关键字。
糟糕,rgb 部分不应该在 var 中
D
Dekel

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

:root { --color: #F00; --颜色不透明度:rgba(255, 0, 0, 0.5); } #a1 { 背景:var(--color); } #a2 { 背景:var(--color-opacity); }

asdf
asdf

如果你不能使用这个并且你可以使用 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 { 背景:var(--color); } #a2 { 背景:var(--color); }

asdf
asdf


不透明度值会改变,因此为每个不透明度创建一个变量会很烦人。
S
Seth M

如果你像我一样喜欢十六进制颜色,还有另一种解决方案。十六进制值是 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');` 为混淆道歉。
D
Dani Fadli

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

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

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

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

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


P
Patrick H.

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

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

或者只是设置不透明度:

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

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