在SASS函数中使用CSS变量以实现hsl()透明度的方法?

39

我在根目录中定义了一个颜色:

:root {
--purple: hsl(266, 35%, 70%);
}

我正在尝试在SASS函数中使用它来赋予透明度:

.purple {
  background: transparentize(#{"var(--primary-color)"}, 0.7)
}

有人知道如何让这个工作吗?还是不可能的?


5
请看这个链接:https://codepen.io/jakealbaugh/post/css4-variables-and-sass 它介绍了CSS4变量和Sass预处理器。我会帮助您将其翻译成中文,以便更容易理解。 - Aravind S
5
好的链接!原帖:一般情况下不可能实现,因为CSS变量是动态的:它们的值每次使用时都会计算。Sass变量具有在编译时已知的值。如果您在Sass中定义常量并将其用于定义:root中的CSS变量,并且不在子节点中使用后者,则可以在两者中都使用它们。 - FelipeAls
8个回答

16

全局变量可以在 :root 伪类中的元素之外定义:

:root {
  --color-primary: #FFFFFF;
}

你可以像这样定义一个函数:

@function color($color-name) {
  @return var(--color-#{$color-name});
}

并将其引入到您的Sass中:

body { 
  color: color(primary); 
}

编译后的Sass代码如下:

body { 
  color: var(--color-primary); 
}

32
不,它不是。transparentize()函数期望一个十六进制代码作为输入。而当前这个函数输出的是一个无效的var()字符串。 - RZKY
4
这并没有回答原始问题。 - eballeste
这不适用于需要有效颜色的函数,因此它不能成为lighten参数的一部分。 - Rommel Manalo
2
这根本没有回答问题。我不知道为什么会得到赞。也许我错了,你能举一个涉及到“transparentize”的例子吗? - oemera
1
这个回答并没有解答原问题,需要提供更具体的信息。 - Clarance Liberiste Ntwari
正如其他评论所说,sass函数期望的是一个颜色而不是另一个函数,因此这并没有解决问题。 - andy_314

11
#{var(--variablename)}

以下是如何在SCSS中使用CSS变量的方法


7
不行。你可以在 SCSS 中像这样使用 CSS 变量,但不能在 SCSS 函数中使用。而且这个问题特别是关于函数的。transparentize(#{var(--someColor)}, 0.7) 不会起作用(因为评论和其他答案中提到的原因)。 - Romalex

8
如果您正在寻找使用Sass颜色函数调整颜色的方法(我觉得这是人们来到这里的主要原因),那么这里有一个解决方案。这个想法与Juanete Montoya的答案相同,但它是纯Sass/Scss(没有PHP):
首先,我们需要将颜色分成HSLA值,并将每个值保存在单独的自定义属性中。
@mixin define-color($title, $color) {
    --#{$title}-h: #{hue($color)};
    --#{$title}-l: #{lightness($color)};
    --#{$title}-s: #{saturation($color)};
    --#{$title}-a: #{alpha($color)};
}

现在我们可以重新组装它,在此过程中进行一些调整。
@function color($title, $hue: 0deg, $lightness: 0%, $saturation: 0%, $alpha: 0) {
    @return hsla(
        calc(var(--#{$title}-h) + #{$hue}), 
        calc(var(--#{$title}-s) + #{$saturation}),
        calc(var(--#{$title}-l) + #{$lightness}),
        calc(var(--#{$title}-a) + #{$alpha}),
    );
}

现在,我们准备定义一些颜色变量...

:root {
    @include define-color("primary", #696969);
    @include define-color("secondary", blue);
}

使用并调整它们!

.example-class {
    color: color("primary");
    background: color("secondary", $lightness: +20%, $alpha: -0.3);
    border: 1px solid color("primary", $hue: -30deg, $saturation: 5%);
}

6
很遗憾,这是不可能的。CSS变量在运行时被替换为它们的值。SASS编译器只是一个编译器,因此无法读取CSS变量的值,因为CSS变量可以在其他文件中定义。

4

简单的解决方案,需要两个变量而不是一个

类似于Romalex的答案,这篇文章中有一个优雅的解决方案:如何使用Sass Mixins和CSS变量

您可以使用RGB三元数列表定义您的颜色变量,然后可以使用Sass transparentize和其他颜色函数进行操作。

:root {
  --color-primary: #16498a;
  --color-primary-rgb: 22, 73, 138;
}

h1 {
  color: var(--color-primary);
}

h2 {
  color: rgba(var(--color-primary-rgb), 0.4);
}

您可以编写自己的Sass函数来处理变量的倍增,就像以下示例中的方式。

使用自定义Sass函数的完整解决方案

本文中有一个示例:

如何结合SASS颜色函数和CSS变量

示例用法:

:root {
  @include defineColorHSL(--color-primary, 220, 90%, 56%);
}

.component {
  color: alpha(var(--color-primary), 0.2); // it works 
}

所需资源:

// return css color variable with different opacity value
@function alpha($color, $opacity){
  $color: str-replace($color, 'var(');
  $color: str-replace($color, ')');
  $color-h: var(#{$color+'-h'});
  $color-s: var(#{$color+'-s'});
  $color-l: var(#{$color+'-l'});
  @return hsla($color-h, $color-s, $color-l, $opacity);
}

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


@mixin defineColorHSL($color, $hue, $saturation, $lightness){
  #{$color}: unquote("hsl(#{$hue}, #{$saturation}, #{$lightness})");#{$color}-h: #{$hue};#{$color}-s: #{$saturation};#{$color}-l: #{$lightness};
}

3

SASS转译是首先执行的,因此最好先设置SASS变量,然后再将其与--css_variables连接起来。

为了实现这一点,您需要像以下示例中使用@use "sass:meta";

@use "sass:meta";


//sass variable
$primarySassVariable: #4252af;


//css variable
:root {
  --primary: #{meta.inspect($primarySassVariable)};
}

这似乎是正确的方法,但您的示例还没有包括原始问题的意图:在 transparentize 函数中使用变量。现在它可能有效,因为它只是一个 SCSS 变量?但最好将其放入答案中。但是,如果从 SCSS 设置 CSS 变量对于人们来说是一种选项,那么这似乎可以避免转换变量的所有需要。 - Flion
另外,仔细思考一下,如果您选择这种方法并且希望在组件中使用CSS变量(就像OP的问题一样),以便您可以通过JS进行更改...那么设置CSS变量的代码应该在任何可能想要更改SCSS变量的SCSS代码之后执行(例如导入主题并更改一个值),但在实际UI的任何SCSS代码之前,如果该UI使用CSS变量。正确吗?因为一旦读取和解析设置CSS变量的位,之后更改SCSS变量将不起作用。 - Flion

0

我意识到这并不完全是原问题所问的,但当我尝试使用SASS变量来定义CSS变量时,我遇到了类似的问题。根据最初的研究,我尝试了transparentize(#{$purple}, 0.7),但失败了。相反,需要用#{ }将函数括起来:

$purple: #abc123;

:root {
  --purple: #{transparentize($purple, 0.7)};
}

想分享一下,因为我还没有找到使用函数和SASS变量定义CSS变量的示例。一度以为不可能,但是我误解了问题。


SCSS将样式编译为CSS,因此SCSS文件中的任何内容都将编码在最终文件中。任何SASS函数都会在编译过程中计算和应用,因此一旦完成,就不会再更改。CSS变量是通过CSS本身动态应用的。这就是为什么您无法从示例中以这种方式组合它的原因。 - Vladimir Jovanović

-3
我的解决方案是将十六进制颜色代码转换为HSL。首先,我创建了一个PHP函数。
function hexToHsl($hex) {
    $hex = str_split(ltrim($hex, '#'), 2);
    // convert the rgb values to the range 0-1
    $rgb = array_map(function($part) {
        return hexdec($part) / 255;
    }, $hex);

    // find the minimum and maximum values of r, g and b
    $min = min($rgb);
    $max = max($rgb);

    // calculate the luminace value by adding the max and min values and divide by 2
    $l = ($min + $max) / 2;
    if ($max === $min) {
        $h = $s = 0;
    } else {
        if ($l < 0.5) {
            $s = ($max - $min) / ($max + $min);
        } elseif ($l > 0.5) {
            $s = ($max - $min) / (2 - $max - $min);
        }
        if ($max === $rgb[0]) {
            $h = ($rgb[1]- $rgb[2]) / ($max -$min);
        } elseif ($max === $rgb[1]) {
            $h = 2 + ($rgb[2]- $rgb[0]) / ($max -$min);
        } elseif ($max === $rgb[2]) {
            $h = 4 + ($rgb[0]- $rgb[1]) / ($max -$min);
        }
        $h = $h * 60;
        if ($h < 0) {
            $h = $h + 360;
        }
    }

    return array($h, $s*100, $l*100);
}

它将接收十六进制颜色代码,例如#cc66cc,并返回一个包含H、S和L三个值的数组。

$color_main_hsl = hexToHsl($color_main);
$color_main_h = $color_main_hsl[0];
$color_main_s = $color_main_hsl[1] . '%';
$color_main_l = $color_main_hsl[2] . '%';

然后将其赋值给变量CSS。

<style>
    :root {
        --color_1: <?php echo $color_main; ?>;
        --color_1_h: <?php echo $color_main_h; ?>;
        --color_1_s: <?php echo $color_main_s; ?>;
        --color_1_l: <?php echo $color_main_l; ?>;
    }
</style>

然后我在SASS中创建了两个函数,一个用于加深颜色,另一个用于减淡颜色:

// hsl css variable darken
@function hsl_d($color_num, $percentage) {
    $color_h: var(--color_#{$color_num}_h);
    $color_s: var(--color_#{$color_num}_s);
    $color_l: var(--color_#{$color_num}_l);
    @return hsl($color_h, $color_s, calc(#{$color_l} - #{$percentage}#{'%'}));
}

// hsl css variable lighten
@function hsl_l($color_num, $percentage) {
    $color_h: var(--color_#{$color_num}_h);
    $color_s: var(--color_#{$color_num}_s);
    $color_l: var(--color_#{$color_num}_l);
    @return hsl($color_h, $color_s, calc(#{$color_l} + #{$percentage}#{'%'}));
}

最后我使用了我的Sass函数:

.element-to-dark {
    background-color: hsl_d(1, 12);
}

.element-to-light {
    background-color: hsl_d(1, 22);
}

数字“1”是因为我的变量被称为--color_1、--color_1_h、--color_1_s、--color_1_l,而我的函数会插值这个数字。第二个参数是用于调整亮度或加深的百分比。

希望我有所贡献 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接