CSS Kapsayıcı Sorguları hala ilgi görüyor ve çoğumuz, küçük deneyler için olsa da olmasa da, onlarla ellerimizi ıslatıyoruz. Harikalar ama tam değiller, tarayıcı desteği — onları bazı projelerde kullanmayı haklı çıkarmaya yetecek kadar, ancak belki de değiştirmeye başlayacağımız ölçüde değil medya sorguları parlak yeni konteyner boyutu sorgularıyla geçmiş projelerden.
Yine de kullanışlı oldukları kesin! Aslında, gerçekten onlara ulaşmak istediğim ancak destek gereksinimlerinin üstesinden gelemediğim birkaç durumla karşılaştım. Onları kullanabilseydim, bu durumlarda böyle görünürdü.
Aşağıdaki demoların tümü, bu yazının yazıldığı sırada en iyi Chrome veya Safari'de görüntülenecektir. Firefox'un planları gemi desteği Sürüm 109'da.
Durum 1: Kart ızgarası
Bunu beklemek zorundaydın, değil mi? Bu o kadar yaygın bir model ki hepimiz bir noktada onunla karşılaşıyoruz. Ancak gerçek şu ki, kapsayıcı boyutundaki sorgular, standart medya sorguları yerine kullanabilseydim, benim için çok büyük bir zaman tasarrufu ve daha iyi bir sonuç olurdu.
Diyelim ki, her kartın 1:1 en boy oranını koruması gerektiği şartıyla bu kart ızgarasını oluşturmakla görevlendirildiniz:
Göründüğünden daha zor! Sorun şu ki, bir bileşenin içeriğini görünümün genişliğine göre boyutlandırmak, sizi bileşenin görünüme nasıl tepki verdiğinin insafına bırakması - ve ayrıca diğer ata kaplarının ona yanıt verme şekli. Örneğin, bir kart başlığının yazı tipi boyutunun, kart belirli bir satır içi boyuta geldiğinde küçülmesini istiyorsanız, bunu yapmanın güvenilir bir yolu yoktur.
Yazı tipi boyutunu ayarlayabilirsiniz vw
birimler, sanırım, ancak bileşen hala tarayıcının görüntü alanı genişliğine bağlı. Ve bu, kart ızgarası aynı kesme noktalarına sahip olmayabilecek başka bağlamlarda kullanıldığında sorunlara neden olabilir.
Gerçek dünyadaki projemde, aşağıdakileri sağlayacak bir JavaScript yaklaşımına ulaştım:
- Yeniden boyutlandırma olayını dinleyin.
- Her kartın genişliğini hesaplayın.
- Genişliğine göre her karta bir satır içi yazı tipi boyutu ekleyin.
- kullanarak içindeki her şeyi şekillendirin
em
birimler.
Çok iş gibi görünüyor, değil mi? Ancak, farklı bağlamlarda farklı ekran boyutlarında gerekli ölçeklendirmeyi elde etmek için kararlı bir çözümdür.
Kapsayıcı sorguları çok daha iyi olurdu çünkü bize kapsayıcı sorgu birimleri, benzeri cqw
birim. Muhtemelen zaten anladın, ama 1cqw
eşittir 1%
bir konteyner genişliğinde. bizde de var cqi
bir kabın satır içi genişliğinin bir ölçüsü olan birim ve cqb
bir konteynerin blok genişliği için. Yani, eğer bir kart konteynerimiz varsa, 500px
geniş, bir 50cqw
değer hesaplar 250px
.
Kart ızgaramda kapsayıcı sorguları kullanabilseydim, .card
kapsayıcı olarak bileşen:
.card {
container: card / size;
}
O zaman bir iç sarmalayıcı ayarlayabilirdim. padding
ölçeklendiren 10%
arasında .card
genişliğini kullanarak cqw
birim:
.card__inner {
padding: 10cqw;
}
Bu, herhangi bir görüntü alanı genişliğinde kartın nerede kullanıldığına bakılmaksızın, kartın kenarları ile içeriği arasındaki boşluğu tutarlı bir şekilde ölçeklendirmenin güzel bir yoludur. Medya sorgusu gerekmez!
Diğer bir fikir? Kullanmak cqw
iç içeriğin yazı tipi boyutu için birimler, ardından dolgu uygulayın em
birimler:
.card__inner {
font-size: 5cqw;
padding: 2em;
}
5cqw
keyfi bir değerdir - sadece benim kararlaştırdığım bir değer. Bu dolgu hala eşittir 10cqw
yana em
birim görecelidir .card__inner
yazı Boyutu!
Bunu yakaladın mı? bu 2em
görecelidir 5cqw
ayarlanan yazı tipi boyutu aynı kapta. Konteynerler alışık olduğumuzdan farklı çalışır, çünkü em
birimler aynı elemanın görelidir font-size value
. Ancak hemen fark ettiğim şey, kapsayıcı sorgu birimlerinin aynı zamanda bir konteyner olan en yakın ebeveyn.
Örneğin, 5cqw
dayalı olarak ölçeklenmez. .card
bu örnekte elemanın genişliği:
.card {
container: card / size;
container-name: card;
font-size: 5cqw;
}
Bunun yerine, kapsayıcı olarak tanımlanan en yakın ebeveyne göre ölçeklenir. Bu yüzden bir kurdum .card__inner
sargı.
Durum 2: Alternatif düzen
Farklı bir projede başka bir kart bileşenine daha ihtiyacım vardı. Bu kez, karta yatay düzenden dikey düzene geçmek için ihtiyacım vardı... sonra tekrar yataya ve ekran küçüldükçe tekrar dikeye.
Bu bileşenin bu iki özel görüntü alanı aralığında portreye gitmesini sağlamak için kirli bir iş yaptım (bağırmak yeni medya sorgu aralığı sözdizimi!), ancak yine sorun şu ki, üzerinde ayarlanan medya sorgularına, ebeveynine ve görünümün genişliğine yanıt verebilecek diğer her şeye kilitleniyor. İçeriğin nerede bozulacağını merak etmeden her koşulda çalışan bir şey istiyoruz!
sayesinde kapsayıcı sorguları bunu bir esinti haline getirebilirdi. @container
kural:
.info-card {
container-type: inline-size;
container-name: info-card;
}
@container info-card (max-width: 500px) {
.info-card__inner {
flex-direction: column;
}
}
Tek sorgu, sonsuz akışkanlık:
Ama bekle! Dikkat etmek isteyebileceğiniz bir şey var. Spesifik olarak, prop tabanlı bir tasarım sisteminde bunun gibi bir konteyner sorgusu kullanmak zor olabilir. Örneğin, bu .info-card
bileşen, görünüşlerini değiştirmek için aksesuarlara dayanan alt bileşenler içerebilir.
Bu neden önemli? Kartın dikey düzeni, alternatif stili gerektirebilir, ancak JavaScript özelliklerini CSS ile değiştiremezsiniz. Bu nedenle, gerekli stilleri çoğaltma riskiniz vardır. Aslında buna değindim ve başka bir makalede bunun etrafında nasıl çalışılacağı. Stilinizin önemli bir kısmı için kapsayıcı sorguları kullanmanız gerekiyorsa, medya sorguları ağırlıklı mevcut bir tasarım sistemine sığdırmaya çalışmak yerine tüm tasarım sisteminizi bunlara dayandırmanız gerekebilir.
Durum 3: SVG vuruşları
İşte son zamanlarda kullandığım, kap boyutu sorgularının daha parlak bir ürünle sonuçlanacağı başka bir süper yaygın kalıp. Başlıkla kilitlenmiş bir simgeniz olduğunu varsayalım:
Heading
Medya sorguları olmadan bile, simgeyi başlığın boyutuyla ölçeklendirmek oldukça kolaydır. Ancak sorun şu ki, SVG'ler stroke-width
daha küçük bir boyutta o kadar iyi fark edilemeyecek kadar ince olabilir ve belki de daha büyük bir boyutta süper kalın bir vuruşla çok fazla dikkat çekebilir.
Boyutunu ve kontur genişliğini belirlemek için her simge örneğine sınıflar oluşturmak ve uygulamak zorunda kaldım. Simge, sabit bir yazı tipi boyutuyla biçimlendirilmiş bir başlığın yanındaysa sorun değil, sanırım, ancak sürekli değişen akıcı türlerle çalışırken o kadar da iyi değil.
Başlığın yazı tipi boyutu, görünümün genişliğine bağlı olabilir, bu nedenle SVG simgesinin, konturunun herhangi bir boyutta çalıştığı yere göre ayarlanması gerekir. Kontur genişliğini başlığın genişliğine göre yapabilirsiniz. font-size
onu ayarlayarak em
birimler. Ancak, bağlı kalmanız gereken belirli bir kontur boyutları grubunuz varsa, bu işe yaramaz çünkü aksi takdirde doğrusal olarak ölçeklenir - onu belirli bir boyuta ayarlamanın bir yolu yoktur. stroke-width
görünüm alanı genişliğinde medya sorgularına başvurmadan belirli noktalarda değer.
Ama o zamanlar kapsayıcı sorgu lüksüne sahip olsaydım ne yapardım:
.icon {
container: icon / size;
width: 1em;
height: 1em;
}
.icon svg {
width: 100%;
height: 100%;
fill: none;
stroke: #ccc;
stroke-width: 0.8;
}
@container icon (max-width: 70px) {
.icon svg {
stroke-width: 1.5;
}
}
@container icon (max-width: 35px) {
.icon svg {
stroke-width: 3;
}
}
Uygulamaları karşılaştırın ve kapsayıcı sorgu sürümünün, SVG'nin konturunu kapsayıcının genişliğine göre istediğim belirli genişliklere nasıl yakaladığını görün.
Bonus: Diğer kapsayıcı boyutu sorgusu türleri
Tamam, bu yüzden gerçek bir projede bununla karşılaşmadım. Ancak kapsayıcı sorgularıyla ilgili bilgileri tararken, kapsayıcının boyutu veya fiziksel boyutlarıyla ilgili bir kapta sorgulayabileceğimiz ek şeyler olduğunu fark ettim.
Gördüğüm çoğu örnek width
, max-width
, ve min-width
, height
, block-size
, ve inline-size
bu makale boyunca yaptığım gibi.
@container info-card (max-width: 500px) {
.info-card__inner {
flex-direction: column;
}
}
Fakat MDN iki şeyi daha özetliyor karşı sorgulayabiliriz. Biri orientation
bu çok mantıklı çünkü onu her zaman medya sorgularında kullanıyoruz. Kapsayıcı sorgularından farklı değil:
@media screen (orientation: landscape) {
.info-card__inner {
/* Style away! */
}
}
@container info-card (orientation: landscape) {
.info-card__inner {
/* Style away! */
}
}
Diğeri? Onun aspect-ratio
, inan ya da inanma:
@container info-card (aspect-ratio: 3/2) {
.info-card__inner {
/* Style away! */
}
}
İşte her iki örnekle de oynamak için düzenlenebilir bir demo:
Henüz bunların hiçbiri için iyi bir kullanım durumu bulamadım. Herhangi bir fikriniz varsa veya projelerinizde size yardımcı olabileceğini düşünüyorsanız, yorumlarda bana bildirin!