Bagaimana cara menerapkan opacity ke variabel warna CSS?

169

Saya mendesain aplikasi dalam elektron, jadi saya memiliki akses ke variabel CSS. Saya telah menentukan variabel warna di vars.css:

:root {
  --color: #f0f0f0;
}

Saya ingin menggunakan warna ini main.css, tetapi dengan beberapa opacity yang diterapkan:

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

Bagaimana saya akan melakukan ini? Saya tidak menggunakan preprocessor apa pun, hanya CSS. Saya lebih suka jawaban semua-CSS, tetapi saya akan menerima JavaScript / jQuery.

Saya tidak dapat menggunakan opacitykarena saya menggunakan gambar latar yang seharusnya tidak transparan.

JoshyRobot
sumber
Jadi sepertinya Anda harus menggunakan lebih dari satu elemen ....
epascarello
Saya lebih suka tidak melakukannya, tetapi sepertinya saya harus ... :(
JoshyRobot
9
AHHHHH !!!!! Ini sangat menyebalkan! Sudah hampir tahun 2020 sekarang. Pemilih warna mendapatkan warna #hex. alpha / rgba tidak berfungsi di Sass / Stylus - karena ini bukan nilai rgb. Haruskah saya meletakkan 4 slider di CMS saya untuk setiap warna?
sheriffderek

Jawaban:

282

Anda tidak dapat mengambil nilai warna yang sudah ada dan menerapkan saluran alfa padanya. Yaitu, Anda tidak dapat mengambil nilai hex yang sudah ada seperti #f0f0f0, memberinya komponen alfa dan menggunakan nilai yang dihasilkan dengan properti lain.

Namun, sifat kustom memungkinkan Anda untuk mengkonversi nilai hex Anda menjadi triplet RGB untuk digunakan dengan rgba(), toko yang nilai dalam properti kustom (termasuk koma!), Pengganti yang nilai menggunakan var()menjadi rgba()fungsi dengan yang diinginkan nilai alpha Anda, dan itu akan hanya bekerja:

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

Ini sepertinya terlalu bagus untuk menjadi kenyataan. 1 Bagaimana cara kerjanya?

Keajaibannya terletak pada kenyataan bahwa nilai properti kustom diganti seperti saat mengganti var()referensi dalam nilai properti, sebelum nilai properti tersebut dihitung. Ini berarti bahwa sejauh sifat kustom yang bersangkutan, nilai --colordalam contoh Anda bukanlah nilai warna sama sekali sampai suatu var(--color)ekspresi muncul di suatu tempat yang mengharapkan nilai warna (dan hanya dalam konteks itu). Dari bagian 2.1 spesifikasi variabel css:

Sintaks yang diizinkan untuk properti kustom sangat permisif. Produksi <declaration-value> cocok dengan urutan apa pun dari satu atau beberapa token, selama urutan tersebut tidak berisi <bad-string-token>, <bad-url-token>, tidak cocok <) - token>, <] - token>, atau <} - token>, atau token <semicolon-token> tingkat atas atau token <delim-token> dengan nilai "!".

Misalnya, berikut ini adalah properti khusus yang valid:

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

Meskipun nilai ini jelas tidak berguna sebagai variabel, karena tidak valid di properti normal mana pun, nilai ini mungkin dibaca dan ditindaklanjuti oleh JavaScript.

Dan bagian 3 :

Jika sebuah properti berisi satu atau beberapa fungsi var (), dan fungsi tersebut valid secara sintaksis, seluruh tata bahasa properti harus dianggap valid pada waktu parse. Ini hanya diperiksa sintaksnya pada waktu nilai komputasi, setelah fungsi var () diganti.

Ini berarti bahwa 240, 240, 240nilai yang Anda lihat di atas diganti langsung ke dalam rgba()fungsi sebelum deklarasi dihitung. Jadi ini:

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

yang pada awalnya tampaknya tidak valid karena rgba()mengharapkan tidak kurang dari empat nilai numerik yang dipisahkan koma, menjadi ini:

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

yang, tentu saja, merupakan CSS yang benar-benar valid.

Selangkah lebih maju, Anda dapat menyimpan komponen alfa di properti kustomnya sendiri:

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

dan gantikan, dengan hasil yang sama:

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

Hal ini memungkinkan Anda untuk memiliki nilai alfa berbeda yang dapat Anda tukar dengan cepat.


1 Ya, jika Anda menjalankan cuplikan kode di browser yang tidak mendukung properti khusus.

