Як застосувати непрозорість до змінної кольору CSS?


144

Я розробляю додаток в електронному вигляді, тому в мене є доступ до змінних CSS. Я визначив змінну кольору в vars.css:

:root {
  --color: #f0f0f0;
}

Я хочу використовувати цей колір у main.css, але із застосуванням деякої непрозорості:

#element {
  background: (somehow use var(--color) at some opacity);
}

Як би я пішов робити це? Я не використовую жодного препроцесора, лише CSS. Я вважаю за краще відповідь на всі CSS, але я прийму JavaScript / jQuery.

Я не можу використовувати, opacityоскільки я використовую фонове зображення, яке не повинно бути прозорим.


Так здається, що ви повинні використовувати більше одного елемента ....
epascarello

Я вважаю за краще не робити, але, здається, мені доведеться ... :(
JoshyRobot

4
AHHHHH !!!!! Це так дратує! Зараз це майже 2020 рік. Вибір кольору набирає # шестигранних кольорів. alpha / rgba не працює в Sass / Stylus - тому що це не значення rgb. Чи варто помістити 4 повзунки в мою CMS для кожного кольору?
sheriffderek

Відповіді:


240

Ви не можете прийняти існуюче значення кольору і застосувати до нього альфа-канал. А саме, ви не можете прийняти існуюче значення шістнадцятки, наприклад #f0f0f0, надати йому альфа-компонент і використовувати отримане значення з іншим властивістю.

Однак користувацькі властивості дозволяють перетворити ваше шістнадцяткове значення в триплет RGB для використання rgba(), зберігати це значення у користувальницькій властивості (включаючи коми!), Замінювати це значення за var()допомогою rgba()функції на потрібне значення альфа, і воно буде просто працюй:

:root {
  /* #f0f0f0 in decimal RGB */
  --color: 240, 240, 240;
}

body {
  color: #000;
  background-color: #000;
}

#element {
  background-color: rgba(var(--color), 0.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>

Це здається майже надто гарним, щоб бути правдою. 1 Як це працює?

Магія полягає в тому, що значення користувацьких властивостей підміняються так, як це відбувається при заміні var()посилань на значення властивості, перш ніж обчислюється значення цього властивості. Це означає , що, наскільки призначені для користувача властивості стурбовані значення --colorв вашому прикладі не є значення кольору на всіх , поки в var(--color)вираженні з'являється де - то , що очікує значення кольору (і тільки в цьому контексті). З розділу 2.1 специфікації змінних css:

Дозволений синтаксис для власних властивостей надзвичайно дозвільний. Виробництво <declaration-value> відповідає будь-якій послідовності одного або декількох лексем, якщо послідовність не містить <bad-string-token>, <bad-url-token>, unmatched <) - token>, <] - токен>, або <} - маркер>, або лексеми верхнього рівня <semicolon-token> або лексеми <delim-token> зі значенням "!".

Наприклад, наведене нижче дійсне спеціальне властивість:

--foo: if(x > 5) this.width = 10;

Хоча це значення, очевидно, марно як змінна, оскільки воно буде недійсним у будь-якій нормальній властивості, воно може читатись і діяти на JavaScript.

І розділ 3 :

Якщо властивість містить одну або більше функцій var (), і ці функції є синтаксично дійсними, граматика всієї власності повинна вважатись дійсною під час розбору. Він перевіряється лише синтаксисом під час обчисленого значення після того, як функції var () були замінені.

Це означає, що 240, 240, 240наведене вище значення заміщається безпосередньо у rgba()функції перед обчисленням декларації. Отже це:

#element {
  background-color: rgba(var(--color), 0.8);
}

який спочатку не здається дійсним CSS, оскільки rgba()очікує не менше чотирьох числових значень, розділених комами, стає таким:

#element {
  background-color: rgba(240, 240, 240, 0.8);
}

що, звичайно, цілком відповідає CSS.

Зробивши його на крок далі, ви можете зберігати альфа-компонент у його власному власному властивості:

:root {
  --color: 240, 240, 240;
  --alpha: 0.8;
}

і замінити його з тим же результатом:

