Как создать оттенки цвета с помощью CSS-переменных, аналогичные функции darken() в Sass?

Вопрос или проблема

Я ищу способ изменить CSS-переменную так, как это делается в SCSS.

Определив цвет, например, основной, я бы автоматически получил оттенки для состояний фокуса и активных состояний. В основном, я хотел бы изменить одну переменную в CSS-переменных и получить 3 оттенка того же цвета.

Что я хотел бы достичь в CSS

$color-primary: #f00;

.button {
    background: $color-primary;

    &:hover,
    &:focus {
        background: darken($color-primary, 5%);
    }

    &:active {
        background: darken($color-primary, 10%);
    }
}

что я пытаюсь достичь:

:root {
    --color-primary: #f00;
    --color-primary-darker: #f20000  //     var(--color-primary) * 5% темнее
    --color-primary-darkest: #e50000 //     var(--color-primary) * 10% темнее
}

.button {
    background: var(--color-primary);
}

.button:hover,
.button:focus {
    background: var(--color-primary-darker);
}

.button:active {
    background: var(--color-primary-darkest);
}

Новая Спецификация вводит “синтаксис относительного цвета”, где вы можете сделать следующее

:root {
  --color-primary: #f00; /* любой формат, который вы хотите */
  --color-primary-darker: hsl(from var(--color-primary) h s calc(l - 5));
  --color-primary-darkest: hsl(from var(--color-primary) h s calc(l - 10));

   background:
    linear-gradient(to right,var(--color-primary) 33%,var(--color-primary-darker) 0 66%,var(--color-primary-darkest) 0);
}

Идея заключается в том, чтобы преобразовать основной цвет в hsl формат и, используя calc(), отрегулировать легкость.

Поддержка этой функции все еще не очень хороша, поэтому рассмотрите приведенное ниже решение.

Вы можете использовать color-mix() и смешать цвет с черным (или белым), чтобы создать разные оттенки одного и того же цвета.

