Wie wende ich Deckkraft auf eine CSS-Farbvariable an?

144

Ich entwerfe eine App in Elektron, damit ich Zugriff auf CSS-Variablen habe. Ich habe eine Farbvariable definiert in vars.css:

:root {
  --color: #f0f0f0;
}

Ich möchte diese Farbe verwenden main.css, aber mit etwas Deckkraft:

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

Wie würde ich das machen? Ich benutze keinen Präprozessor, nur CSS. Ich würde eine reine CSS-Antwort bevorzugen, aber ich werde JavaScript / jQuery akzeptieren.

Ich kann nicht verwenden, opacityda ich ein Hintergrundbild verwende, das nicht transparent sein sollte.

JoshyRobot
quelle
Klingt also
Ich würde es vorziehen, es nicht zu
tun
3
AHHHHH !!!!! Das ist so nervig! Es ist jetzt fast 2020. Der Farbwähler erhält # Hex-Farben. alpha / rgba funktioniert in Sass / Stylus nicht - weil es kein rgb-Wert ist. Sollte ich für jede einzelne Farbe 4 Schieberegler in mein CMS einfügen?
Sheriffderek

Antworten:

240

Sie können einen vorhandenen Farbwert nicht übernehmen und einen Alphakanal darauf anwenden. Sie können nämlich keinen vorhandenen Hex-Wert wie z#f0f0f0 eine Alpha-Komponente angeben und den resultierenden Wert mit einer anderen Eigenschaft verwenden.

Mit benutzerdefinierten Eigenschaften können Sie Ihren Hex-Wert jedoch zur Verwendung in ein RGB-Triplett konvertieren rgba(), diesen Wert in der benutzerdefinierten Eigenschaft (einschließlich der Kommas!) Speichern, diesen Wert mithilfe var()in eine rgba()Funktion mit Ihrem gewünschten Alpha-Wert ersetzen einfach arbeiten:

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

Dies scheint fast zu schön, um wahr zu sein. 1 Wie funktioniert es?

Die Magie liegt in der Tatsache, dass die Werte von benutzerdefinierten Eigenschaften wie beim Ersetzen von var()Referenzen in einem Eigenschaftswert ersetzt werden, bevor der Wert dieser Eigenschaft berechnet wird. Dies bedeutet, dass in Bezug auf benutzerdefinierte Eigenschaften der Wert von --colorin Ihrem Beispiel überhaupt kein Farbwert ist, bisvar(--color) irgendwo ein Ausdruck erscheint, der einen Farbwert erwartet (und nur in diesem Kontext). Aus Abschnitt 2.1 der CSS-Variablen-Spezifikation:

Die zulässige Syntax für benutzerdefinierte Eigenschaften ist äußerst zulässig. Die Produktion <declaration-value> stimmt mit einer beliebigen Sequenz eines oder mehrerer Token überein, sofern die Sequenz nicht <bad-string-token>, <bad-url-token>, nicht übereinstimmendes <) - Token>, <] - enthält. Token> oder <} - Token> oder <semicolon-token> -Token der obersten Ebene oder <delim-token> -Token mit dem Wert "!".

Das Folgende ist beispielsweise eine gültige benutzerdefinierte Eigenschaft:

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

Während dieser Wert als Variable offensichtlich unbrauchbar ist, da er in jeder normalen Eigenschaft ungültig wäre, kann er von JavaScript gelesen und verarbeitet werden.

Und Abschnitt 3 :

Wenn eine Eigenschaft eine oder mehrere var () - Funktionen enthält und diese Funktionen syntaktisch gültig sind, muss angenommen werden, dass die Grammatik der gesamten Eigenschaft zum Zeitpunkt der Analyse gültig ist. Es wird nur zur Zeit des berechneten Werts syntaktisch überprüft, nachdem var () -Funktionen ersetzt wurden.

Dies bedeutet, dass der 240, 240, 240oben angezeigte Wert direkt in die rgba()Funktion eingesetzt wird, bevor die Deklaration berechnet wird. Also das:

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

rgba()Dies scheint zunächst kein gültiges CSS zu sein, da nicht weniger als vier durch Kommas getrennte numerische Werte erwartet werden:

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

Das ist natürlich vollkommen gültiges CSS.

Wenn Sie noch einen Schritt weiter gehen, können Sie die Alpha-Komponente in einer eigenen benutzerdefinierten Eigenschaft speichern:

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

und ersetzen Sie es mit dem gleichen Ergebnis:

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

Auf diese Weise können Sie verschiedene Alpha-Werte festlegen, die Sie im laufenden Betrieb austauschen können.


1 Nun, wenn Sie das Code-Snippet in einem Browser ausführen, der keine benutzerdefinierten Eigenschaften unterstützt.

