CSS'te bir rengi elle yeniden yazmadan ondan yeni bir renk üretmenin iki yolu vardır. color-mix() renkleri seçtiğiniz bir renk uzayında, verdiğiniz oranlarda karıştırır: color-mix(in oklab, red 30%, white) gibi. Göreceli renk sözdizimi (relative color syntax) ise from anahtar kelimesiyle var olan bir rengi kanallarına ayırır ve her kanalı ayrı ayrı değiştirmenize izin verir: hsl(from var(--marka) h s calc(l + 20)) gibi. İkisi de sonuçta normal bir <color> değeri döndürür.

Bu yazıda color-mix() sözdizimini, yüzdelerin nasıl normalleştirildiğini, saydamlık eklemeyi, karıştırma uzayının sonucu nasıl değiştirdiğini ve ton (hue) enterpolasyon yöntemlerini; ardından göreceli renklerde kanal anahtar kelimelerini, calc() ile hesaplamayı ve özel özelliklerle palet üretmeyi anlatıyoruz. Renk fonksiyonlarının kendisini (rgb(), hsl(), oklch() ve diğerleri) önce CSS renk değerleri yazısından okumanızı öneririz.

color-mix() sözdizimi

MDN, fonksiyonun biçimini color-mix( <color-interpolation-method>? , [ <color> && <percentage [0,100]>? ]#) olarak verir. Okunuşu şöyledir: İsteğe bağlı olarak in ve bir renk uzayı, ardından virgülle ayrılmış bir veya daha fazla renk; her rengin yanına isteğe bağlı bir yüzde. Uzay yazılmazsa oklab kullanılır. Kutupsal bir uzayda (hsl, hwb, lch, oklch) tonun hangi yoldan karışacağını belirten bir ton enterpolasyon yöntemi de eklenebilir; yazılmazsa shorter hue geçerlidir.

css
.ornekler {
  --a: color-mix(in oklab, #a71e14 25%, white);
  /* yüzde 25 koyu kırmızı, yüzde 75 beyaz */
  --b: color-mix(in oklab, #a71e14, white);
  /* yüzde verilmedi: ikisi de yüzde 50 */
  --c: color-mix(red, blue);
  /* uzay yazılmadı: color-mix(in oklab, red, blue) ile aynı */
  --d: color-mix(in oklch, red, blue);
  /* color-mix(in oklch shorter hue, red, blue) ile aynı */
}

Fonksiyon geçerli bir <color> döndürdüğü için renk kabul eden her özellikte kullanılabilir: background-color, border-color, box-shadow içindeki renk ya da bir gradyanın renk durağı. Karıştırılan renkler herhangi bir yazımda olabilir; bir hex kodla bir adlandırılmış rengi ya da hsl() ile var(--x) değerini karıştırmakta sakınca yoktur.

Yüzdeler nasıl normalleştirilir?

Yüzdeler nasıl normalleştirilir? İkisi de yazılmamışsa p1 = p2 = yüzde 50 olur., Yalnızca biri yazılmışsa diğeri yüzde 100'den kalan kadardır: p1 yoksa p1 = 100..., İkisi de yüzde...

İki rengin yüzdeleri toplamda yüzde 100 etmek zorunda değildir; tarayıcı bunları belirli kurallarla normalleştirir. MDN iki renk için kuralları şöyle sıralar (yüzdelere p1 ve p2 diyelim):

  • İkisi de yazılmamışsa p1 = p2 = yüzde 50 olur.
  • Yalnızca biri yazılmışsa diğeri yüzde 100'den kalan kadardır: p1 yoksa p1 = 100 - p2.
  • İkisi de yüzde 0 ise fonksiyon geçersizdir.
  • Toplam yüzde 100 değilse her biri toplama bölünür: p1' = p1 / (p1 + p2), p2' = p2 / (p1 + p2).
  • Toplam yüzde 100'den küçükse sonuca ayrıca p1 + p2 kadar bir alpha çarpanı uygulanır. Bu, kalan payı transparent ile karıştırmaya benzer.
css
.hesaplar {
  --e: color-mix(in srgb, red 80%, blue 60%);
  /* toplam 140: kırmızı 80 / 140 = yaklaşık yüzde 57,1
                 mavi    60 / 140 = yaklaşık yüzde 42,9
     toplam 100'ü aştığı için alpha çarpanı yok */

  --f: color-mix(in srgb, red 30%, blue 30%);
  /* toplam 60: her biri 30 / 60 = yüzde 50
     toplam 100'den küçük: alpha çarpanı 0,6
     sonuç yüzde 60 opak, eşit karışım */
}

İkinci örnek sık şaşırtır: Yüzdeleri küçültmek renkleri "daha az karıştırmaz", oranı aynı bırakıp sonucu saydamlaştırır. Bir rengin ötekine göre daha baskın olmasını istiyorsanız oranı değiştirmeniz gerekir; sonucu yarı saydam yapmak istiyorsanız toplamı bilerek yüzde 100'ün altında tutabilirsiniz.

Saydamlık eklemek: transparent ile karıştırma

MDN'nin örneklerinden biri, bir rengi transparent ile karıştırarak saydamlaştırmaktır. Rengin payı ne kadar azsa sonuç o kadar saydam olur. Yüzde verilmezse sonuç, temel rengin yarısı kadar opaktır. Bu yöntem renk zaten yarı saydam olsa bile çalışır.

css
:root {
  --base: red;
}

.rozet-25 {
  background-color: color-mix(in srgb, var(--base) 25%, transparent);
  /* --base rengi, yüzde 25 opaklıkta */
}

.rozet-yarim {
  background-color: color-mix(in srgb, var(--base), transparent);
  /* yüzde verilmedi: --base rengi yarı opak */
}

Bunun bir sınırı vardır: MDN'ye göre color-mix() yarı saydam bir rengi tam opak yapamaz, çünkü karıştırma alpha değerini yalnızca düşürebilir. Saydamlığı artırmak ya da tam opak yapmak için göreceli renk sözdizimiyle alpha kanalına doğrudan değer yazmanız gerekir. Bunu aşağıda göreceğiz.

Karıştırma uzayını seçmek

Aynı iki renk farklı uzaylarda karıştırıldığında farklı sonuç verir. MDN seçim için şu yönlendirmeyi yapar: Fiziksel olarak renkli ışıkların karışımını taklit etmek istiyorsanız ışık şiddetine göre doğrusal olan CIE XYZ veya srgb-linear uygundur. Renklerin algısal olarak eşit aralıklı olması gerekiyorsa (örneğin bir gradyanda) algısal olarak tekdüze tasarlanmış Oklab ve eski Lab uygundur. Karışımın ortasında renklerin grileşmesini önlemek, yani kromayı mümkün olduğunca yüksek tutmak istiyorsanız Oklch ve eski LCH iyi sonuç verir. sRGB ise ancak sRGB kullanan belirli bir cihaz ya da yazılımın davranışını eşleştirmeniz gerekiyorsa tercih edilmelidir; MDN bu uzayın ne ışığa göre doğrusal ne de algısal olarak tekdüze olduğunu, aşırı koyu veya grimsi karışımlar üretebildiğini belirtir.

AmaçÖnerilen uzayMDN'ye göre gerekçe
Işık karışımını taklitxyz, srgb-linearIşık şiddetine göre doğrusal
Eşit algılanan adımlaroklab, labAlgısal olarak tekdüze
Grileşmeyi önlemekoklch, lchKromayı geçiş boyunca korur
Eski bir sistemle eşleşmesrgbYalnızca uyum gerekiyorsa

Uzaylar iki gruba ayrılır. Dikdörtgen uzaylar srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb, rec2020, lab, oklab, xyz, xyz-d50 ve xyz-d65'tir; bunlarda her bileşen düz bir çizgi üzerinde karışır. Kutupsal uzaylar hsl, hwb, lch ve oklch'tir; bunlarda ton bir açıdır ve renk çemberinde iki yönden birine doğru ilerleyebilir.

Dikdörtgen bir uzayda karışımın ne yaptığını en kolay sRGB'de görebilirsiniz. MDN'nin renk sayfasına göre enterpolasyonda her bileşen doğrusal olarak hesaplanır. red sRGB'de rgb(255 0 0), blue ise rgb(0 0 255)'dir. Eşit karışımda kırmızı kanal (255 + 0) / 2 = 127,5, mavi kanal (0 + 255) / 2 = 127,5 olur ve sonuç rgb(127.5 0 127.5) değerine denk bir mordur. Aynı iki renk oklab veya oklch içinde karıştırıldığında ara renk farklı bir tonda ve açıklıkta çıkar; farkı görmek için kutuları yan yana koyup karşılaştırmak yeterlidir.

Ton enterpolasyonu: shorter, longer, increasing, decreasing

Ton enterpolasyonu: shorter, longer, increasing, decreasing

Kutupsal bir uzayda iki ton açısı renk çemberini iki yaya böler. Hangi yayın kullanılacağını <hue-interpolation-method> belirler ve dört değeri vardır: shorter hue kısa yayı, longer hue uzun yayı kullanır; increasing hue saat yönündeki, decreasing hue saat yönünün tersindeki yayı seçer. Varsayılan shorter hue'dur. MDN, belirli koşullarda bu yöntemlerin ikişer ikişer aynı sonucu verdiğini belirtir: İki açı arasındaki fark 0 ile 180 derece arasındaysa shorter ile increasing aynı, longer ile decreasing aynı yayı seçer.

css
.ton-yollari {
  --kisa: color-mix(in oklch, red, blue);
  /* varsayılan: shorter hue */
  --uzun: color-mix(in oklch longer hue, red, blue);
  /* çemberin öbür tarafından dolaşır, ara renk farklı bir tondur */
  --artan: color-mix(in lch increasing hue, hsl(200deg 50% 80%), coral);
}

increasing ve decreasing değerlerinin bir avantajı vardır: Bir geçiş ya da animasyon sırasında açı farkı 180 dereceden geçtiğinde yay öbür tarafa atlamaz. shorter ve longer ise bu noktada yön değiştirebilir. Animasyonlu renk geçişleri yazıyorsanız transition yazısındaki örneklerde bu ayrıntıyı hesaba katın. Aynı in <uzay> sözdizimi gradyan fonksiyonlarında da geçerlidir; gradyan yazısında linear-gradient(in oklch longer hue, ...) gibi örnekler bulabilirsiniz.

Birden fazla rengi karıştırmak

Yerel kopyadaki MDN sayfası, color-mix()'in yalnızca iki değil herhangi sayıda renk kabul ettiğini gösterir. Tek renk verildiğinde sonuç o rengin kendisidir. Yüzdeler verilmezse her renk eşit pay alır. MDN'nin örneği bu biçimi desteklemeyen tarayıcılar için ayrıca bir @supports not uyarısı ekler; bu da özelliğin her yerde bulunmayabileceğinin işaretidir.

css
.liste {
  --tek: color-mix(in oklab, teal);
  /* sonuç: teal */
  --uclu: color-mix(in oklab, teal 20%, olive 30%, blue 50%);
  --dortlu: color-mix(in oklab, teal, olive, blue, purple);
  /* yüzde yok: her biri eşit pay alır */
}

@supports not (color: color-mix(in oklab, red, white, blue)) {
  .liste {
    /* renk listesi desteklenmiyorsa burada iki renkli yedek tanımlayın */
  }
}

@supports kuralının kendisi @supports yazısında ayrıntılı olarak anlatılıyor.

Göreceli renk sözdizimi: from ile türetme

Göreceli renkler, tanıdığınız renk fonksiyonlarını farklı parametrelerle kullanır. Genel biçim renk-fonksiyonu(from köken-renk kanal1 kanal2 kanal3 / alpha) şeklindedir. from anahtar kelimesinden sonra gelen köken renk herhangi bir geçerli renk olabilir: bir özel özellik, bir sistem rengi, currentColor ya da başka bir göreceli renk. Tarayıcı köken rengi seçtiğiniz fonksiyonun modeline çevirir, kanallarına ayırır ve bu kanalları fonksiyonun içinde adlarıyla kullanmanıza izin verir: rgb() içinde r, g, b; hsl() içinde h, s, l; oklch() içinde l, c, h; hepsinde ayrıca alpha.

Önemli bir fark alpha kanalındadır: Mutlak renklerde alpha yazılmazsa yüzde 100 kabul edilir, göreceli renklerde ise köken rengin alpha değeri korunur. Bir ayrıntı daha: MDN'ye göre rgb(), hsl() ve hwb() ile üretilen göreceli renkler, görünür renklerin tamamını ifade edebilmek için color(srgb ...) biçiminde serileştirilir; JavaScript ile okuduğunuzda bu biçimi görürsünüz.

css
.turetme {
  --a: rgb(from red r g b);
  /* köken renkle aynı: kanallar olduğu gibi kullanıldı */
  --b: rgb(from rgb(200 0 0) r r r);
  /* üç kanal da 200: rgb(200 200 200), açık gri */
  --c: rgb(from rgb(200 170 0) b g r);
  /* kanallar ters sırada: rgb(0 170 200) */
  --d: hsl(from rgb(255 0 0) h 30% 60%);
  /* ton korunur (0), sonuç hsl(0 30% 60%) */
}

İlk iki örnek MDN'nin de belirttiği gibi gerçek anlamda "göreceli" değildir; biri köken rengi aynen döndürür, diğeri kanalları istediğiniz gibi yeniden dizebileceğinizi gösterir. Asıl kullanım son örnekteki gibidir: Kökenden bazı kanalları alır, bazılarını değiştirirsiniz. hsl(0 30% 60%) sonucunu sRGB'ye çevirirsek kroma (1 - |2 x 0,6 - 1|) x 0,3 = 0,8 x 0,3 = 0,24, alt değer 0,6 - 0,24 / 2 = 0,48 olur; kırmızı kanal 0,48 + 0,24 = 0,72, yeşil ve mavi 0,48 kalır. Bu da MDN'nin verdiği color(srgb 0.72 0.48 0.48) değeriyle örtüşür.

calc() ile kanal hesaplamak ve sayı kuralı

Göreceli renklerin gücü kanal değerlerini calc() gibi matematik fonksiyonlarıyla hesaplayabilmekten gelir. Burada en çok yapılan hata birimlerle ilgilidir. MDN'ye göre köken rengin kanalları her zaman <number> değerine çözülür: Yüzde olarak yazılmış kanallar uygun bir sayıya, ton açıları 0 ile 360 arasında bir derece sayısına dönüşür. Bu yüzden calc(l + 20) geçerlidir ama calc(l + 20%) geçersizdir, çünkü bir sayıya yüzde eklenemez. hsl() içinde s ve l 0 ile 100 arasında sayıdır; oklch() içinde l 0 ile 1 arasındadır.

css
:root {
  --marka: purple;
}

.acik {
  background-color: lch(from var(--marka) calc(l + 20) c h);
  /* açıklık 20 birim artar, kroma ve ton aynı */
}

.koyu {
  background-color: lch(from var(--marka) calc(l - 20) c h);
}

.hatali {
  background-color: hsl(from var(--marka) h s calc(l + 20%));
  /* geçersiz: l bir sayıdır, yüzde eklenemez; bildirim yok sayılır */
}

.oklch-acik {
  background-color: oklch(from var(--marka) calc(l + 0.1) c h);
  /* oklch'de l 0 ile 1 arasında: 0.1 eklenir */
}

Bu kalıp, tek bir marka renginden açık ve koyu tonlar üretmenin pratik yoludur. Ana renk değiştiğinde bütün türevler kendiliğinden güncellenir. Kanal değerlerini clamp() ile sınırlamak da mümkündür; matematik fonksiyonlarının ayrıntısı calc(), min(), max() ve clamp() yazısında anlatılıyor.

Alpha kanalını değiştirmek

MDN'nin alpha örneğinde aynı teal rengi iki iç içe öğeye verilir ve saydamlık bir özel özellikle çarpılır. Değişken her öğede farklı tanımlandığı için aynı kural iki farklı sonuç üretir. color-mix()'in yapamadığı şeyi, yani saydamlığı artırmayı da bu yöntemle yaparsınız: / 1 yazmak rengi tam opak hâle getirir.

css
div {
  background-color: rgb(from teal r g b / calc(alpha * var(--carpan)));
}

.kapsayici {
  --carpan: 0.3;
  /* teal, yüzde 30 opak */
}

.oge {
  --carpan: 1;
  /* teal, tam opak */
}

.opak-yap {
  background-color: rgb(from var(--yari-saydam) r g b / 1);
  /* köken ne kadar saydam olursa olsun sonuç tam opak */
}

Yalnızca alpha kanalıyla ilgileniyorsanız MDN'de alpha() adlı ayrı bir fonksiyon da belgelenmiştir: alpha(from var(--renk) / 80%) rengin diğer bileşenlerini aynen korur, sonucu köken rengin uzayında döndürür ve yalnızca saydamlığı değiştirir. İçinde alpha anahtar kelimesi köken rengin saydamlığını verir, örneğin calc(alpha * 0.5) saydamlığı yarıya indirir. Bu fonksiyon için de uyumluluk tablosunu kontrol edin.

sRGB gamı dışındaki köken renkler

MDN bir ayrıntıya daha dikkat çeker: Köken renk çıktı uzayına çevrilirken kanallar o uzayın olağan aralığına kırpılmaz. Örneğin color(display-p3 1 0.5 0.5) Display P3 gamında olsa da sRGB dışındadır; rgb() ölçeğinde kırmızı kanalı yaklaşık 273,88'dir ve calc(r - 1) sonucu 272,88 olur. Mutlak rgb() yazımı ise değerleri kırpar; aynı sayıları rgb(273.88 ...) diye yazsaydınız kırmızı 255'ten başlardı. Sonucun ekranda doğru görünüp görünmemesi ekranın yeteneğine bağlıdır.

Uygulamalı mini örnek: tek renkten buton durumları

Aşağıdaki kurallar tek bir --ana renginden bir butonun normal, üzerine gelinmiş, basılı ve devre dışı görünümlerini türetir. Renk değiştiğinde dört durum birlikte güncellenir.

css
:root {
  --ana: oklch(55% 0.15 250);
}

.buton {
  background-color: var(--ana);
  color: white;
  border: 1px solid oklch(from var(--ana) calc(l - 0.1) c h);
  /* kenarlık: açıklık 0.55 - 0.1 = 0.45 */
}

.buton:hover {
  background-color: oklch(from var(--ana) calc(l + 0.08) c h);
  /* açıklık 0.55 + 0.08 = 0.63 */
}

.buton:active {
  background-color: color-mix(in oklab, var(--ana) 80%, black);
  /* yüzde 20 siyahla karışım: daha koyu */
}

.buton:disabled {
  background-color: color-mix(in oklab, var(--ana) 40%, transparent);
  /* yüzde 40 opaklıkta, aynı renk */
}

Aynı sonuca farklı yollardan ulaşılabileceğine dikkat edin: Koyulaştırmak için hem açıklık kanalını düşürmek hem siyahla karıştırmak işe yarar. Fark kontrol düzeyindedir. Göreceli renk tek bir kanalı hedefler ve tonu, kromayı olduğu gibi bırakır; color-mix() ise iki rengin bütün kanallarını birlikte karıştırır. :hover, :active ve :disabled seçicileri pseudo-class yazısında anlatılıyor.

Sık yapılan hatalar

Sık yapılan hatalar: Kanal hesabında birim kullanmak, Yanlış uzayın kanal adını kullanmak, Yüzde toplamının alpha etkisini unutmak, İki yüzdeyi de sıfır yazmak
  • Kanal hesabında birim kullanmak: calc(l + 20%) geçersizdir; kanallar sayıya çözülür, calc(l + 20) yazın.
  • Yanlış uzayın kanal adını kullanmak: rgb(from ... h s l) geçersizdir; kanal adları seçtiğiniz fonksiyona aittir. color() içinde RGB tabanlı bir uzayla x y z kullanmak da geçersizdir.
  • Yüzde toplamının alpha etkisini unutmak: color-mix(in srgb, red 30%, blue 30%) yüzde 60 opak bir renk verir.
  • İki yüzdeyi de sıfır yazmak: Fonksiyon geçersiz olur.
  • Saydam rengi color-mix() ile opaklaştırmaya çalışmak: Mümkün değildir; göreceli renkte alpha kanalına 1 yazın.
  • Varsayılan uzayı sRGB sanmak: color-mix() ve enterpolasyon varsayılan olarak Oklab kullanır.

Sık Sorulan Sorular

color-mix() ile göreceli renk arasında hangisini seçmeliyim?

İki rengi belirli bir oranda harmanlamak istiyorsanız color-mix() doğaldır; örneğin bir rengi beyaz ya da siyahla açıp koyulaştırmak veya transparent ile saydamlaştırmak. Tek bir kanalı kesin olarak değiştirmek istiyorsanız, örneğin yalnızca açıklığı artırmak ya da alpha değerini sabitlemek, göreceli renk sözdizimi daha doğrudandır.

Göreceli renk desteğini nasıl sınarım?

MDN'nin önerdiği yol bir özellik sorgusudur: @supports (color: hsl(from white h s l)) { ... }. Bu bloğun içine yalnızca destekleyen tarayıcılarda uygulanacak kuralları yazar, dışarıda düz renkli bir yedek bırakırsınız.

Köken rengin hangi biçimde yazıldığı önemli mi?

Hayır. Tarayıcı köken rengi seçtiğiniz fonksiyonun modeline kendisi çevirir. Hex olarak tanımlanmış bir marka rengini hsl(from ...) ya da oklch(from ...) içine koyabilirsiniz; kanal adları çıktı fonksiyonuna göre belirlenir.

color-mix() sonucunu bir değişkende saklayabilir miyim?

Evet. Fonksiyon normal bir renk değeri olduğu için --hover: color-mix(in oklab, var(--ana) 85%, white); gibi bir özel özelliğe yazılabilir ve var(--hover) ile kullanılabilir. Özel özelliklerin çalışma biçimi CSS değişkenleri yazısında anlatılıyor.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: CSS öğrenme rehberi · CSS renk değerleri · CSS gradyanları · CSS değişkenleri · calc(), min(), max(), clamp() · @supports özellik sorguları