Как создавать цветовые оттенки с помощью CSS-переменных, подобных darken() SASS?

#css #function #variables #sass #colors

Вопрос:

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

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

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

 $color-primary: #f00;

.button {
    background: $color-primary;

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

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

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

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

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

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

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

Ответ №1:

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

 :root {
    --color-primary: #f00; /* any format you want here */
    --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%)); 
}
 

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

На сегодняшний день для этого все еще нет поддержки, поэтому рассмотрите приведенное ниже решение.


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

 :root {
    --color:0, 100%; /*the base color*/
    --l:50%; /*the initial lightness*/
    
    --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">some text</span> 

В качестве примечания, darken() также делает то же самое:

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

Комментарии:

1. Как бы установить другой цвет для начальной переменной —color? Я не уверен, как 0, 100% это равно красному.

2. @Bribbons использует конвертер: rapidtables.com/convert/color/rgb-to-hsl.html

3. @TemaniAfif решение работает. Но вместо того, чтобы жестко кодировать значение яркости, есть ли способ извлечь значение из цвета на ходу. Видите ли, у меня есть около дюжины цветов, и я хотел бы получить более темную версию всех

4. @Dibzmania можете ли вы поделиться примером использования и кодом? исходя из ситуации, мы можем найти решение

5. @Dani Sass и меньше переменных компилируются перед выполнением. CSS-переменные могут быть изменены во время выполнения. Это то, чего Сасс и Меньше просто не могут сделать. Это означает, что вы можете, например, изменить значение переменной в ответ на действие пользователя. Очень полезно для разработки режимов света/темноты. Это было бы гораздо сложнее, если не невозможно, сделать в Sass/Less.

Ответ №2:

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

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

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

    amp;: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) /* black mask with 5% opacity */
}

.button:active:before {
    background:rgba(0,0,0,0.1) /* black mask with 10% opacity */
}