#element {
  background-color: rgba(var(--color), var(--alpha));
}

Це дозволяє вам мати різні альфа-значення, які можна обміняти на ходу.


1 Ну, це якщо ви запустите фрагмент коду в браузері, який не підтримує власні властивості.


12
Це прекрасно
roberrrt-s

1
@Roberrrt: Це те, що я мав усвідомити на початку, насправді, бачачи, як я раніше розміщував ці відповіді .
BoltClock

2
Якщо ми будемо це вар, то чому б не використати що - щось на кшталт: .element2 { background-color: rgba(var(--red), var(--low-opacity); }. Таким чином ви зможете повністю використати використання змінних :).
roberrrt-s

7
На жаль, значення "240, 240, 240"не можна редагувати за допомогою вибору кольору. Це величезна сума, коли вам потрібно знайти потрібні кольори для вашого графічного інтерфейсу.
GetFree

1
@ s3c Синтаксис var(--hex-color)99перетворюється на два лексеми #333333 99( помічайте простір для розділення лексем), що, очевидно, не те, що ви хочете. Спеціальні властивості спочатку були визначені для копіювання жетонів, а не рядків, і це кінцевий результат. Зараз це занадто пізно, щоб виправити це.
Мікко Ранталайнен

19

Я знаю, що ОП не використовує препроцесор, але мені допомогли, якби наступна інформація була частиною відповіді тут (я поки не можу коментувати, інакше я б прокоментував відповідь @BoltClock.

Якщо ви використовуєте, наприклад, scss, відповідь вище не вдасться, оскільки scss намагається компілювати стилі за допомогою scss-специфічної функції rgba () / hsla (), для якої потрібні 4 параметри. Однак, rgba () / hsla () також є нативними функціями css, тому ви можете використовувати рядкову інтерполяцію для обходу функції scss.

Приклад (дійсний у sass 3.5.0+):

:root {
    --color_rgb: 250, 250, 250;
    --color_hsl: 250, 50%, 50%;
}

div {
    /* This is valid CSS, but will fail in a scss compilation */
    background-color: rgba(var(--color_rgb), 0.5);
    
    /* This is valid scss, and will generate the CSS above */
    background-color: #{'rgba(var(--color_rgb), 0.5)'};
}
<div></div>

Зауважте, що рядкова інтерполяція не працюватиме для не-CSS-функцій scss, таких як lighten(), оскільки отриманий код не буде функціональним CSS. Це все ще буде дійсним scss, тому ви не отримаєте помилок при компіляції.


4
Якщо ви віддаєте перевагу використанню натурних кольорів CSS у своїх файлах Sass .scss, ви можете включити наступні визначення функцій у верхній частині файлу, щоб перекрити обробку Sass і зробити так, щоб вони проходили: @function rgb($args...) { @return #{'rgb(#{$args})'}; } @function rgba($args...) { @return #{'rgba(#{$args})'}; } @function hsl($args...) { @return #{'hsl(#{$args})'}; } @function hsla($args...) { @return #{'hsla(#{$args})'}; }`` ``
lunelson

rgbaє синонімом вже rgbдавно. Ви, отже, дозволено кинути "а".
s3c

1
Інше рішення для scss-файлів - це використання верхнього регістру ( RGB), який потім ігнорується sass. Наприклад: color: RGB(var(--color_rgb), 0.5);. Від GitHub
Jono Job

9

Я був в подібній ситуації, але , до жаль , ці рішення не працюють для мене, так як змінні можуть бути чим - або від rgbдо hslдо hexабо навіть назв квітів.
Я вирішив цю проблему зараз, застосувавши до background-colorі opacityпсевдо :afterабо :beforeелемент:

.container {
    position: relative;
}

.container:before {
    content: "";
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    background-color: var(--color);
    opacity: 0.3;
}

Стилі, можливо, потрібно буде трохи змінити, залежно від елемента, до якого слід застосувати фон.
Крім того, це може не працювати у всіх ситуаціях, але, сподіваємось, це допомагає в деяких випадках, коли інші рішення не можна використовувати.

Редагувати: Я щойно помітив, що це рішення, очевидно, також впливає на колір тексту, оскільки створює елемент перед цільовим елементом і застосовує до нього прозорий колір фону.
У деяких випадках це може бути проблемою.


Це не тільки має перевагу в тому, що дозволяє більш гнучко визначати колір (наприклад, ім’я чи rgbабо HSL), але й уникає будь-якого конфлікту між нативними функціями кольорів CSS та кольоровими функціями Sass. Дивіться відповідь SimplyPhy нижче.
Джим Ратліфф

1
Я думаю, що краще використовувати, :beforeщоб ви отримали правильний порядок укладання без гри z-index.
Мікко Ранталайнен

5

Це дійсно можливо за допомогою CSS . Це просто трохи брудно, і вам доведеться використовувати градієнти. Я зашифрував невеликий фрагмент як приклад, візьміть на замітку, що для темних фонів слід використовувати чорну непрозорість, а для світлого - білу:

:root {
  --red: rgba(255, 0, 0, 1);
  --white-low-opacity: rgba(255, 255, 255, .3);
  --white-high-opacity: rgba(255, 255, 255, .7);
  --black-low-opacity: rgba(0, 0, 0, .3);
  --black-high-opacity: rgba(0, 0, 0, .7);
}

div {
	width: 100px;
	height: 100px;
	margin: 10px;
}
    
    
.element1 {
	background: 
        linear-gradient(var(--white-low-opacity), var(--white-low-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}

.element2 {
	background: 
        linear-gradient(var(--white-high-opacity), var(--white-high-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}
    
.element3 {
	background: 
        linear-gradient(var(--black-low-opacity), var(--black-low-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}

.element4 {
	background: 
        linear-gradient(var(--black-high-opacity), var(--black-high-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}
<div class="element1">hello world</div>
<div class="element2">hello world</div>
<div class="element3">hello world</div>
<div class="element4">hello world</div>


Не потрібно вказувати розмір фону - градієнти не мають внутрішнього розміру і автоматично розтягнуться в результаті.
BoltClock

@BoltClock Так, я буквально думав про це, коли публікував це, це було просто трохи пограти в кодені;). Очистили зараз, дякую!
roberrrt-s

Це розумно, я не думав надшарувати градієнти суцільного кольору один над одним, коли минулого року я відповів на подібне питання . Це питання, мабуть, більш загальне так, як воно було написане, на те, на що я відповів, було дуже конкретним випадком використання.
BoltClock

Насправді це не спрацьовує, коли фони відрізняються, але тепер я припускаю білий фон (255,255,255) при застосуванні "непрозорості". Можливо, це може бути дефолтом до основного кольору фону OP. Але знову ж таки, білий фон, ймовірно, відповідатиме потребі самих світлих кольорів, щоб люди цього не помітили.
roberrrt-s

1
Я щойно виявив щось інше, що є досить неймовірним. Зараз я опублікував відповідь.
BoltClock

1
:root{
--color: 255, 0, 0;
}

#element{
    background-color: rgba(var(--color), opacity);
}

де ви замінюєте непрозорість чим-небудь між 0 і 1


Це спроба відповісти на запитання? Тому що якщо так, код насправді не має сенсу. Особливо rgba(var(--color), opacity)шматочок. Тим більше, що ваша власна властивість - це вся позначення rgb (). Але також через ключове слово «непрозорість».
BoltClock

здивує мої погані частини rgb не повинні бути у варі
Пірд-лорд

1

SCSS / SASS

Перевага: Ви можете просто використовувати значення шістнадцяткових кольорів, замість цього використовувати 8 біт для кожного каналу (0-255).

Ось як я це зробив з початковою ідеєю: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

Редагувати: Ви також можете змінити функцію альфа, щоб просто використовувати #{$color-name}-rgbта опускати згенеровані змінні * -r, * -g, * -b CSS.


Результат

body {
  --main-color: rgb(170, 68, 204);
  --main-color-rgb: 170,68,204;
  --main-color-r: 170;
  --main-color-g: 68;
  --main-color-b: 204;
}

.button-test {
  // Generated from the alpha function
  color: rgba(var(--main-color-r), var(--main-color-g), var(--main-color-b), 0.5);
  // OR (you wrote this yourself, see usage)
  color: rgba(var(--main-color-rgb), 0.5);
}

Використання:

body {
    @include defineColorRGB(--main-color, #aa44cc);
}

.button-test {
  // With alpha function:
  color: alpha(var(--main-color), 0.5);
  // OR just using the generated variable directly
  color: rgba(var(--main-color-rgb), 0.5);
}

Mixin та функції

@mixin defineColorRGB($color-name, $value) {
    $red: red($value);
    $green: green($value);
    $blue: blue($value);
    #{$color-name}: unquote("rgb(#{$red}, #{$green}, #{$blue})");
    #{$color-name}-rgb: $red,$green,$blue;
    #{$color-name}-r: $red;
    #{$color-name}-g: $green;
    #{$color-name}-b: $blue;
}

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

@function alpha($color, $opacity) {
    $color: str-replace($color, 'var(');
    $color: str-replace($color, ')');
    $color-r: var(#{$color+'-r'});
    $color-g: var(#{$color+'-g'});
    $color-b: var(#{$color+'-b'});
    @return rgba($color-r, $color-g, $color-b, $opacity);
}

Сподіваємось, це врятує когось деякий час.


1
Мені подобається такий підхід. Спасибі
tonygatta

0

Ви можете встановити конкретну змінну / значення для кожного кольору - оригінальний і той, що має непрозорість:

:root {
  --color: #F00;
  --color-opacity: rgba(255, 0, 0, 0.5);
}
#a1 {
  background: var(--color);
} 
#a2 {
  background: var(--color-opacity);
}
<div id="a1">asdf</div>
<div id="a2">asdf</div>

Якщо ви не можете використовувати це, і ви все в порядку з рішенням javascript, ви можете використовувати це:

$(function() {
  $('button').click(function() {
    bgcolor = $('#a2').css('backgroundColor');
    rgb_value = bgcolor.match(/\d+,\s?\d+,\s?\d+/)[0]
    $('#a2').css('backgroundColor', 'rgba(' + rgb_value + ', 0.5)');
  });
});
:root {
  --color: #F00;
}
#a1 {
  background: var(--color);
} 
#a2 {
  background: var(--color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1">asdf</div>
<div id="a2">asdf</div>
<button>Click to change opacity</button>


1
Значення непрозорості зміниться, тому було б прикро створювати змінну для кожної непрозорості.
JoshyRobot

-1

Для використання rgba () із загальною змінною css, спробуйте це:

  1. Заявіть про свій колір всередині: root, але не використовуйте rgb (), як це роблять інші відповіді. просто запишіть значення

:root{
  --color : 255,0,0;
  }

  1. Використовуйте змінну --кольору, використовуючи var () як інші відповіді

#some-element {
  color : rgba(var(--color),0.5);
}


-3

У CSS ви повинні мати можливість використовувати значення rgba:

#element {
  background: rgba(240, 240, 240, 0.5);
}

або просто встановити непрозорість:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}

1
Я не в змозі жорстко кодувати значення rgba, я використовую кольорові змінні. Я повинен був сказати, що не можу використовувати непрозорість, оскільки у мене буде фонове зображення, яке не повинно бути прозорим.
JoshyRobot

Це не є рішенням, якщо ви хочете, щоб BG мав прозорість, але повний елемент має непрозорість, а потім додавання непрозорості до всього не корисно.
Левідпс

-4

Якщо ви любите шестигранні кольори, як я, є ще одне рішення. Шістнадцяткове значення - 6 цифр, після чого - це значення альфа. 00 - 100% прозорість 99 - це приблизно 75%, тоді вона використовує алфавіт "a1-af", потім "b1-bf", що закінчується на "ff", що є 100% непрозорим.

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}

1
На жаль, я не думаю, що це працює. 8-розрядна підтримка шістнадцяткового коду починає поширюватися, але це не схоже на хитрість, що використовується для прийнятої відповіді. Приклад: jsbin.com/nacuharige/edit?css,output
JoshyRobot

Це не працює, хоча це було б чудовим рішенням, якби це було.
Braden Rockwell Napier
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.