【问题标题】:SASS detect colour darkness to determine stylesSASS 检测颜色暗度以确定样式
【发布时间】:2022-01-21 10:34:43
【问题描述】:

我正在尝试制作一个可以检测是否显示深色文本(如果传递给 buttonStyles 的颜色是浅色的)或浅色文本(用于传递深色)的 mixin。我记得有一种方法可以用 LESS 来做,我想知道是否有 SASS 方法。

考虑这个 SCSS:

$white: #fff;
$text: #393939;
$font-std: 18px;
$transition-std: 0.4s ease all;
$primary: #f8e421;
$secondary: #354052;

@mixin buttonStyles($color) {
    font-size: $font-std;
    color: $text;
    padding: 1rem 3rem;
    background-color: $color;
    color: $white;
    transition: $transition-std;

    &:hover {
        cursor: pointer;
        background-color: lighten($color, 15%);
    }
    &:focus {
        background-color: lighten($color, 10%);
    }
    &:active {
        background-color: lighten($color, 25%);
    }
}
.btnPrimary {
    @include buttonStyles($primary);
}
.btnSecondary {
    @include buttonStyles($secondary);
}

还有这个html:

<button class='btnSecondary'>secondary</button>
<button class='btnPrimary'>primary</button>

辅助按钮比主按钮更易读。我知道我可以传入第二个参数来设置文本颜色,但想知道是否有与 LESS 一样更清洁、更自动的方式? (不幸的是,我不记得它是如何使用 LESS 完成的)

现场演示:https://jsfiddle.net/3v0ckeq9/5/

谢谢

编辑:

我已经添加了这个似乎几乎可以工作的功能:

@function ligthOrDark($color) {
    $result: red;

    @if (blackness($color) == 50) { // fails with > 50 or < 50
        $result: green;
    }

    @return $result;
}

但问题是 SASS 在尝试确定颜色是否大于 50(或小于)时会抱怨,但可以使用 ==。我只想能够确定提供的颜色是深色还是浅色,以便应用正确的文本颜色。

看来这里应该有判断明暗的选项:https://sass-lang.com/documentation/modules/color#grayscale

欢迎使用替代解决方案。

