SASS 检测颜色暗度以确定样式

SASS detect colour darkness to determine styles

我正在尝试制作一个 mixin,它可以检测是显示深色文本(如果传递给 buttonStyles 的颜色是浅色)还是浅色文本(用于传递较深的颜色)。我记得有一种方法可以用 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

欢迎其他解决方案。

根据 documentation, whiteness and blackness are related to HWB 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 to get most contrasting color. White has luminance 1 and black has 0. And black-on-gray contrast is more than white-on-gray. To explore more figure out how 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);*/
}