Transform'lar: translate, rotate, scale, Bağımsız Transform Property'leri, transform-origin ve 3D
Transform function'ları soldan sağa uygulanır ve her biri bir sonrakinin koordinat sistemini değiştirdiği için sıra sonucu değiştirir; bağımsız translate, rotate ve scale property'leri ise yazım sırasından bağımsız olarak hep bu sırayla ve transform'la birleşerek uygulanır. Yazı transform-origin'i, SVG'de transform-box'ı, layout'a etkisizliği ve Bookstore'da kapak hover'ı, 3D kapak çevirme ve sepet ikonunu ölçümlerle anlatır.
Sürüm notu: Bu yazı CSS Transforms Level 1 ve Level 2 spesifikasyonlarına ve Baseline'ın Kasım 2026 durumuna (web-features 3.46.0) göre yazıldı; örnekler Chromium 158 ve WebKit 27.2 (Playwright 1.65) ile denenmiştir, Firefox desteği web-features ve MDN'in (Mozilla'nın web dokümantasyon projesi) browser-compat-data 8.1.9 verisinden alınmıştır.
Önce Tahmin Et
Metin ve kutu görünümünü bitirdik; bu yazıyla görsel efektlere geçiyoruz. Sitedeki serilerin ortak örnek uygulaması Bookstore (bir online kitapçı) için katalog kartlarına kapak görseli, kitap detayına ön ve arka kapağı çeviren bir kart ve header'a küçük bir sepet ikonu ekleyeceğiz. Önce iki satırlık bir deney. İki kutu aynı iki function'ı alıyor, yalnız sıraları farklı:
.box { position: absolute; inset-block-start: 80px; inset-inline-start: 0; inline-size: 80px; block-size: 40px; background: #1d4ed8; }
#translate-rotate { transform: translate(100px, 0) rotate(45deg); }
#rotate-translate { transform: rotate(45deg) translate(100px, 0); }
İki kutu da 45 derece dönecek ve 100px kayacak. Sence ikisi ekranda aynı yere mi düşer? Düşmüyorsa hangisi sağa, hangisi aşağıya gider? Cevabını not et; ilk ölçüm bununla ilgili.
transform Function'ları ve Sıranın Sonucu Değiştirmesi
transform property'si boşlukla ayrılmış bir function listesi alır: translate(), rotate(), scale(), skew(), bunların eksen bazlı biçimleri (translateX(), scaleY()…) ve hepsini tek seferde veren matrix(). Lab'de kutuların merkezinin nereye kaydığını ölçtüm:
node scripts/06-transforms.mjs
translate-rotate center moved (100, 0) bbox 84.85x84.85
rotate-translate center moved (70.71, 70.71) bbox 84.85x84.85
İki kutu da aynı biçimde dönmüş (sınır kutuları 84.85×84.85, 80×40'lık bir dikdörtgenin 45 derecelik hâli), ama merkezleri farklı yerde. İlkinde merkez tam 100px sağa kaymış; ikincisinde 70.71px sağa ve 70.71px aşağıya. Sebebi, function'ların soldan sağa okunması ve her birinin bir sonrakinin koordinat sistemini değiştirmesi. translate(100px, 0) rotate(45deg) önce kutuyu sağa taşır, sonra olduğu yerde döndürür. rotate(45deg) translate(100px, 0) ise önce eksenleri 45 derece çevirir; ardından gelen 100px'lik kayma artık bu eğik x ekseni boyunca olur. 100px'in 45 derecelik component'leri de 70.71'er piksel.

Pratik kural: bir element'i "olduğu yerde" döndürüp ölçeklemek istiyorsan kaydırmayı başa yaz. Bir noktanın etrafında yörüngede döndürmek istiyorsan (saat kadranındaki sayılar gibi) önce döndür, sonra kaydır. transform'un computed değeri her zaman tek bir matrix()'tir; function listesini geri okuyamazsın, bu yüzden DevTools'ta gördüğün matris değil, yazdığın kural esas alınır.
Bağımsız translate, rotate ve scale Property'leri
2022'den beri translate, rotate ve scale ayrı property'ler olarak da yazılabiliyor. Bunların function sırası sorununu nasıl çözdüğüne bakalım:
/* 2) bağımsız property'ler: her zaman önce translate, sonra rotate, sonra scale, en son transform */
#individual { rotate: 45deg; translate: 100px 0; }
#rotate-only { rotate: 45deg; }
#combined { transform: rotate(20deg); rotate: 25deg; }
individual center moved (100, 0) bbox 84.85x84.85
rotate-only center moved (0, 0) bbox 84.85x84.85
combined center moved (0, 0) bbox 84.85x84.85
#individual computed: translate: 100px; rotate: 45deg; transform: none
#combined computed: rotate: 25deg; transform: matrix(0.939693, 0.34202, -0.34202, 0.939693, 0, 0)
#individual'da önce rotate, sonra translate yazdık; sonuç yine de translate(100px, 0) rotate(45deg) ile aynı: merkez (100, 0) kaymış. Bağımsız property'ler yazım sırasına bakmaz, spesifikasyonun belirlediği sabit sırayla uygulanır: önce translate, sonra rotate, sonra scale ve en son transform listesi. Bu da "olduğu yerde döndür ve büyüt" demek; çoğu arayüz efektinin istediği tam olarak bu.
#combined ikinci önemli kuralı gösteriyor: rotate: 25deg, transform: rotate(20deg)'i ezmez; ikisi toplanır. Sınır kutusu 45 derece dönmüş #rotate-only ile birebir aynı. Computed değerlerde de ikisi ayrı duruyor: rotate 25deg, transform ise 20 derecelik matris (cos 20° = 0.9397, sin 20° = 0.342). Aynı element'te iki yerden gelen dönüşü birleştirmek istemiyorsan, birini bilerek sıfırlaman gerekir.
Bağımsız property'lerin asıl faydası animasyonda görülüyor. transform tek bir property olduğu için bir animasyon onu değiştirdiğinde statik değerin tamamı gider:
@keyframes tilt-transform { from { transform: rotate(0deg); } to { transform: rotate(10deg); } }
@keyframes tilt-rotate { from { rotate: 0deg; } to { rotate: 10deg; } }
#anim-transform { transform: scale(1.5); animation: tilt-transform 1s linear paused; }
#anim-rotate { scale: 1.5; animation: tilt-rotate 1s linear paused; }
anim-transform transform: matrix(0.996195, 0.0871557, -0.0871557, 0.996195, 0, 0); scale: none; rotate: none; bbox 83.18
anim-rotate transform: none; scale: 1.5; rotate: 5deg; bbox 124.77
Animasyonu tam ortasında durdurdum. #anim-transform'da computed transform yalnız 5 derecelik dönüş; scale(1.5) kaybolmuş ve kutu 80×40 boyutunda dönüyor (sınır genişliği 83.18). #anim-rotate'te ise animasyon yalnız rotate'i değiştiriyor, scale: 1.5 yerinde kalıyor ve sınır genişliği 124.77. Hover'da büyüyen bir element'e ayrıca bir dönme animasyonu vermek gerektiğinde bu fark işe yarıyor; Bookstore'un sepet ikonunda aşağıda tam olarak bunu yapacağız. Animasyonun kendisi (@keyframes, easing, reduced motion) sitedeki CSS serisinin (CSS3: Flexbox, Grid ve Modern CSS) 13. yazısında anlatıldı.
transform-origin ve SVG'de transform-box
Dönme ve ölçeklemenin bir merkezi var: transform-origin. Başlangıç değeri 50% 50%, yani kutunun ortası. Aynı 90 derecelik dönüşü iki farklı merkezle ölçtüm:
#origin-center { rotate: 90deg; }
#origin-corner { rotate: 90deg; transform-origin: top left; }
origin-center transform-origin 40px 20px bbox from (20, -20) size 40x80
origin-corner transform-origin 0px 0px bbox from (-40, 0) size 40x80
Computed değer piksel cinsinden: 80×40'lık kutunun ortası 40px 20px. Ortadan dönen kutunun sınırı (20, -20)'den başlıyor, yani kutu yerinde dikilmiş. Sol üst köşeden dönen kutu ise köşenin soluna geçmiş: (-40, 0)'dan başlayıp aşağı uzanıyor, menteşesinden açılan bir kapı gibi. Hangi noktanın sabit kalacağını transform-origin belirler; bir menünün tıklanan butondan açılıyormuş gibi büyümesi ya da bir ikonun alt kenarından sallanması bu property ile yapılır.
SVG (vektörel görsel formatı) içindeki şekillerde transform-origin bir sürpriz yapar. HTML element'lerinde yüzdeler element'in kendi kutusuna göre hesaplanır; SVG'nin içindeki bir rect ya da path'te ise referans kutusu varsayılan olarak SVG'nin viewBox'ıdır. Bunu transform-box değiştirir:
<svg viewBox="0 0 24 24"><rect id="wheel-view" x="2" y="2" width="6" height="6" fill="#b91c1c"/></svg>
<svg viewBox="0 0 24 24"><rect id="wheel-fill" x="2" y="2" width="6" height="6" fill="#b91c1c"/></svg>
/* 7) SVG içinde transform-origin: view-box (varsayılan) ve fill-box */
#wheel-view, #wheel-fill { rotate: 45deg; transform-origin: center; }
#wheel-fill { transform-box: fill-box; }
--- chromium
wheel-view transform-box view-box center after rotate (120, 21)
wheel-fill transform-box fill-box center after rotate (50, 50)
--- webkit
wheel-view transform-box view-box center after rotate (120, 21)
wheel-fill transform-box fill-box center after rotate (50, 50)
SVG'ler 240px genişliğinde, viewBox 24 birim; yani bir birim 10 piksel ve kare dönmeden önce (50, 50)'de. transform-origin: center varsayılan view-box ile viewBox'ın ortası olan (120, 120) etrafında dönüyor ve kare (120, 21)'e kaçıyor. transform-box: fill-box ile referans karenin kendi sınırı oluyor ve kare yerinde dönüyor. SVG ikonlarındaki bir parçayı (bir dişliyi, bir zil tokmağını) canlandırırken fill-box neredeyse her zaman istediğin şey.
Transform Layout'u Değiştirmez
Transform, element'in layout'taki yerini değiştirmez; yalnız çizildiği yeri değiştirir. Bir satırdaki ortadaki kutuyu 1.5 kat büyüttüm:
.row div { inline-size: 80px; block-size: 40px; background: #1d4ed8; }
#grown { scale: 1.5; }
#grown: offsetWidth 80, rendered width 120; #after starts at x=180
offsetWidth hâlâ 80; ekranda çizilen genişlik 120. Sağdaki kutu da yerinden oynamamış: 80 + 10 + 80 + 10 = 180. Büyüyen kutu komşularının üstüne taşar, onları itmez. Bu, hover efektleri için tam istenen davranış: büyüme sayfadaki hiçbir şeyi kaydırmaz, layout'u yeniden hesaplatmaz. Aynı nedenle transform, CSS3 serisinin 13. yazısında ölçüldüğü gibi compositor'da (tarayıcının ana thread'i beklemeden katmanları birleştiren kısmı) canlandırılabilen birkaç property'den biri.
Bunun iki yan etkisi var ve ikisi de CSS3 serisinin 04. yazısında ölçüldü: none dışında bir transform (bağımsız property'ler dahil) element'i yeni bir stacking context yapar, ve içindeki position: fixed element'ler artık viewport'a değil bu element'e göre konumlanır. Hover'da büyüyen bir kartın içinde fixed bir bildirim varsa, bildirim kartla birlikte hareket eder.
Katalogdaki kapak görseli için bu bilgiyi birleştirelim: görsel hover'da hafifçe büyüsün, ama kartın sınırından taşmasın:
.book-card .cover {
margin-block-end: 0.75rem;
border-radius: 0.25rem;
/* büyüyen görsel çerçevenin içinde kalır */
overflow: hidden;
}
.book-card .cover img {
display: block;
inline-size: 100%;
block-size: auto;
transition: scale 200ms ease-out;
}
.book-card:hover .cover img { scale: 1.05; }
@media (prefers-reduced-motion: reduce) {
.book-card .cover img { transition: none; }
}
Taşmayı kesen overflow: hidden görselin kendisinde değil, çerçevesinde (.cover). Görsel çerçeveyle aynı boyutta başlıyor; büyüyünce fazlası kesiliyor. img'ye display: block vermemiz görselin altındaki küçük boşluğu kaldırıyor; img reset'inin ayrıntısı bu serinin görseller yazısında. Sayfadaki ölçüm:
node scripts/06-pages.mjs
--- chromium
cover img scale: 1.05
img 193.2x289.8 -> 202.86x304.29, frame 193.2x289.8, card moved: false
cart count: 1
cart icon at 25% + hover: rotate -12deg, scale 1.1, transform-origin 12px 24px
flip: aria-pressed=true, rotate y 180deg, cover box 240x360
cover pixel: front rgb(21, 95, 61), after flip rgb(30, 41, 60)
--- webkit
cover img scale: 1.05
img 193.2x289.8 -> 202.86x304.29, frame 193.2x289.8, card moved: false
cart count: 1
cart icon at 25% + hover: rotate -12deg, scale 1.1, transform-origin 12px 24px
flip: aria-pressed=true, rotate y 180deg, cover box 240x360
İlk iki satır kapakla ilgili: görsel 193.2×289.8'den 202.86×304.29'a büyüyor, çerçeve aynı boyutta kalıyor ve kart hiç kımıldamıyor. Bu satırlar iki motorda da aynı.
3D: perspective, preserve-3d ve backface-visibility
Kitap detayında kapağa tıklayınca arka kapak görünsün istiyoruz. Bir 3D çevirme için üç parça gerekir: üst element'te perspective (bakış mesafesi; küçük değer daha abartılı bir derinlik verir), dönen element'te transform-style: preserve-3d (çocuklar aynı 3D sahnede kalsın) ve her yüzde backface-visibility: hidden (arkası dönük yüz çizilmesin). Lab'de üç varyantı ölçtüm:
/* 6) 3D çevirme: perspective üst element'te, preserve-3d dönen element'te */
.flip { position: relative; inline-size: 120px; block-size: 180px; margin: 20px 0 20px 100px; perspective: 800px; }
.flip-inner { display: grid; block-size: 100%; transform-style: preserve-3d; }
.flip.is-flipped .flip-inner { rotate: y 180deg; }
.face { grid-area: 1 / 1; backface-visibility: hidden; }
.front { background: #15803d; }
.back { background: #1e293b; rotate: y 180deg; }
#flip-visible .face { backface-visibility: visible; }
/* overflow: hidden 3D sahneyi düzleştirir */
#flip-clipped .flip-inner { overflow: hidden; border-radius: 8px; }
flip-ok front side shows front (green) flipped shows back (navy)
flip-visible front side shows back (navy) flipped shows back (navy)
flip-clipped front side shows front (green) flipped shows front (green)
Doğru kurulmuş kart (flip-ok) önde yeşil ön yüzü, çevrilince lacivert arka yüzü gösteriyor. backface-visibility'yi visible bıraktığımız kartta ise çevirmeden önce bile arka yüz görünüyor: iki yüz aynı düzlemde ve DOM'da (sayfanın element ağacında) sonra gelen arka yüz, sırtı dönük olsa da önde çiziliyor. Üçüncü kart en sinsi olanı: .flip-inner'a köşeleri yuvarlamak için overflow: hidden verdik ve kart çevrildiğinde yine ön yüz görünüyor (aynalanmış hâliyle). Spesifikasyona göre overflow (visible ve clip dışında), 1'den küçük opacity, filter, clip-path, mask, isolation: isolate ve mix-blend-mode gibi değerler sahneyi düzleştirir ve preserve-3d'nin kullanılan değeri flat olur. Computed değer hâlâ preserve-3d görünür; DevTools'ta bakınca hata görünmez. Köşe yuvarlatma ve kırpma yüzlere verilir, dönen element'e değil.
Bu ölçümde piksel kontrolünü yalnız Chromium'da yaptım: Playwright'ın WebKit build'i ekran görüntüsünde backface-visibility'yi uygulamadı ve her durumda arka yüzü çizdi. Computed değerler WebKit'te de aynı; browser-compat-data'ya göre Safari property'yi 15.4'ten beri prefix'siz destekliyor, daha önce -webkit-backface-visibility gerekiyordu. Gerçek Safari'de görsel kontrolü yapamadım.
Bookstore'daki kart, lab'deki doğru kurulumun aynısı. İki görsel grid ile aynı hücreye yığılıyor, arka kapak baştan 180 derece çevrik duruyor:
<div class="cover-flip">
<div class="cover-flip-inner">
<img class="cover-face" src="img/cover-middlemarch.webp" alt="Front cover of Middlemarch" width="240" height="360">
<img class="cover-face cover-back" src="img/cover-middlemarch-back.webp" alt="Back cover of Middlemarch" width="240" height="360">
</div>
</div>
<button type="button" class="flip-button" aria-pressed="false">Show back cover</button>
/* ön ve arka kapak: perspective üst element'te, preserve-3d dönen element'te */
.cover-flip { inline-size: 240px; perspective: 800px; }
.cover-flip-inner {
display: grid;
transform-style: preserve-3d;
transition: rotate 400ms ease-in-out;
}
.cover-flip.is-flipped .cover-flip-inner { rotate: y 180deg; }
.cover-face {
grid-area: 1 / 1;
display: block;
inline-size: 100%;
block-size: auto;
border-radius: 0.25rem;
backface-visibility: hidden;
}
.cover-back { rotate: y 180deg; }
@media (prefers-reduced-motion: reduce) {
.cover-flip-inner { transition: none; }
}
// Kapağı çevirir; aria-pressed screen reader'a hangi yüzün açık olduğunu söyler.
const flip = document.querySelector('.cover-flip');
const flipButton = document.querySelector('.flip-button');
flipButton?.addEventListener('click', () => {
const flipped = flip.classList.toggle('is-flipped');
flipButton.setAttribute('aria-pressed', String(flipped));
});
Çevirmeyi bir button tetikliyor ve aria-pressed ile durumunu bildiriyor; görsele bir click listener koymak klavye ve screen reader kullanıcısını dışarıda bırakırdı. Ölçümün son satırları: buton aria-pressed=true'ya geçiyor, dönen element'in computed rotate'i y 180deg ve Chromium'da kapağın ortasındaki piksel ön kapağın yeşilinden arka kapağın lacivertine dönüyor. Kutu 240×360'ta kalıyor; 3D dönüş de layout'u etkilemiyor.
Sepet İkonu: rotate ve scale Birlikte
Son parça header'daki sepet ikonu. Fare üstüne gelince ikon biraz büyüyor; "Add to cart"a basılınca da tekerlekleri üstünde kısa bir sallanma yapıyor:
.cart-link {
display: inline-flex;
align-items: center;
gap: 0.375rem;
margin-inline-start: auto;
color: inherit;
text-decoration: none;
}
.cart-icon {
inline-size: 1.5rem;
block-size: 1.5rem;
fill: none;
stroke: currentColor;
stroke-width: 2;
/* ortadan değil, tekerleklerden sallan */
transform-origin: 50% 100%;
}
.cart-link:hover .cart-icon { scale: 1.1; }
/* rotate ve scale ayrı property'ler: sallanma hover'daki büyütmeyi korur */
.cart-icon.bump { animation: cart-bump 400ms ease-in-out; }
@keyframes cart-bump {
25% { rotate: -12deg; }
75% { rotate: 12deg; }
}
@media (prefers-reduced-motion: reduce) {
.cart-icon.bump { animation: none; }
}
Sallanmanın merkezi ikonun alt kenarı: transform-origin: 50% 100%, 24×24'lük ikonda 12px 24px olarak hesaplanıyor. Ölçüm, animasyonu %25'te durdurup fareyi linkin üstüne getiriyor: computed rotate -12deg, scale 1.1. Hover'ın büyütmesi ile animasyonun dönmesi birbirini ezmeden birlikte uygulanıyor. Aynı efekti iki transform kuralıyla yazsaydık, lab'deki #anim-transform'da gördüğümüz gibi animasyon süresince hover'ın büyütmesi kaybolurdu.
Üretimde Dikkat
Bir element'i büyütmek tarayıcıya iki seçenek bırakır: içeriği yeni boyutta yeniden çizmek ya da var olan çizimi büyütmek. Chrome, 53 sürümünden beri ölçek değişince içeriği yeniden çiziyor; ama element'te will-change: transform varsa animasyonun akıcı kalması için çizimi yeniden yapmıyor, var olanı büyütüyor. Bu da büyütülmüş metnin ve görselin bulanık görünmesine yol açabiliyor (Chrome for Developers blogundaki "Re-rastering composited layers on scale change" yazısı). Headless ekran görüntüsü katmanı yeniden çizdiği için bu farkı burada ölçemedim. Kural: will-change'i yalnız gerçekten sürekli canlanan element'e ve mümkünse animasyon süresince ver; hover'da %5 büyüyen bir kapak için gerekmiyor.
Büyütme oranını da küçük tut. %5 bir kapak görselinde yeterince fark edilir; metin içeren bir kartı büyütmek ise satırları alt piksel konumlarına iter ve kenarlar yumuşar. Kartın kendisini büyütmek yerine gölgesini değiştirmek (önceki yazı) ya da yalnız görseli büyütmek daha temiz sonuç verir. translate'te de tam olmayan piksel değerleri (translate: 0.5px) metni bulanıklaştırabilir.
Hareket hassasiyeti olan kullanıcılar için büyük dönme ve çevirme efektleri sorun olabilir. Bookstore'daki her geçişin prefers-reduced-motion: reduce altında kapatıldığını gördün; kapak yine çevriliyor, yalnız animasyonsuz.
Sık Düşülen Tuzaklar
Birincisi, function sırasını önemsiz sanmak. rotate(45deg) translate(100px) ile translate(100px) rotate(45deg) farklı yerlere düşer. Sıradan emin değilsen bağımsız property'leri kullan; onların sırası sabit.
İkincisi, bağımsız rotate'in transform: rotate()'i ezdiğini sanmak. İkisi birleşir; bir component'ten gelen transform ile senin rotate'in toplanır.
Üçüncüsü, transform'lu bir ata içinde position: fixed kullanmak. Fixed element artık viewport'a değil o ataya göre konumlanır; ayrıntı CSS3 serisinin 04. yazısında.
Dördüncüsü, 3D kartta dönen element'e overflow: hidden, opacity ya da filter vermek. Sahne düzleşir ve arka yüz hiç görünmez; computed değer bunu göstermez.
Beşincisi, SVG içindeki bir şekli transform-origin: center ile döndürüp transform-box: fill-box'ı unutmak. Şekil viewBox'ın ortası etrafında döner ve yerinden kaçar.
Baseline Durumu
node scripts/baseline.mjs transforms2d individual-transforms transforms3d transform-box will-change
transforms2d widely 2018-03-30 Chrome 36, Firefox 16, Safari 9, iOS 9
individual-transforms widely 2025-02-05 Chrome 104, Firefox 72, Safari 14.1, iOS 14.5
transforms3d widely 2024-09-14 Chrome 36, Firefox 16, Safari 15.4, iOS 15.4
transform-box widely 2026-10-16 Chrome 118, Firefox 125, Safari 13.1, iOS 13.4
will-change widely 2022-07-15 Chrome 36, Firefox 36, Safari 9.1, iOS 9.3
| Özellik | Durum | Not |
|---|---|---|
transform (2D), transform-origin | Widely available | Function'lar soldan sağa uygulanır |
translate, rotate, scale | Widely available | 2022-08'de newly, 2025-02'de widely |
3D transform, perspective, backface-visibility | Widely available | Safari 15.4'e kadar backface-visibility prefix'liydi |
transform-box | Widely available | fill-box çok eski; content-box/stroke-box yüzünden 2026-10'da widely |
will-change | Widely available | Chrome'da ölçek değişince yeniden çizimi durdurur |
Bu yazıdaki hiçbir özellik "Baseline değil" kategorisinde değil. transform-box'ın widely tarihi yanıltmasın: SVG ikonları için gereken fill-box değeri browser-compat-data'ya göre Chrome 64, Firefox 55 ve Safari 11'den beri var; 2026-10 tarihini Firefox'a 125 sürümünde gelen content-box ve stroke-box değerleri belirliyor.
Küçük Bir Deneme
★☆☆ Lab'deki #rotate-translate'i, merkezini (100, 0)'a taşıyan bir kurala çevir; önce function sırasını değiştirerek, sonra yalnız bağımsız property'lerle. 06-transforms.mjs iki durumda da aynı satırı yazdırmalı.
★★☆ Katalog kartındaki kapağın hover'da sol alttan büyümesini sağla (transform-origin) ve 06-pages.mjs'e görselin sol alt köşesinin hover öncesi ve sonrası aynı noktada kaldığını ölçen bir satır ekle.
★★★ Kitap detayındaki kapak kartına border-radius'lu bir çerçeve ve hafif bir gölge ekle, ama 3D sahneyi düzleştirmeden. Çevrilmiş durumda Chromium'da kapağın ortasındaki pikselin hâlâ arka kapağın rengi olduğunu doğrula; neyi hangi element'e verdiğini not et.
Bir sonraki yazıda görselleri ve arka planı CSS ile işliyoruz: filter function'ları, drop-shadow() ile box-shadow farkı, sticky bir filtre çubuğunda backdrop-filter ve kampanya banner'ında blend mode'larla duotone bir efekt.