【问题讨论】:

    标签: css sass scss-mixins


    【解决方案1】:

    根据documentationwhitenessblacknessHWB color model 相关。如果您可以使用 HSL 模型,则可以使用 lightness,如下所示:

    $white: #fff;
    $text: #393939;
    $font-std: 18px;
    $transition-std: 0.4s ease all;
    $primary: #f8e421;
    $secondary: #354052;
    
    @function contrastText($color) {
        $result: invert($color);
        $lightness: lightness($result);
        @if ($lightness < 50) {
            $result: black;
        }
        @return $result;
    }
    
    @mixin buttonStyles($color) {
        font-size: $font-std;
        padding: 1rem 3rem;
        background-color: $color;
        color: contrastText($color);
        transition: $transition-std;
    
        &:hover {
            cursor: pointer;
            background-color: lighten($color, 15%);
        }
        &:focus {
            background-color: lighten($color, 10%);
        }
        &:active {
            background-color: lighten($color, 25%);
        }
    }
    .btnPrimary {
        @include buttonStyles($primary);
    }
    .btnSecondary {
        @include buttonStyles($secondary);
       
    }
    .btnTest {
        @include buttonStyles(#888);
    }
    
    

    编译后如下:jsfiddle

    /* CSS compiled from SASS*/
    .btnPrimary {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: #f8e421;
      color: black;
      transition: 0.4s ease all;
    }
    
    .btnPrimary:hover {
      cursor: pointer;
      background-color: #faed6b;
    }
    
    .btnPrimary:focus {
      background-color: #faea52;
    }
    
    .btnPrimary:active {
      background-color: #fcf39d;
    }
    
    .btnSecondary {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: #354052;
      color: #cabfad;
      transition: 0.4s ease all;
    }
    
    .btnSecondary:hover {
      cursor: pointer;
      background-color: #536480;
    }
    
    .btnSecondary:focus {
      background-color: #495871;
    }
    
    .btnSecondary:active {
      background-color: #697d9e;
    }
    
    .btnTest {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: #888;
      color: black;
      transition: 0.4s ease all;
    }
    
    .btnTest:hover {
      cursor: pointer;
      background-color: #aeaeae;
    }
    
    .btnTest:focus {
      background-color: #a2a2a2;
    }
    
    .btnTest:active {
      background-color: #c8c8c8;
    }
    
    .testRed {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: red;
      color: cyan;
      transition: 0.4s ease all;
    }
    
    .testRed:hover {
      cursor: pointer;
      background-color: #ff4d4d;
    }
    
    .testRed:focus {
      background-color: #ff3333;
    }
    
    .testRed:active {
      background-color: #ff8080;
    }
    
    .testGreen {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: green;
      color: #ff7fff;
      transition: 0.4s ease all;
    }
    
    .testGreen:hover {
      cursor: pointer;
      background-color: #00cc00;
    }
    
    .testGreen:focus {
      background-color: #00b300;
    }
    
    .testGreen:active {
      background-color: lime;
    }
    
    .testBlue {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: blue;
      color: yellow;
      transition: 0.4s ease all;
    }
    
    .testBlue:hover {
      cursor: pointer;
      background-color: #4d4dff;
    }
    
    .testBlue:focus {
      background-color: #3333ff;
    }
    
    .testBlue:active {
      background-color: #8080ff;
    }
    
    .testOrange {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: orange;
      color: #005aff;
      transition: 0.4s ease all;
    }
    
    .testOrange:hover {
      cursor: pointer;
      background-color: #ffc04d;
    }
    
    .testOrange:focus {
      background-color: #ffb733;
    }
    
    .testOrange:active {
      background-color: #ffd280;
    }
    
    .testPurple {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: purple;
      color: #7fff7f;
      transition: 0.4s ease all;
    }
    
    .testPurple:hover {
      cursor: pointer;
      background-color: #cc00cc;
    }
    
    .testPurple:focus {
      background-color: #b300b3;
    }
    
    .testPurple:active {
      background-color: magenta;
    }
    
    .testYellow {
      font-size: 18px;
      padding: 1rem 3rem;
      background-color: yellow;
      color: blue;
      transition: 0.4s ease all;
    }
    
    .testYellow:hover {
      cursor: pointer;
      background-color: #ffff4d;
    }
    
    .testYellow:focus {
      background-color: #ffff33;
    }
    
    .testYellow:active {
      background-color: #ffff80;
    }
    <button class='btnSecondary'>secondary</button>
    <button class='btnPrimary'>primary</button>
    <button class='btnTest'>test</button>
    <hr>
    <button class='testRed'>Red</button>
    <button class='testGreen'>Green</button>
    <button class='testBlue'>Blue</button>
    <button class='testOrange'>Orange</button>
    <button class='testPurple'>Purple</button>
    <button class='testYellow'>Yellow</button>


    我不明白为什么 HWB whitenessblackness 无法与 HSL lightness 这样的数字相提并论。但有可能不用这些函数也能搞定,因为公式很简单:

    您可以使用red($color)min max 函数。


    仅使用whitnessblacknesslightness 不足以处理某些颜色。我认为您正在寻找的是relative luminance 以获得最具对比的颜色。白色的亮度为 1,黑色的亮度为 0。灰底黑对比度大于灰底白。探索更多,了解this website 是如何计算对比度的。


    可选参数您可以通过定义参数的默认值来生成arguments optional。在我们的例子中,任何非颜色值都可以:

    @function contrastText($color, $text:-1) {
        $result: invert($color);
        $lightness: lightness($result);
        @if ($lightness < 47) {
            $result: black;
        }
        @if ($lightness > 46) {
            $result: white;
        }
        @if (type_of($text) == 'color') {
            $result: $text;
        }
        @return $result;
    }
    
    @mixin buttonStyles($color) {
        color: contrastText($color);
       /*color: contrastText($color,);*/
       /*color: contrastText($color, red);*/
    }
    

    【讨论】:

    • 谢谢 - 看起来这可能是最接近的选项。但是是否可以使用 SASS 函数传入可选参数?我希望能够传入一个可选的文本变量,因为黄色按钮有点偏离,就像我刚刚制作的这个演示一样:jsfiddle.net/xytuj739 - 这可能吗?第 17 行似乎打破了它
    • 是的,由于缺少参数,它在第 27 行 color: contrastText($color) 失败。您可以将参数设为可选。查看更新后的答案。
    • 太好了,谢谢!
    猜你喜欢
    • 2020-04-04
    • 2014-01-27
    • 2016-02-12
    • 2017-03-31
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    相关资源
    最近更新 更多