html {
  --color-primary: #8A9B0F; 
  --color-primary-darker:  color-mix(in srgb,var(--color-primary),#000 15%);
  --color-primary-darkest: color-mix(in srgb,var(--color-primary),#000 30%);

  background:
    linear-gradient(to right,var(--color-primary) 33%,var(--color-primary-darker) 0 66%,var(--color-primary-darkest) 0);
}

Я также написал об этом здесь: https://css-tip.com/color-shades-color-mix/


Старый ответ

Вы можете рассмотреть hsl() цвета и просто контролировать легкость:

:root {
    --color:0, 100%; /*основной цвет*/
    --l:50%; /*начальная легкость*/

    --color-primary: hsl(var(--color),var(--l));
    --color-primary-darker: hsl(var(--color),calc(var(--l) - 5%));
    --color-primary-darkest: hsl(var(--color),calc(var(--l) - 10%)); 
}

.button {
    background: var(--color-primary);
    display:inline-block;
    padding:10px 20px;
    color:#fff;
    cursor:pointer;
}

.button:hover,
.button:focus {
    background: var(--color-primary-darker);
}

.button:active {
    background: var(--color-primary-darkest);
}
<span class="button">некоторый текст</span>

Кстати, darken() также делает то же самое:

Делает цвет темнее. Берет цвет и число от 0% до 100% и возвращает цвет с уменьшенной легкостью на это значение.

Как насчет этого (чистый sass/scss):

Сначала нам нужно разделить цвет на значения hsla и сохранить каждое из них в отдельном пользовательском свойстве. К счастью, sass имеет некоторые функции для выполнения этой работы.

@mixin define-color($title, $color) {
    --#{$title}-h: #{hue($color)};
    --#{$title}-l: #{lightness($color)};
    --#{$title}-s: #{saturation($color)};
    --#{$title}-a: #{alpha($color)};
}

Теперь мы можем собрать его обратно, сделав некоторые adjustments на этом пути.

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

переопределить их (например, для динамического переключения между темами)…

:root.theme-light {
    @include define-color("primary", #424242);
    @include define-color("secondary", red);
}

использовать и настраивать их!

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

Развивая ответ Темани: Я использую градиент – от черного к динамическому цвету до белого – и расширяю фон в 100 раз. Теперь это только вопрос позиционирования фона.

В CSS

.dynamic-color {
    --lighten: 80%;
    --darken: 45%;
    --original-color: 50%;
    --color-intensity: var(--original-color);
    --color-variable: blue;
    background-image: linear-gradient(90deg,black, var(--color-variable),white);
    background-repeat: no-repeat;
    background-size: 10000% 100%;
    background-position-x: var(--color-intensity);
}

.dynamic-color:hover{
    --color-intensity: var(--lighten);
}

.dynamic-color.active{
    --color-intensity: var(--darken);
}

А в HTML

<btn class="dynamic-color" style="--color-variable: green">Наведи на меня</btn>

Если вы готовы подойти к вашей проблеме с другого ракурса, использование масок с псевдоэлементом “:before” решит вашу проблему. Хотя, если вы используете это, я бы посоветовал вам поместить любой контент кнопки внутрь span или чего-то подобного, чтобы дать ему “z-index:1”, чтобы контент не оказался за маской.

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

.button {
    position:relative;
    background: var(--color-primary);

    &:before {
        content:'';
        position:absolute;
        width:100%;
        height:100%;
        top:0;
        left:0;
    }
}

.button:hover:before,
.button:focus:before {
    background:rgba(0,0,0,0.05) /* черная маска с 5% непрозрачностью */
}

.button:active:before {
    background:rgba(0,0,0,0.1) /* черная маска с 10% непрозрачностью */
}

Ответ или решение

Для создания оттенков цвета с использованием CSS-переменных, аналогичных функции darken() в Sass, можно применить несколько подходов. Важно понимать, что CSS не предоставляет встроенных функций для изменения цвета, как это делает Sass, поэтому потребуется использовать методы, позволяющие достичь похожих результатов.

Использование HSL

Одним из методов является использование цветовой модели HSL (Hue, Saturation, Lightness). Вы можете настроить цвет, изменяя его светлоту. Вот пример, как это реализовать:

:root {
    --color-hue: 0; /* Главный цвет (красный) */
    --color-saturation: 100%; 
    --color-lightness: 50%; /* Исходная светлота */

    --color-primary: hsl(var(--color-hue), var(--color-saturation), var(--color-lightness));
    --color-primary-darker: hsl(var(--color-hue), var(--color-saturation), calc(var(--color-lightness) - 5%));
    --color-primary-darkest: hsl(var(--color-hue), var(--color-saturation), calc(var(--color-lightness) - 10%));
}

.button {
    background: var(--color-primary);
    padding: 10px 20px;
    color: #fff;
    cursor: pointer;
}

.button:hover,
.button:focus {
    background: var(--color-primary-darker);
}

.button:active {
    background: var(--color-primary-darkest);
}

В этом примере мы определили основные параметры цвета (оттенок, насыщенность и светлоту) как переменные. Затем с помощью вычисления calc() изменяем светлоту для создания более темных оттенков.

Использование color-mix()

Другой способ – использование функции color-mix(), которая позволяет смешивать цвета. Это может быть полезно для создания более темных оттенков, смешивая оригинальный цвет с черным:

:root {
    --color-primary: #8A9B0F; 
    --color-primary-darker: color-mix(in srgb, var(--color-primary), #000 15%);
    --color-primary-darkest: color-mix(in srgb, var(--color-primary), #000 30%);
}

.button {
    background: var(--color-primary);
    padding: 10px 20px;
    color: #fff;
    cursor: pointer;
}

.button:hover,
.button:focus {
    background: var(--color-primary-darker);
}

.button:active {
    background: var(--color-primary-darkest);
}

Подход с использованием градиентов

Ещё один подход заключается в использовании градиентов. Мы можем создать линейный градиент, который будет варьироваться от черного через основной цвет к белому. С помощью позиционирования можно добиться необходимого эффекта:

.dynamic-color {
    --lighten: 80%;
    --darken: 45%;
    --original-color: 50%;
    --color-intensity: var(--original-color);
    --color-variable: blue;

    background-image: linear-gradient(90deg, black, var(--color-variable), white);
    background-repeat: no-repeat;
    background-size: 10000% 100%;
    background-position-x: var(--color-intensity);
}

.dynamic-color:hover {
    --color-intensity: var(--lighten);
}

.dynamic-color:active {
    --color-intensity: var(--darken);
}

Заключение

CSS-переменные предлагают гибкий и мощный способ динамического изменения стилей элементов. Несмотря на отсутствие функций типа darken() из Sass, приведённые выше методы позволяют создать аналогичную функциональность. Выбор между использованием HSL, функции color-mix() или градиентов зависит от ваших предпочтений и конкретных требований проекта.

Оцените материал
Добавить комментарий

Капча загружается...