Jak zastosować krycie do zmiennej koloru CSS?

144

Projektuję aplikację w electron, więc mam dostęp do zmiennych CSS. Zdefiniowałem zmienną koloru w vars.css:

:root {
  --color: #f0f0f0;
}

Chcę użyć tego koloru main.css, ale z pewnym kryciem:

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

Jak bym to zrobił? Nie używam żadnego preprocesora, tylko CSS. Wolałbym odpowiedź w całości CSS, ale akceptuję JavaScript / jQuery.

Nie mogę użyć, opacityponieważ używam obrazu tła, który nie powinien być przezroczysty.

JoshyRobot
źródło
Wygląda na to, że powinieneś używać więcej niż jednego elementu ...
epascarello
Wolałbym tego nie robić, ale wygląda na to, że będę musiał ... :(
JoshyRobot
4
AHHHHH !!!!! To takie denerwujące! Już prawie 2020 rok. Próbnik kolorów pobiera kolory #hex. alpha / rgba nie działa w Sass / Stylus - ponieważ nie jest to wartość rgb. Czy powinienem umieścić 4 suwaki w moim CMS dla każdego koloru?
szeryfderek

Odpowiedzi:

240

Nie możesz wziąć istniejącej wartości koloru i zastosować do niej kanał alfa. Mianowicie, nie możesz wziąć istniejącej wartości szesnastkowej, takiej jak #f0f0f0nadać jej składnik alfa i użyć wynikowej wartości z inną właściwością.

Jednak właściwości niestandardowe umożliwiają konwersję wartości szesnastkowej na trójkę RGB do użycia z rgba(), przechowywanie tej wartości we właściwości niestandardowej (łącznie z przecinkami!), Zastąpienie tej wartości za var()pomocą rgba()funkcji żądaną wartością alfa, a po prostu pracuj:

: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>

Wydaje się to zbyt piękne, aby mogło być prawdziwe. 1 Jak to działa?

Magia polega na tym, że wartości właściwości niestandardowych są zastępowane tak, jak ma to miejsce podczas zastępowania var()odniesień w wartości właściwości, zanim wartość tej właściwości zostanie obliczona. Oznacza to, że o ile właściwości niestandardowe są zainteresowane, wartość --colorw przykładzie nie jest wartością koloru w ogóle do var(--color)wypowiedzi pojawia gdzieś, że spodziewa się, że wartość koloru (i tylko w tym kontekście). Z sekcji 2.1 specyfikacji zmiennych css:

Dozwolona składnia właściwości niestandardowych jest wyjątkowo liberalna. Produkcja <declaration-value> pasuje do dowolnej sekwencji jednego lub więcej tokenów, o ile sekwencja nie zawiera <bad-string-token>, <bad-url-token>, unmatched <) - token>, <] - token> lub <} - token> lub tokeny <semicolon-token> najwyższego poziomu lub tokeny <delim-token> o wartości „!”.

Na przykład poniżej przedstawiono prawidłową właściwość niestandardową:

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

Chociaż ta wartość jest oczywiście bezużyteczna jako zmienna, ponieważ byłaby nieprawidłowa w każdej normalnej właściwości, może być odczytywana i wykonywana przez JavaScript.

I sekcja 3 :

Jeśli właściwość zawiera jedną lub więcej funkcji var (), a te funkcje są poprawne składniowo, należy założyć, że gramatyka całej właściwości jest prawidłowa w czasie analizy. Sprawdzana jest składnia tylko w czasie obliczania wartości, po podstawieniu funkcji var ().

Oznacza to, że 240, 240, 240wartość, którą widzisz powyżej, zostanie podstawiona bezpośrednio do rgba()funkcji przed obliczeniem deklaracji. Więc to:

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

który na początku nie wydaje się być prawidłowym CSS, ponieważ rgba()oczekuje nie mniej niż czterech wartości liczbowych oddzielonych przecinkami, staje się taki:

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

co oczywiście jest całkowicie poprawnym CSS.

Idąc o krok dalej, możesz przechowywać komponent alfa we własnej niestandardowej właściwości:

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

i zastąp go, z tym samym wynikiem:

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

Dzięki temu możesz mieć różne wartości alfa, które możesz wymieniać w locie.


1 Cóż, tak jest, jeśli uruchamiasz fragment kodu w przeglądarce, która nie obsługuje niestandardowych właściwości.