BoltClock
sumber
16
Ini indah
roberrrt-s
2
@Roberrrt: Ini adalah sesuatu yang seharusnya saya sadari sejak awal, pada kenyataannya, mengingat saya memposting jawaban ini sebelumnya.
BoltClock
2
Jika kita akan var ini, mengapa tidak menggunakan sesuatu seperti: .element2 { background-color: rgba(var(--red), var(--low-opacity); }. Dengan cara ini Anda dapat memanfaatkan sepenuhnya penggunaan variabel :).
roberrrt-s
8
Sayangnya, nilainya "240, 240, 240"tidak dapat diedit dengan color picker. Itu adalah kehilangan besar ketika Anda perlu menemukan warna yang tepat untuk GUI Anda.
Dapatkan Gratis
4
@ s3c: Kabar baiknya adalah bahwa CSS Color 5 memperkenalkan beberapa fungsi baru yang keren untuk memanipulasi nilai hex yang ada, termasuk mengubah saluran alfa mereka: drafts.csswg.org/css-color-5/#colormodify
BoltClock
21

Saya tahu OP tidak menggunakan preprocessor, tetapi saya akan terbantu jika informasi berikut adalah bagian dari jawaban di sini (saya belum bisa berkomentar, kalau tidak saya akan mengomentari jawaban @BoltClock.

Jika Anda menggunakan, misalnya scss, jawaban di atas akan gagal, karena scss mencoba mengkompilasi gaya dengan fungsi rgba () / hsla () khusus scss, yang memerlukan 4 parameter. Namun, rgba () / hsla () juga merupakan fungsi css asli, sehingga Anda dapat menggunakan interpolasi string untuk melewati fungsi scss.

Contoh (valid di 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>

Perhatikan bahwa interpolasi string tidak akan berfungsi untuk fungsi scss non-CSS, seperti lighten(), karena kode yang dihasilkan tidak akan berfungsi sebagai CSS. Itu masih akan menjadi scss yang valid, jadi Anda tidak akan menerima kesalahan dalam kompilasi.

SimplyPhy
sumber
4
Jika Anda lebih suka menggunakan fungsi warna CSS asli dalam file Sass .scss Anda, Anda dapat menyertakan definisi fungsi berikut di bagian atas file Anda untuk mengganti penanganan Sass dan membuatnya melewati: @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
rgbaadalah sinonim untuk rgbbeberapa waktu sekarang .. Oleh karena itu, Anda diizinkan untuk menghapus "a".
s3c
1
Solusi lain untuk file scss adalah dengan menggunakan huruf besar ( RGB) yang kemudian diabaikan oleh sass. Misalnya: color: RGB(var(--color_rgb), 0.5);. Dari GitHub
Jono Job
Jawaban bagus! Jika Anda telah menentukan warna dalam hex, Anda dapat menambahkan kode ini untuk mengubahnya menjadi properti custom rgb::root { @each $color, $value in $colors { --#{$color}_rgb: #{red($value), green($value), blue($value)}; } }
Torsten Kolb
13

Saya berada dalam situasi yang sama, tetapi sayangnya solusi yang diberikan tidak berhasil untuk saya, karena variabel dapat berupa apa saja dari rgbhingga hslhingga hexatau bahkan nama warna.
Saya memecahkan masalah ini sekarang, dengan menerapkan background-colordan pada opacitypseudo :afteratau :beforeelemen:

.container {
    position: relative;
}

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

Gaya mungkin perlu diubah sedikit, tergantung pada elemen latar belakang harus diterapkan.
Juga mungkin tidak berfungsi untuk semua situasi, tetapi mudah-mudahan ini membantu dalam beberapa kasus, di mana solusi lain tidak dapat digunakan.

Sunting: Saya baru saja memperhatikan, bahwa solusi ini jelas juga memengaruhi warna teks, karena ini membuat elemen di depan elemen target dan menerapkan warna latar transparan padanya.
Ini mungkin menjadi masalah dalam beberapa kasus.

Springrbua
sumber
Ini tidak hanya memiliki keuntungan karena memungkinkan spesifikasi warna yang lebih fleksibel (misalnya, nama, atau rgbatau HSL) tetapi juga menghindari konflik antara fungsi warna CSS asli dan fungsi warna Sass. Lihat jawaban SimplyPhy di bawah.
Jim Ratliff
1
Saya pikir lebih baik digunakan :beforesehingga Anda mendapatkan urutan penumpukan yang tepat tanpa bermain-main z-index.
Mikko Rantalainen
5

Ini memang mungkin dengan CSS . Hanya sedikit kotor, dan Anda harus menggunakan gradien. Saya telah mengkodekan potongan kecil sebagai contoh, perhatikan bahwa untuk latar belakang gelap, Anda harus menggunakan opasitas hitam, seperti untuk terang-putih .:

: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
sumber
Anda tidak perlu menentukan ukuran latar belakang - gradien tidak memiliki ukuran intrinsik dan sebagai hasilnya akan meregang secara otomatis.
BoltClock
@BoltClock Ya, saya benar-benar memikirkan bahwa ketika saya mempostingnya, itu hanya sedikit bermain-main di codepen;). Sudah dibersihkan sekarang, terima kasih!
roberrrt-s
Ini pintar, saya tidak pernah berpikir untuk melapisi gradien warna solid satu sama lain ketika saya menjawab pertanyaan serupa tahun lalu. Pertanyaan ini mungkin lebih umum dari cara penulisannya, yang saya jawab adalah untuk kasus penggunaan yang sangat spesifik.
BoltClock
Ini tidak benar-benar berfungsi ketika latar belakangnya berbeda, saya sekarang mengasumsikan latar belakang putih (255.255.255) saat menerapkan 'opacity'. Itu mungkin bisa default ke warna latar belakang utama OP. Tapi sekali lagi, latar belakang putih mungkin akan sesuai dengan kebutuhan warna yang paling terang sehingga orang tidak akan menyadarinya.
roberrrt-s
1
Saya baru saja menemukan hal lain yang sangat luar biasa. Saya sekarang telah memposting jawaban.
BoltClock
1
:root{
--color: 255, 0, 0;
}

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

di mana Anda mengganti opacity dengan apa pun antara 0 dan 1

Tuan pizza
sumber
Apakah ini upaya menjawab pertanyaan? Karena jika demikian, kodenya tidak masuk akal. Terutama rgba(var(--color), opacity)bagiannya. Terutama karena nilai properti khusus Anda adalah seluruh notasi rgb (). Tetapi juga karena kata kunci "opacity".
BoltClock
woops my bad the rgb parts should not in the var
Pizza lord
1

SCSS / SASS

Keuntungan: Anda bisa menggunakan nilai warna Hex, alih-alih menggunakan 8 Bit untuk setiap saluran (0-255).

Beginilah cara saya melakukannya dengan ide awal: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

Edit: Anda juga dapat memodifikasi fungsi alfa untuk hanya menggunakan #{$color-name}-rgbdan menghilangkan variabel CSS * -r, * -g, * -b yang dihasilkan.


Hasil

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

Pemakaian:

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 dan fungsinya

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

Semoga ini akan menghemat waktu seseorang.

Stefan Rein
sumber
1
Saya suka pendekatan ini. Terima kasih
tonygatta
-1

Anda dapat mengatur variabel / nilai tertentu untuk setiap warna - yang asli dan yang memiliki opasitas:

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

Jika Anda tidak dapat menggunakan ini dan Anda baik-baik saja dengan solusi javascript, Anda dapat menggunakan yang ini:

$(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
sumber
1
Nilai opasitas akan berubah, jadi membuat variabel untuk setiap opasitas akan mengganggu.
JoshyRobot
-3

Untuk menggunakan rgba () dengan variabel css umum, coba ini:

  1. Deklarasikan warna Anda di dalam: root, tetapi jangan gunakan rgb () seperti jawaban lain. tulis saja nilainya

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

  1. Gunakan variabel --color menggunakan var () sebagai jawaban lain

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

Dani Fadli
sumber
-4

Di CSS Anda harus dapat menggunakan nilai rgba:

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

atau cukup setel opasitas:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}
Patrick H.
sumber
1
Saya tidak dapat melakukan hardcode pada nilai rgba, saya menggunakan variabel warna. Saya seharusnya menyebutkan bahwa saya tidak dapat menggunakan opacity karena saya akan memiliki gambar latar belakang yang seharusnya tidak transparan.
JoshyRobot
Ini bukan solusi b / c jika Anda hanya ingin BG memiliki transparansi tetapi elemen penuh memiliki opasitas, lalu menambahkan opasitas ke semuanya tidak membantu.
Levidps
-4

Jika Anda menyukai warna hex seperti saya, ada solusi lain. Nilai hex adalah 6 digit setelah itu adalah nilai alpha. 00 adalah 100% transparansi 99 adalah sekitar 75% kemudian menggunakan alfabet 'a1-af' lalu 'b1-bf' diakhiri dengan 'ff' yang 100% buram.

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}
Seth M
sumber
1
Sayangnya, menurut saya ini tidak berhasil. 8 digit dukungan kode hex mulai menyebar, tetapi sepertinya trik yang digunakan dengan jawaban yang diterima tidak berfungsi dengan mereka. Contoh: jsbin.com/nacuharige/edit?css,output
JoshyRobot
Ini tidak berhasil, meskipun akan menjadi solusi yang bagus jika berhasil.
Braden Rockwell Napier