BoltClock
quelle
12
Das ist wunderschön
roberrrt-s
1
@Roberrrt: Das hätte ich schon früh erkennen müssen, da ich diese Antworten bereits gepostet habe .
BoltClock
2
Wenn wir diese Variante verwenden, warum nicht etwas verwenden wie : .element2 { background-color: rgba(var(--red), var(--low-opacity); }. Auf diese Weise können Sie die Verwendung von Variablen voll ausnutzen :).
Roberrrt-s
7
Leider kann der Wert "240, 240, 240"mit einem Farbwähler nicht bearbeitet werden. Das ist ein großer Fehler, wenn Sie die richtigen Farben für Ihre GUI finden müssen.
GetFree
1
@ s3c Die Syntax var(--hex-color)99wird in zwei Token konvertiert #333333 99(beachten Sie den Platz zum Trennen von Token), was offensichtlich nicht das ist, was Sie wollen. Benutzerdefinierte Eigenschaften wurden ursprünglich zum Kopieren von Token und nicht von Zeichenfolgen definiert. Dies ist das Endergebnis. Es ist viel zu spät, dies jetzt zu beheben.
Mikko Rantalainen
19

Ich weiß, dass das OP keinen Präprozessor verwendet, aber mir wäre geholfen worden, wenn die folgenden Informationen Teil der Antwort hier gewesen wären (ich kann noch keinen Kommentar abgeben, sonst hätte ich die @ BoltClock-Antwort kommentiert.

Wenn Sie z. B. scss verwenden, schlägt die obige Antwort fehl, da scss versucht, die Stile mit einer scss-spezifischen Funktion rgba () / hsla () zu kompilieren, für die 4 Parameter erforderlich sind. Rgba () / hsla () sind jedoch auch native CSS-Funktionen, sodass Sie die SCSS-Funktion mithilfe der Zeichenfolgeninterpolation umgehen können.

Beispiel (gültig in 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>

Beachten Sie, dass die Zeichenfolgeninterpolation für Nicht-CSS-Scss-Funktionen nicht funktioniert, z. B. lighten()weil der resultierende Code kein funktionales CSS ist. Es wäre jedoch immer noch ein gültiges scss, sodass Sie keinen Fehler bei der Kompilierung erhalten würden.

SimplyPhy
quelle
4
Wenn Sie native CSS-Farbfunktionen in Ihren Sass .scss-Dateien bevorzugen, können Sie die folgenden Funktionsdefinitionen oben in Ihre Datei einfügen, um die Sass-Behandlung zu überschreiben und sie durchzulassen: @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
rgbaist rgbseit geraumer Zeit ein Synonym für . Sie dürfen daher das "a" fallen lassen.
s3c
1
Eine andere Problemumgehung für scss-Dateien ist die Verwendung von Großbuchstaben ( RGB), die dann von sass ignoriert werden. ZB : color: RGB(var(--color_rgb), 0.5);. Von GitHub
Jono Job
9

Ich war in einer ähnlichen Situation, aber leider funktionierten die angegebenen Lösungen für mich nicht, da die Variablen alles von rgbbis hslbis hexoder sogar Farbnamen sein konnten.
Ich habe dieses Problem jetzt gelöst, indem ich das background-colorund das opacityauf ein Pseudo :afteroder :beforeElement angewendet habe:

.container {
    position: relative;
}

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

Je nach dem Element, auf das der Hintergrund angewendet werden soll, müssen die Stile möglicherweise ein wenig geändert werden.
Es funktioniert möglicherweise nicht in allen Situationen, aber hoffentlich hilft es in einigen Fällen, in denen die anderen Lösungen nicht verwendet werden können.

Bearbeiten: Mir ist gerade aufgefallen, dass diese Lösung offensichtlich auch die Textfarbe beeinflusst, da sie ein Element vor dem Zielelement erstellt und eine transparente Hintergrundfarbe darauf anwendet.
Dies kann in einigen Fällen ein Problem sein.

Springrbua
quelle
Dies hat nicht nur den Vorteil, dass eine flexiblere Angabe der Farbe (z. B. eines Namens oder rgboder HSL) möglich ist, sondern auch Konflikte zwischen nativen CSS-Farbfunktionen und den Farbfunktionen von Sass vermieden werden. Siehe die Antwort von SimplyPhy unten.
Jim Ratliff
1
Ich denke, es ist besser zu verwenden, :beforedamit Sie die richtige Stapelreihenfolge erhalten, ohne damit zu spielen z-index.
Mikko Rantalainen
5

Dies ist in der Tat mit CSS möglich . Es ist nur ein bisschen schmutzig und Sie müssen Farbverläufe verwenden. Ich habe als Beispiel ein kleines Snippet codiert. Beachten Sie, dass Sie für dunkle Hintergründe die schwarze Deckkraft verwenden sollten, für helle die weißen:

: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
quelle
Sie müssen keine Hintergrundgröße angeben - Farbverläufe haben keine intrinsische Größe und werden dadurch automatisch gedehnt.
BoltClock
@BoltClock Ja, ich habe buchstäblich daran gedacht, als ich es gepostet habe, es war nur ein bisschen herumspielen im Codepen;). Jetzt aufgeräumt, danke!
Roberrrt-s
Das ist klug, ich hatte nicht daran gedacht, einfarbige Farbverläufe übereinander zu legen, als ich letztes Jahr eine ähnliche Frage beantwortete . Diese Frage ist wahrscheinlich sowieso allgemeiner, wie sie geschrieben wurde. Die Frage, die ich beantwortet habe, war für einen ganz bestimmten Anwendungsfall.
BoltClock
Es funktioniert nicht wirklich, wenn die Hintergründe unterschiedlich sind. Ich gehe jetzt von einem weißen Hintergrund (255.255.255) aus, wenn ich die 'Deckkraft' anwende. Möglicherweise wird standardmäßig die Haupthintergrundfarbe von OP verwendet. Andererseits wird der weiße Hintergrund wahrscheinlich den Anforderungen der meisten helleren Farben in dem Maße entsprechen, dass die Leute dies nicht bemerken.
Roberrrt-s
1
Ich habe gerade etwas anderes entdeckt, das ziemlich unglaublich ist. Ich habe jetzt eine Antwort gepostet.
BoltClock
1
:root{
--color: 255, 0, 0;
}

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

Hier ersetzen Sie die Deckkraft durch einen Wert zwischen 0 und 1

Pizza Lord
quelle
Ist dies ein Versuch, die Frage zu beantworten? Denn wenn ja, macht der Code keinen Sinn. Besonders das rgba(var(--color), opacity)bisschen. Zumal Ihr benutzerdefinierter Eigenschaftswert die gesamte rgb () - Notation ist. Aber auch wegen des Schlüsselworts "Deckkraft".
BoltClock
woops my bad die rgb teile sollten nicht in der var sein
Pizza lord
1

SCSS / SASS

Vorteil: Sie können einfach Hex-Farbwerte verwenden, um stattdessen das 8-Bit für jeden Kanal (0-255) zu verwenden.

So habe ich es mit der ursprünglichen Idee gemacht: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

Bearbeiten: Sie können die Alpha-Funktion auch so ändern, dass nur #{$color-name}-rgbdie generierten CSS-Variablen * -r, * -g, * -b verwendet und weggelassen werden.


Ergebnis

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

Verwendung:

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 und Funktionen

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

Hoffentlich spart dies jemandem etwas Zeit.

Stefan Rein
quelle
1
Ich mag diesen Ansatz. Danke
Tonygatta
0

Sie können für jede Farbe eine bestimmte Variable / einen bestimmten Wert festlegen - das Original und die mit Deckkraft:

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

Wenn Sie dies nicht verwenden können und mit der Javascript-Lösung einverstanden sind, können Sie diese verwenden:

$(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
quelle
1
Der Deckkraftwert ändert sich, daher wäre es ärgerlich, für jede Deckkraft eine Variable zu erstellen.
JoshyRobot
-1

Versuchen Sie Folgendes, um rgba () mit einer allgemeinen CSS-Variablen zu verwenden:

  1. Deklarieren Sie Ihre Farbe im Inneren: root, aber verwenden Sie rgb () nicht wie andere Antworten. Schreiben Sie einfach den Wert

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

  1. Verwenden Sie --color variable mit var () als anderen Antworten

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

Dani Fadli
quelle
-3

In CSS sollten Sie entweder rgba-Werte verwenden können:

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

oder stellen Sie einfach die Deckkraft ein:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}
Patrick H.
quelle
1
Ich kann einen rgba-Wert nicht fest codieren, ich verwende Farbvariablen. Ich hätte erwähnen sollen, dass ich keine Deckkraft verwenden kann, da ich ein Hintergrundbild habe, das nicht transparent sein sollte.
JoshyRobot
Dies ist keine b / c-Lösung, wenn Sie nur möchten, dass der Hintergrund Transparenz hat, aber das gesamte Element Deckkraft hat. Dann ist es nicht hilfreich, alles mit Deckkraft zu versehen.
Levidps
-4

Wenn Sie Hex-Farben wie mich lieben, gibt es eine andere Lösung. Der Hex-Wert ist 6-stellig, danach ist der Alpha-Wert. 00 ist 100% Transparenz 99 ist ungefähr 75%, dann wird das Alphabet 'a1-af' verwendet, dann 'b1-bf' und endet mit 'ff', was 100% undurchsichtig ist.

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}
Seth M.
quelle
1
Leider glaube ich nicht, dass das funktioniert. Die Unterstützung für 8-stelligen Hex-Code beginnt sich zu verbreiten, aber es sieht nicht so aus, als würde der Trick, der mit der akzeptierten Antwort verwendet wird, mit ihnen funktionieren. Beispiel: jsbin.com/nacuharige/edit?css,output
JoshyRobot
Dies funktioniert nicht, obwohl es eine großartige Lösung wäre, wenn dies der Fall wäre.
Braden Rockwell Napier