BoltClock
źródło
12
To jest piękne
roberrrt-s
1
@Roberrrt: Właściwie to powinienem był zdać sobie sprawę na początku, biorąc pod uwagę to, że zamieściłem te odpowiedzi wcześniej.
BoltClock
2
Jeśli mamy zamiar to var, dlaczego nie używać coś takiego: .element2 { background-color: rgba(var(--red), var(--low-opacity); }. W ten sposób możesz w pełni wykorzystać użycie zmiennych :).
roberrrt-s
7
Niestety wartości "240, 240, 240"nie można edytować za pomocą próbnika kolorów. To ogromna porażka, gdy musisz znaleźć odpowiednie kolory dla swojego GUI.
GetFree
1
@ s3c Składnia var(--hex-color)99jest konwertowana na dwa tokeny #333333 99(zwróć uwagę na miejsce na oddzielne tokeny), co oczywiście nie jest tym, czego chcesz. Właściwości niestandardowe zostały pierwotnie zdefiniowane w celu kopiowania tokenów, a nie ciągów i jest to efekt końcowy. Jest już za późno, aby to teraz naprawić.
Mikko Rantalainen
19

Wiem, że OP nie używa preprocesora, ale pomogłoby mi, gdyby następujące informacje były częścią odpowiedzi tutaj (nie mogę jeszcze komentować, w przeciwnym razie skomentowałbym odpowiedź @BoltClock.

Jeśli używasz np. Scss, powyższa odpowiedź nie powiedzie się, ponieważ scss próbuje skompilować style z funkcją rgba () / hsla () specyficzną dla scss, która wymaga 4 parametrów. Jednak rgba () / hsla () są również natywnymi funkcjami css, więc możesz użyć interpolacji ciągów, aby ominąć funkcję scss.

Przykład (ważny w 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>

Zwróć uwagę, że interpolacja ciągów nie będzie działać w przypadku funkcji scss innych niż CSS, na przykład lighten(), ponieważ wynikowy kod nie byłby funkcjonalnym CSS. Jednak nadal byłby to poprawny scss, więc nie wystąpiłby błąd podczas kompilacji.

SimplyPhy
źródło
4
Jeśli wolisz używać natywnych funkcji kolorów CSS w swoich plikach .scss Sass, możesz dołączyć następujące definicje funkcji na początku pliku, aby nadpisać obsługę Sass i sprawić, by były przekazywane: @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
rgbajest synonimem od rgbdłuższego czasu .. Dlatego możesz upuścić „a”.
s3c
1
Innym obejściem dla plików scss jest użycie wielkich liter ( RGB), które są następnie ignorowane przez sass. Np color: RGB(var(--color_rgb), 0.5);. : . Z GitHub
Jono Job
9

Byłem w podobnej sytuacji, ale niestety podane rozwiązania nie działa dla mnie, jako zmienne może być cokolwiek od rgbcelu hsldo hexlub nawet kolor nazw.
Rozwiązałem ten problem teraz, stosując background-colori opacitydo pseudo :afterlub :beforeelementu:

.container {
    position: relative;
}

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

Style mogą wymagać trochę zmiany, w zależności od elementu, do którego należy zastosować tło.
Może też nie działać we wszystkich sytuacjach, ale mam nadzieję, że pomaga w niektórych przypadkach, w których nie można zastosować innych rozwiązań.

Edycja: Właśnie zauważyłem, że to rozwiązanie oczywiście wpływa również na kolor tekstu, ponieważ tworzy element przed elementem docelowym i nakłada na niego przezroczysty kolor tła.
W niektórych przypadkach może to stanowić problem.

Springrbua
źródło
Ma to nie tylko tę zaletę, że pozwala na bardziej elastyczną specyfikację koloru (np. Nazwy, rgblub HSL), ale także pozwala uniknąć konfliktu między natywnymi funkcjami kolorów CSS a funkcjami kolorów Sass. Zobacz odpowiedź SimplyPhy poniżej.
Jim Ratliff,
1
Myślę, że lepiej jest użyć, :beforeaby uzyskać odpowiednią kolejność układania bez gry z-index.
Mikko Rantalainen
5

Jest to rzeczywiście możliwe dzięki CSS . Jest trochę brudny i będziesz musiał używać gradientów. Jako przykład zakodowałem mały fragment, zwróć uwagę, że na ciemnych tłach powinieneś używać czarnego krycia, jak dla jasnego - białego .:

: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>

roberrrt-s
źródło
Nie musisz określać rozmiaru tła - gradienty nie mają własnego rozmiaru i w rezultacie zostaną automatycznie rozciągnięte.
BoltClock
@BoltClock Tak, dosłownie pomyślałem o tym, kiedy to opublikowałem, to tylko trochę zabawy w kodepen;). Teraz posprzątane, dzięki!
roberrrt-s
To sprytne, nie myślałem o nakładaniu na siebie jednolitych gradientów kolorów, kiedy odpowiadałem na podobne pytanie w zeszłym roku. To pytanie jest prawdopodobnie bardziej ogólne i tak, jak zostało napisane, to, na które odpowiedziałem, dotyczyło bardzo konkretnego przypadku użycia.
BoltClock
Jednak to nie działa, gdy tła są inne, teraz zakładam białe tło (255,255,255), gdy stosuję „krycie”. Możliwe, że domyślny kolor to główny kolor tła OP. Ale z drugiej strony białe tło prawdopodobnie będzie pasowało do większości jaśniejszych kolorów do tego stopnia, że ​​ludzie tego nie zauważą.
roberrrt-s
1
Właśnie odkryłem coś jeszcze, co jest całkiem niesamowite. Wysłałem odpowiedź.
BoltClock
1
:root{
--color: 255, 0, 0;
}

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

gdzie zamieniasz krycie na dowolną wartość z przedziału od 0 do 1

Pan pizzy
źródło
Czy to próba odpowiedzi na pytanie? Bo jeśli tak, kod tak naprawdę nie ma sensu. Szczególnie rgba(var(--color), opacity)wędzidło. Zwłaszcza, że ​​wartością właściwości niestandardowej jest cała notacja rgb (). Ale także ze względu na słowo kluczowe „krycie”.
BoltClock
woops my zła, części rgb nie powinny być w var
pan pizzy,
1

SCSS / SASS

Zaleta: Możesz po prostu użyć wartości koloru Hex, zamiast tego użyć 8 bitów dla każdego kanału (0-255).

Tak to zrobiłem z początkowym pomysłem: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

Edycja: Możesz także zmodyfikować funkcję alfa, aby po prostu używać #{$color-name}-rgbi pomijać wygenerowane * -r, * -g, * -b zmienne CSS.


Wynik

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

Stosowanie:

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

Mieszanie i funkcje

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

Miejmy nadzieję, że pozwoli to komuś zaoszczędzić trochę czasu.

Stefan Rein
źródło
1
Podoba mi się to podejście. Dzięki
tonygatta
0

Możesz ustawić określoną zmienną / wartość dla każdego koloru - oryginalnego i tego z kryciem:

: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>

Jeśli nie możesz tego użyć i nie przeszkadza Ci rozwiązanie javascript, możesz użyć tego:

$(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>

Dekel
źródło
1
Wartość krycia ulegnie zmianie, więc tworzenie zmiennej dla każdego krycia byłoby denerwujące.
JoshyRobot
-1

Aby użyć rgba () z ogólną zmienną css, spróbuj tego:

  1. Zadeklaruj swój kolor wewnątrz: root, ale nie używaj rgb () tak, jak robią to inne odpowiedzi. po prostu wpisz wartość

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

  1. Użyj zmiennej --color, używając var () jako innych odpowiedzi

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

Dani Fadli
źródło
-3

W CSS powinieneś być w stanie użyć wartości rgba:

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

lub po prostu ustaw krycie:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}
Patrick H.
źródło
1
Nie mogę zakodować wartości rgba, używam zmiennych kolorów. Powinienem był wspomnieć, że nie mogę używać krycia, ponieważ będę mieć obraz tła, który nie powinien być przezroczysty.
JoshyRobot
To nie jest rozwiązanie b / c, jeśli chcesz, aby tylko BG miał przezroczystość, ale pełny element miał przezroczystość, wtedy dodanie krycia do wszystkiego nie jest pomocne.
Levidps
-4

Jeśli tak jak ja kochasz kolory hex, jest inne rozwiązanie. Wartość szesnastkowa składa się z 6 cyfr, a po niej jest wartością alfa. 00 to 100% przezroczystości 99 to około 75% to używa alfabetu „a1-af”, a następnie „b1-bf” kończącego się na „ff”, który jest w 100% nieprzezroczysty.

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}
Seth M.
źródło
1
Niestety nie sądzę, żeby to działało. Obsługa 8-cyfrowego kodu szesnastkowego zaczyna się rozprzestrzeniać, ale wygląda na to, że sztuczka użyta z zaakceptowaną odpowiedzią nie działa. Przykład: jsbin.com/nacuharige/edit?css,output
JoshyRobot
To nie działa, chociaż byłoby to świetne rozwiązanie, gdyby tak było.
Braden Rockwell Napier