CSS Kapsayıcı Sorguları: Kullanım Örnekleri ve Taşıma Stratejileri
Yayınlanan: 2022-03-10Bir UI öğesi için medya sorguları yazdığımızda, o öğenin ekran boyutlarına bağlı olarak nasıl stillendirildiğini her zaman açıklarız. Bu yaklaşım, hedef öğe medya sorgusunun yanıt verebilirliğinin yalnızca görüntü alanı boyutuna bağlı olması gerektiğinde iyi çalışır. Aşağıdaki duyarlı sayfa düzeni örneğine bir göz atalım.
Ancak, duyarlı Web Tasarımı (RWD) bir sayfa düzeniyle sınırlı değildir - tek tek UI bileşenleri genellikle, görünüm penceresi boyutlarına bağlı olarak stillerini değiştirebilen medya sorgularına sahiptir.
Önceki ifadede zaten bir sorun fark etmiş olabilirsiniz - bireysel UI bileşen düzeni genellikle yalnızca görünüm penceresi boyutlarına bağlı değildir. Sayfa düzeni, görünüm boyutlarına yakından bağlı bir öğe ve HTML'deki en üstteki öğelerden biri olsa da, UI bileşenleri farklı bağlamlarda ve kapsayıcılarda kullanılabilir. Düşünürseniz, görünüm alanı yalnızca bir kapsayıcıdır ve UI bileşenleri, bileşenin boyutlarını ve düzenini etkileyen stillerle diğer kapların içine yerleştirilebilir.
Hem üst hem de alt bölümlerde aynı ürün kartı bileşeni kullanılmasına rağmen, bileşen stilleri yalnızca görüntü alanı boyutlarına değil, aynı zamanda bağlam ve kapsayıcı CSS özelliklerine (örnekteki ızgara gibi) yerleştirildiği yere de bağlıdır.
Elbette, CSS'mizi, mizanpaj sorununu manuel olarak ele almak için farklı bağlamlar ve kaplar için stil varyasyonlarını destekleyecek şekilde yapılandırabiliriz. En kötü senaryoda, bu varyasyon, kod çoğaltma ve özgünlük sorunlarına yol açacak olan stil geçersiz kılma ile eklenecektir.
.product-card { /* Default card style */ } .product-card--narrow { /* Style variation for narrow viewport and containers */ } @media screen and (min-width: 569px) { .product-card--wide { /* Style variation for wider viewport and containers */ } }
Ancak bu, uygun bir çözümden ziyade medya sorgularının sınırlamaları için bir geçici çözümdür. UI öğeleri için medya sorguları yazarken, hedef öğenin düzenin bozulmadığı minimum boyutlara sahip olduğu bir kesme noktası için "sihirli" bir görünüm değeri bulmaya çalışıyoruz. Kısacası, "büyülü" bir görüntü alanı boyut değerini eleman boyutları değerine bağlıyoruz . Bu değer genellikle görünüm boyutundan farklıdır ve iç kap boyutları veya düzeni değiştiğinde hatalara eğilimlidir.
Aşağıdaki örnek tam olarak bu sorunu göstermektedir - duyarlı bir ürün kartı öğesi uygulanmış ve standart bir kullanım durumunda iyi görünse de, öğe boyutlarını etkileyen CSS özelliklerine sahip farklı bir kapsayıcıya taşınırsa bozuk görünüyor. Her ek kullanım durumu, yinelenen koda, kod şişmesine ve bakımı zor kodlara yol açabilecek ek CSS kodunun eklenmesini gerektirir .
Bu, konteyner sorgularının düzeltmeye çalıştığı sorunlardan biridir. Kapsayıcı sorguları, hedef öğe boyutlarına bağlı sorgularla mevcut medya sorguları işlevselliğini genişletir . Bu yaklaşımı kullanmanın üç ana faydası vardır:
- Kapsayıcı sorgu stilleri, hedef öğenin kendisinin boyutlarına bağlı olarak uygulanır. UI bileşenleri, verilen herhangi bir bağlama veya kapsayıcıya uyum sağlayabilecektir.
- Geliştiricilerin, bir görünüm alanı medya sorgusunu belirli bir kapsayıcıda veya belirli bir bağlamda UI bileşeninin hedef boyutuna bağlayan bir "sihirli sayı" görünüm boyutu değeri araması gerekmez.
- Farklı bağlamlar ve kullanım durumları için ek CSS sınıfları veya medya sorguları eklemeye gerek yok.
"İdeal duyarlı web sitesi, birden çok bağlamda hizmet vermek üzere yeniden kullanılabilen esnek, modüler bileşenlerden oluşan bir sistemdir."
— "Konteyner Sorguları: Bir Kez Daha İhlalde", Mat Marquis
Konteyner sorgularına derinlemesine dalmadan önce, tarayıcı desteğini kontrol etmemiz ve tarayıcımızda deneysel özelliği nasıl etkinleştirebileceğimizi görmemiz gerekiyor.
Tarayıcı Desteği
Kapsayıcı sorguları, bu makalenin yazıldığı sırada şu anda Chrome Canary sürümünde bulunan deneysel bir özelliktir. Bu makaledeki CodePen örneklerini takip etmek ve çalıştırmak istiyorsanız, aşağıdaki ayarlar URL'sinde kapsayıcı sorgularını etkinleştirmeniz gerekir.
chrome://flags/#enable-container-queries
Kapsayıcı sorgularını desteklemeyen bir tarayıcı kullanıyorsanız, CodePen demosunun yanında amaçlanan çalışma örneğini gösteren bir resim sağlanacaktır.
Kapsayıcı Sorgularıyla Çalışma
Kapsayıcı sorguları, normal medya sorguları kadar basit değildir. Kapsayıcı sorgularının çalışmasını sağlamak için UI öğemize fazladan bir CSS kodu satırı eklememiz gerekecek, ancak bunun bir nedeni var ve onu daha sonra ele alacağız.
Sınırlama Özelliği
CSS contain
özelliği, modern tarayıcıların çoğuna eklenmiştir ve bu makalenin yazıldığı sırada %75 oranında iyi bir tarayıcı desteğine sahiptir. contain
özelliği esas olarak, tarayıcıya sayfanın hangi bölümlerinin (alt ağaçların) bağımsız olarak değerlendirilebileceğini ve bir ağaçtaki diğer öğelerdeki değişiklikleri etkilemeyeceğini ima ederek performans optimizasyonu için kullanılır. Bu şekilde, tek bir öğede bir değişiklik meydana gelirse, tarayıcı tüm sayfa yerine yalnızca o kısmı (alt ağaç) yeniden oluşturacaktır. contain
özelliği değerleriyle, layout
, size
veya paint
gibi hangi tür çevrelemeyi kullanmak istediğimizi belirtebiliriz.
Kullanılabilir seçenekleri ve kullanım durumlarını çok daha ayrıntılı olarak özetleyen contain
özelliği hakkında birçok harika makale var, bu nedenle yalnızca kapsayıcı sorgularıyla ilgili özelliklere odaklanacağım.
Optimizasyon için kullanılan CSS memnuniyet özelliğinin kapsayıcı sorgularıyla ne ilgisi var? Kapsayıcı sorgularının çalışması için, tarayıcının, öğenin alt düzeninde yalnızca o bileşeni yeniden oluşturması gereken bir değişiklik olup olmadığını bilmesi gerekir. Tarayıcı, bileşen oluşturulduğunda veya bileşenin boyutu değiştiğinde, kapsayıcı sorgusundaki kodu eşleşen bileşene uygulamayı bilecektir.
contain
için layout
style
kullanacağız, ancak tarayıcıya değişikliğin gerçekleşeceği eksen hakkında sinyal gönderen ek bir değere de ihtiyacımız olacak.
-
inline-size
Hat içi eksende muhafaza. Bu değerin önemli ölçüde daha fazla kullanım örneğine sahip olması bekleniyor, bu nedenle ilk olarak uygulanıyor. -
block-size
Blok ekseninde muhafaza. Hala geliştirme aşamasındadır ve şu anda mevcut değildir.
contain
özelliğinin küçük bir dezavantajı, düzen öğemizin bir contain
öğesinin alt öğesi olması gerektiğidir; bu, ek bir iç içe yerleştirme düzeyi eklediğimiz anlamına gelir.
<section> <article class="card"> <div class="card__wrapper"> <!-- Card content --> </div> </article> </section>
.card { contain: layout inline-size style; } .card__wrapper { display: grid; grid-gap: 1.5em; grid-template-rows: auto auto; /* ... */ }
Bu değeri daha uzak bir ebeveyn benzeri section
nasıl eklemediğimize ve kapsayıcıyı etkilenen öğeye mümkün olduğunca yakın tutmadığımıza dikkat edin.
“Performans, işten kaçınma ve yaptığınız herhangi bir işi mümkün olduğunca verimli hale getirme sanatıdır. Çoğu durumda mesele, tarayıcıya karşı değil, tarayıcıyla çalışmaktır.”
— “Görüntüleme Performansı,” Paul Lewis
Bu yüzden tarayıcıya değişiklik hakkında doğru bir şekilde sinyal vermeliyiz. Uzak bir üst öğeyi bir contain
özelliğiyle sarmak ters etki yapabilir ve sayfa performansını olumsuz etkileyebilir. contain
özelliğinin kötüye kullanılmasının en kötü senaryolarında, düzen bozulabilir ve tarayıcı onu doğru şekilde oluşturmaz.
Kapsayıcı Sorgusu
Kart elemanı sarmalayıcısına contain
özelliği eklendikten sonra bir kapsayıcı sorgusu yazabiliriz. card
sınıfına sahip bir öğeye bir contain
özelliği ekledik, böylece artık onun alt öğelerinden herhangi birini bir kapsayıcı sorgusuna dahil edebiliriz.
Normal medya sorgularında olduğu gibi, min-width
veya max-width
özelliklerini kullanarak bir sorgu tanımlamamız ve tüm seçicileri bloğun içine yerleştirmemiz gerekiyor. Ancak, bir kapsayıcı sorgusu tanımlamak için @media
yerine @container
anahtar sözcüğünü kullanacağız.
@container (min-width: 568px) { .card__wrapper { align-items: center; grid-gap: 1.5em; grid-template-rows: auto; grid-template-columns: 150px auto; } .card__image { min-width: auto; height: auto; } }
Hem card__wrapper
hem de card__image
öğesi, tanımlanan contain
özelliğine sahip card
öğesinin çocuklarıdır. Normal medya sorgularını kapsayıcı sorgularla değiştirdiğimizde, dar kapsayıcılar için ek CSS sınıflarını kaldırdığımızda ve kapsayıcı sorgularını destekleyen bir tarayıcıda CodePen örneğini çalıştırdığımızda aşağıdaki sonucu alıyoruz.
Lütfen kapsayıcı sorgularının şu anda Chrome geliştirici araçlarında görünmediğini ve bunun da kapsayıcı sorgularında hata ayıklamayı biraz zorlaştırdığını unutmayın. Gelecekte tarayıcıya uygun hata ayıklama desteğinin eklenmesi bekleniyor.
Kapsayıcı sorgularının, neredeyse her kapsayıcıya ve düzene uyum sağlayabilen daha sağlam ve yeniden kullanılabilir UI bileşenleri oluşturmamıza nasıl olanak tanıdığını görebilirsiniz. Ancak, kapsayıcı sorguları için uygun tarayıcı desteği, özellikte hala çok uzakta. Aşamalı geliştirme kullanarak kapsayıcı sorguları uygulayıp uygulayamayacağımızı deneyelim ve görelim.
Aşamalı Geliştirme ve Çoklu Dolgular
Bakalım CSS sınıf varyasyonuna ve medya sorgularına bir geri dönüş ekleyebilecek miyiz. Kullanılabilir tarayıcı özelliklerini tespit etmek için CSS özellik sorgularını @supports
kuralıyla kullanabiliriz. Ancak, diğer sorguları kontrol edemeyiz, bu nedenle contain: layout inline-size style
değeri için bir kontrol eklememiz gerekiyor. inline-size
özelliğini destekleyen tarayıcıların da kapsayıcı sorgularını desteklediğini varsaymamız gerekecek.
/* Check if the inline-size value is supported */ @supports (contain: inline-size) { .card { contain: layout inline-size style; } } /* If the inline-size value is not supported, use media query fallback */ @supports not (contain: inline-size) { @media (min-width: 568px) { /* ... */ } } /* Browser ignores @container if it's not supported */ @container (min-width: 568px) { /* Container query styles */ }
Ancak, aynı stiller hem kapsayıcı sorgusu hem de ortam sorgusu tarafından uygulandığından, bu yaklaşım yinelenen stillere yol açabilir. Aşamalı geliştirme ile kapsayıcı sorguları uygulamaya karar verirseniz, kod bloklarını çoğaltmaktan kaçınmak için SASS gibi bir CSS ön işlemcisi veya PostCSS gibi bir son işlemci kullanmak ve bunun yerine CSS karışımlarını veya başka bir yaklaşımı kullanmak istersiniz.
Bu kapsayıcı sorgu spesifikasyonu hâlâ deneysel bir aşamada olduğundan, spesifikasyonun veya uygulamanın gelecekteki sürümlerde değişmeye açık olduğunu akılda tutmak önemlidir.
Alternatif olarak, güvenilir bir geri dönüş sağlamak için çoklu dolguları kullanabilirsiniz. Vurgulamak istediğim, şu anda aktif olarak korunan ve gerekli kapsayıcı sorgu özelliklerini sağlayan iki JavaScript çoklu dolgusu var:
-
cqfill
tarafından Jonathan Neal
CSS ve PostCSS için JavaScript çoklu doldurma -
react-container-query
, Chris Garcia
React için özel kanca ve bileşen
Medya Sorgularından Kapsayıcı Sorgularına Geçiş
Medya sorguları kullanan mevcut bir projede kapsayıcı sorguları uygulamaya karar verirseniz, HTML ve CSS kodunu yeniden düzenlemeniz gerekir. Bunu, medya sorgularına güvenilir bir geri dönüş sağlarken kapsayıcı sorguları eklemenin en hızlı ve en basit yolu olarak buldum. Bir önceki kart örneğine bir göz atalım.
<section> <div class="card__wrapper card__wrapper--wide"> <!-- Wide card content --> </div> </section> /* ... */ <aside> <div class="card__wrapper"> <!-- Narrow card content --> </div> </aside>
.card__wrapper { display: grid; grid-gap: 1.5em; grid-template-rows: auto auto; /* ... */ } .card__image { /* ... */ } @media screen and (min-width: 568px) { .card__wrapper--wide { align-items: center; grid-gap: 1.5em; grid-template-rows: auto; grid-template-columns: 150px auto; } .card__image { /* ... */ } }
İlk olarak, medya sorgusu uygulanan kök HTML öğesini, contain
özelliğine sahip bir öğeyle sarın.
<section> <article class="card"> <div class="card__wrapper"> <!-- Card content --> </div> </article> </section>
@supports (contain: inline-size) { .card { contain: layout inline-size style; } }
Ardından, bir ortam sorgusunu bir özellik sorgusuna sarın ve bir kapsayıcı sorgusu ekleyin.
@supports not (contain: inline-size) { @media (min-width: 568px) { .card__wrapper--wide { /* ... */ } .card__image { /* ... */ } } } @container (min-width: 568px) { .card__wrapper { /* Same code as .card__wrapper--wide in media query */ } .card__image { /* Same code as .card__image in media query */ } }
Bu yöntem bazı kod şişkinliği ve yinelenen kodla sonuçlansa da, SASS veya PostCSS kullanarak geliştirme kodunun kopyalanmasını önleyebilirsiniz, böylece CSS kaynak kodunun bakımı yapılabilir kalır.
Kapsayıcı sorguları uygun tarayıcı desteğini aldıktan sonra, @supports not (contain: inline-size)
kod bloklarını kaldırmayı ve yalnızca kapsayıcı sorgularını desteklemeye devam etmeyi düşünebilirsiniz.
Stephanie Eckles kısa süre önce çeşitli geçiş stratejilerini kapsayan kapsayıcı sorguları hakkında harika bir makale yayınladı. Konu hakkında daha fazla bilgi için incelemenizi tavsiye ederim.
Kullanım Durumu Senaryoları
Önceki örneklerden gördüğümüz gibi, kapsayıcı sorguları en iyi, kullanılabilir kapsayıcı alanına bağlı olan ve çeşitli bağlamlarda kullanılabilen ve sayfadaki farklı kapsayıcılara eklenebilen bir düzene sahip yeniden kullanılabilirliği yüksek bileşenler için kullanılır.
Diğer örnekler şunları içerir (örnekler, kapsayıcı sorgularını destekleyen bir tarayıcı gerektirir):
- Kartlar, form öğeleri, afişler vb. gibi modüler bileşenler.
- Uyarlanabilir düzenler
- Mobil ve masaüstü için farklı işlevlere sahip sayfalandırma
- CSS yeniden boyutlandırma ile eğlenceli deneyler
Çözüm
Spesifikasyon uygulandıktan ve tarayıcılarda geniş çapta desteklendikten sonra, kapsayıcı sorguları oyunun kurallarını değiştiren bir özellik haline gelebilir. Geliştiricilerin, uzak ve neredeyse hiç ilişkili olmayan görünüm alanı medya sorgularını kullanmak yerine, sorguları ilgili bileşenlere yaklaştırarak, bileşen düzeyinde sorgular yazmasına olanak tanır. Bu, çeşitli kullanım durumlarına, yerleşimlere ve kapsayıcılara uyum sağlayabilecek daha sağlam, yeniden kullanılabilir ve bakımı yapılabilir bileşenlerle sonuçlanacaktır.
Halihazırda, kapsayıcı sorguları hala erken, deneysel bir aşamadadır ve uygulama değişmeye açıktır. Bugün projelerinizde kapsayıcı sorguları kullanmaya başlamak istiyorsanız, bunları özellik algılama ile aşamalı geliştirme kullanarak eklemeniz veya bir JavaScript çoklu dolgu kullanmanız gerekir. Her iki durum da kodda bir miktar ek yüke neden olacaktır; bu nedenle, bu erken aşamada kapsayıcı sorguları kullanmaya karar verirseniz, özellik geniş çapta desteklendiğinde kodu yeniden düzenlemeyi planladığınızdan emin olun.
Referanslar
- “Kapsayıcı Sorguları: Hızlı Başlangıç Kılavuzu” David A. Herron
- "CSS Kapsayıcı Sorgularına Merhaba Deyin", Ahmad Shadeed
- "Chrome 52'de CSS Kapsama Alanı", Paul Lewis
- "CSS Özelliği İçererek Tarayıcıların Optimize Edilmesine Yardımcı Oluyor" Rachel Andrew