CSS Düzenleri ve Duyarlı Tasarım

  1. 1 Temel Bilgiler
    1. Hangi düzen modu kullanılmalı?
    2. Çalışma ilkeleri
  2. 2 Flexbox
  3. 3 Izgara ve alt ızgara
    1. Kod örneği: grid ve subgrid
  4. 4 Kapsayıcı sorguları
    1. Kod örneği: Kapsayıcı sorgu birimlerini kullanan akıcı tipografi
  5. 5 Doğal yer paylaşımları, sabit konumlandırma ve yığınlama bağlamları
  6. 6 Taşma izleme ve düzen kararlılığı
  7. 7 Görüntü alanı mekaniği ve parça dağıtımı
  8. 8 Izgara şeritleri (diğer adıyla duvar örgüsü)

1 Temel Bilgiler

Daha iyi performans için mümkün olduğunda tarayıcının düzen motorunu kullanın. Sabit kodlu boyutlara veya karmaşık medya sorgularına başvurmadan önce içsel boyutlandırma, mantıksal özellikler ve aspect-ratio kullanın.

1.1 Hangi düzen modu kullanılmalı?

Karar ağacını yukarıdan aşağıya doğru inceleyin ve ilk eşleşmede durun. Düzenlerin iç içe yerleştirilebileceğini ve her kararın ilgili kapsayıcının kullanım alanına göre verildiğini unutmayın.

  1. Öğelerden oluşan basit bir satır VEYA sütun mu? Flexbox'ı kullanın: 1D, içerik öncelikli, içerik tek bir eksen boyunca dağıtılır.
  2. İç içe yerleştirilmiş bir öğenin, üst öğesinin üst öğesi olan ızgaranın kanallarıyla hizalanması gerekiyor mu? Alt ızgara kullanın: 2D, ilişki öncelikli, üst öğe parçalarını devralır, böylece alt öğeler kardeşler arasında hizalanabilir.
  3. Satır VE sütun içeren karmaşık bir sayfa veya bileşen yapısı mı? Izgara kullanın: 2D, önce düzen, iskeleti siz tanımlarsınız ve içerik bunu doldurur.
  4. İçerik, dengeli sütunlara bölünmesi gereken uzun bir düz yazı akışı mı? Çok sütunlu: Tek boyutlu akış, gazete stili.
  5. Sıkıca paketlenmesi gereken farklı yüksekliklerde öğeler var mı? Bugün grid-auto-flow: dense ile grid kullanın; yerel duvar örgüsüne (diğer adıyla "grid lanes") yalnızca Baseline hedefinizde sunulduğunda ulaşın (bkz. §8).
  6. Bir öğenin, DOM sınırları veya yığınlama bağlamları arasında bile sayfanın üzerinde kayması ve bir tetikleyiciye mekansal olarak bağlı kalması gerekiyor mu? Sabit konumlandırma kullanın: Tetikleyicide anchor-name, yer paylaşımında position-anchor (§5 bölümüne bakın).

1.2 Çalışma ilkeleri

  • Düzen boyutları ve boşluklar için mantıksal özellikleri (inline-size, block-size, margin-inline, padding-block, inset-inline-start) kullanın. Tüm ayrıntılar için CSS: Modern Mimari başlıklı makaleyi inceleyin.
  • Önce içerik ve önce düzen zihinsel modelini uygulayın: Öğeler akışı belirlediğinde flexbox, önce iskeleti tanımladığınızda grid kullanın.
  • Tek bir bildirimde her iki eksende hizalama yapmak için place-* kısaltmalarını (place-content, place-items, place-self) kullanın.
  • Sabit width/height yerine içsel boyutlandırma (min-content, max-content, fit-content()) ve esnek parçalar (fr, minmax()) kullanın. Böylece daha az medya sorgusu ve daha esnek düzenler elde edersiniz.
  • Düzen sorunlarını gizlemek için overflow: hidden kullanmayın. Bu sorunları kaynakta düzeltin. Örneğin, <canvas>, <img>, <svg>, <video>, <iframe> gibi belirli değiştirilen öğeler varsayılan olarak display: inline kullanır. Bu da belirli düzenlerde boşluk ekleyebilir. Boşluğu overflow ile kırpmak yerine, bir block display-outside değeri (ör. display: block, grid, flex vb.) uygulayarak kaldırın.
  • Medya için yer ayırmak ve öğeler yüklenmeden önce düzen kaymasını önlemek için aspect-ratio kullanın.
.sidebar       { inline-size: max-content; }    /* Size to longest unbreakable token. */
.main-content  { inline-size: fit-content; }    /* Grow to available space, no further. */
.media         { aspect-ratio: 16 / 9; inline-size: 100%; block-size: auto; }
body.centered  { display: grid; place-content: center; min-block-size: 100dvb; }

calc-size() ve kısıtlamaya duyarlı iç boyutlandırma için İç Boyutlarla Hesaplama başlıklı makaleyi inceleyin.

2 Flexbox

Tek boyutlu düzen: Öğeler, çapraz eksende hizalanarak tek bir ana eksen boyunca akar. Gezinme çubukları, araç çubukları, öğe satırları ve tek satırlı veya sütunlu dağıtımlar için bu düzeni kullanın.

Yapılması gerekenler:

  • display: flex ile bir bağlam oluşturun ve ana ekseni flex-direction (row varsayılan) ile ayarlayın.
  • Taşma olasılığı olduğunda flex-wrap: wrap kullanın. overflow: auto/hidden olmadan nowrap, dar görüntü alanlarında taşar.
  • Öğeleri satırlara eşit şekilde dağıtmak ve son satırda tek bir öğenin kalmasını önlemek için kompakt öğelerin (etiket bulutları, filtre kapsülleri, düğme grupları veya gezinme bağlantıları gibi) sarmalanmış satırlarında flex-wrap: wrap öğesinden sonra flex-wrap: balance katmanını kullanın. Desteklenmeyen tarayıcılar wrap değerine geri döner.
  • Öğelerde flex-grow/flex-shrink/flex-basis özelliklerini ayrı ayrı ayarlamak yerine flex kısaltmasını <grow> <shrink> <basis> (ör. flex: 1 1 250px) kullanın.
  • Öğeler arasındaki boşluk için alt kenar boşlukları yerine gap (veya row-gap/column-gap uzun biçimi) kullanın.
  • Kapsayıcı, içeriğinden daha dar olduğunda odaklanılabilir içeriğin kırpılmaması için konumsal hizalamanın önüne safe (ör. align-items: safe center) ekleyin.
  • margin-inline-start: auto (veya margin-block-start: auto) ile tek bir öğeyi ana eksenin en uç noktasına itin. Bu, standart çıkış yoludur.
  • align-self ile öğe başına çapraz eksen hizalamasını geçersiz kılın.
  • Tüm öğeleri çapraz eksende ortalamak için align-items, tek bir öğeyi her iki eksende de bağımsız olarak ortalamak için margin: auto, yalnızca kapsayıcı sarmalandığında ve satırlar arasında fazladan boşluk olduğunda align-content kullanın.
  • Uzun ve bölünemeyen içerikler (URL'ler, kodlar, uzun dizeler) barındıran esnek öğelerde min-inline-size: 0 (veya min-width: 0) özelliğini ayarlayın. Esnek öğeler varsayılan olarak içerik boyutlarından daha küçük olmayacağı için taşmaya neden olur.

Şunları yapmayın:

  • Esnek öğelerde justify-self kullanmayın. Bu özellik yalnızca ızgara, blok ve mutlak konumlu düzenlerde çalışır. Bunun yerine otomatik kenar boşluklarını kullanın.
  • Etkileşimli içeriği yeniden sıralamak için order veya flex-direction: *-reverse kullanmayın. Yalnızca görsel sırayı değiştirirler. DOM sırası, sıralı odağı yönlendirmeye devam eder. Bu nedenle, klavye sekme akışı kullanıcının gördüğüyle eşleşmez.
  • space-around (uçlarda yarım boşluk) ile space-evenly (önce, arasında ve sonra eşit boşluklar) karıştırılmamalıdır.
  • Eksenlerin yer değiştirdiğini unutmayın: flex-direction: column olduğunda justify-content blok ekseninde, align-items ise satır içi eksende hizalanır. Bu, varsayılanın tam tersidir.
  • Hem kapsayıcıyı hem de alt öğelerini birbirini dolduracak şekilde boyutlandırmayın. Bu, taşma ve şaşırtıcı sonuçların yaygın bir nedenidir. Bir tarafa kesin bir boyut verin.
  • Aynı öğede hem flex-basis hem de width/inline-size özelliklerini ayarlamayın. Flex bağlamında flex-basis önceliklidir ve width yok sayılır. Flex öğelerini boyutlandırmak için tek doğruluk kaynağı olarak flex-basis (veya flex kısayolunu) kullanın.
.card-grid        { display: flex; flex-flow: row wrap; gap: 1rem; }
.card-item        { flex: 1 1 250px; }                  /* grow, shrink, basis */
.card-item-action { margin-inline-start: auto; }        /* Push to main-axis end. */
.toolbar          { display: flex; align-items: safe center; }
.tag-list         { display: flex; flex-wrap: wrap; flex-wrap: balance; gap: 0.5rem; }

3 Izgara ve alt ızgara

İki boyutlu düzen: Satırları VE sütunları açıkça tanımlayın veya motorun bunları türetmesine izin verin. Alt ızgara, iç içe yerleştirilmiş bir ızgaranın üst öğesinin kanallarını devralmasına olanak tanır. Böylece alt öğeler, kardeş öğelerle hizalanır.

Izgara özelliklerini seçme:

  • Tam olarak kaç sütuna ihtiyacınız olduğunu biliyor musunuz?
    • Evet: Uygunsuz içerik barındıran parçaları (grid-template-columns: 200px 1fr, repeat(3, 1fr) vb.) kullanın.
    • Farklı sütunların farklı boyutlarda olması gerekiyor mu (kenar çubuğu + ana içerik, tümünü kapsayan başlık)? → Adlandırılmış, okunabilir bölgeler için grid-template-areas kullanın.
    • Tüm sütunlar tek tip mi yoksa yalnızca satır numarasına göre mi konumlandırılmış? → repeat(N, ...) veya adlandırılmış satırları kullanın
    • Hayır (duyarlı, bilinmeyen öğe sayısı) - repeat(auto-fit, minmax(min, 1fr)) kullanın
    • Son satırdaki öğeler, kalan alanı dolduracak şekilde genişletilmeli mi? → auto-fit
    • Boş son satır parçaları minimum boyutlarını korumalı mı (sütun hayalet alanları korunur)? → auto-fill
  • Bir öğeyi belirli bir konuma yerleştirmeniz mi gerekiyor?
    • Evet: grid-column: <start> / <end> veya grid-area: <name> kullanın.
    • Hayır (yalnızca birden fazla kanalı kapsıyor, akış konumu önemli değil): grid-column: span <n> kullanın.
  • Alt öğelerin, üst ızgaranın kanal boyutlarını devralması gerekiyor mu (kardeşler arasında düzensiz kenar hizalaması)?
    • Evet: Etkilenen eksende alt ızgara kullanın.
    • Hücre başına çocuk sayısı değişken mi? → alt ızgara yalnızca bir eksen; diğeri için grid-auto-rows/grid-auto-columns kullanın
    • Çocuk sayısı sabit mi? → her iki eksende de alt ızgara kullanılabilir
    • Hayır: Standart ızgara, alt ızgara gerekmez

Yapılması gerekenler:

  • display: grid ile bağlam oluşturun.
  • Karmaşık sayfa düzeyindeki düzenler için grid-template-areas kullanın. Alan adları kendi kendini belgeleyebilir ve bildirim, bir bakışta okunabilirlik için satırlar ve sütunlar halinde hizalanabilir.
  • Dolu kanalları satırı dolduracak şekilde genişleten duyarlı kart ızgaraları için repeat(auto-fit, minmax(200px, 1fr)), boş yinelenen kanalları minimum boyutlarında tutmak için auto-fill kullanın.
  • Orantılı kanal dağıtımı için fr, esnek ancak sınırlı kanallar için minmax(min, max) kullanın.
  • Öğeleri, kanallar arasında boyutlandırmak için grid-column: span <n>, belirli satırlara yerleştirmek için grid-column: <start> / <end> veya adlandırılmış bölgeler için grid-area: <name> ile konumlandırın.
  • Kart listelerindeki "pürüzlü kenar" sorununu çözmek için alt ızgara (grid-template-columns: subgrid veya grid-template-rows: subgrid) kullanın. Başlıklar, meta veriler ve CTA'lar gibi dahili öğeler kardeş öğelerle aynı hizada olur.
  • Eski tarayıcılar için aynı basamaklı yedek olarak bir alt ızgara beyanını önceki açık grid-template-rows/-columns beyanıyla eşleştirin.

Şunları yapmayın:

  • auto-fit/auto-fill track boyutunun öğe içeriğinden gelmesini beklemeyin. Bu boyut, repeat() size bağımsız değişkeninden gelir.
  • Etkileşimli içeriklerde grid-auto-flow: dense kullanmayın. Öğeleri verimli bir şekilde paketler ancak görsel olarak yeniden sıralar ve DOM sırasına göre klavye sekmesi akışını bozar.
  • Alt öğe sayısı değişken olduğunda alt ızgarayı her iki eksene de uygulamayın. Ekstralar son parçaya yerleştirilir. Bunun yerine dolaylı eksen için grid-auto-rows/grid-auto-columns kullanın.
  • justify-items/align-items (öğe içeriğini kendi kanalı içinde hizalar) ile justify-content/align-content (ızgara kanallarını kapsayıcı içinde hizalar) karıştırılmamalıdır. Yanlış olanı kullanmanın herhangi bir etkisi yoktur.
  • Kapsayıcıda kesin bir inline-size olmadan repeat(auto-fit/auto-fill, ...) kullanmayın. display: inline-grid veya boyutlandırılmamış bir esnek öğenin içinde kapsayıcının bölünecek genişliği yoktur. Bu da parça sayılarının tahmin edilemez olmasına neden olur.

3.1 Kod örneği: ızgara ve alt ızgara

Sayfa kabuğu: <main class="page-layout">; <header>, <aside>, <div class="card"> alt öğe içeren bir <section class="card-grid"> ve <footer> içeriyor.

/* Align grid-template-areas in rows and columns for readability. */
.page-layout {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-areas:
    "header  header  header"
    "sidebar main    main"
    "footer  footer  footer";
  gap: 1.5rem;
}

header  { grid-area: header; }
aside   { grid-area: sidebar; }
footer  { grid-area: footer; }

.card-grid {
  grid-area: main;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  grid-template-rows: auto 1fr; /* title block, body block */
  gap: 1rem;
}

.card {
  grid-row: span 2;
  display: grid;
  /* Same-cascade fallback: ignored when subgrid is supported. */
  grid-template-rows: auto 1fr;
  grid-template-rows: subgrid;
}

4 Kapsayıcı sorguları

Görüntü alanı yerine bir üst kapsayıcının boyutunu (veya hesaplanan stilini) sorgulayın. Zihinsel model: kapsayıcı sorguları = bileşen bağlamı; medya sorguları = genel sayfa düzeni ve kullanıcı tercihleri (prefers-color-scheme, prefers-reduced-motion).

Yapılması gerekenler:

  • Alt öğeleri sorgulanmadan önce bir sarmalayıcıda container-type: inline-size (yalnızca genişlik sorguları) veya container-type: size (her iki eksen) ile bir kapsama bağlamı oluşturun.
  • İç içe yerleştirilmiş bağlamlar çakışabileceğinden kapsayıcıları container-name (veya container kısaltması: container: card / inline-size) ile adlandırın.
  • Akışkan türü ve boşluk hesaplanırken kapsayıcı sorgu birimleri dahil edilir: cqi/cqb (mantıksal satır içi/blok), cqw/cqh (fiziksel), cqmin/cqmax.
  • container-type: size kullanıldığında kapsayıcıya kesin bir block-size verin. Aksi takdirde, boyut sınırlaması kapsayıcıyı içeriğini yok saymaya zorladığından alt öğeler daraltılır.

Şunları yapmayın:

  • block-size değerini container-type değeri olarak kullanmayın. Bu değer geçerli değildir. Her iki eksen için size kullanın.
  • container-type değerini belirttikten sonra alt öğelerin doğal boyutunun kapsayıcıyı etkilemesini beklemeyin. Kapsayıcı, kapsama etkinleştirildikten sonra alt öğesi yokmuş gibi hesaplanır.
  • Uygun olmayan bir üst öğenin alt öğelerinde kapsayıcı sorgusu birimlerini kullanmayın. Bu birimler küçük görüntü alanına (svw/svh) geri döner.

4.1 Kod örneği: Kapsayıcı sorgu birimlerini kullanan akıcı tipografi

.card-wrapper {
  container: card / inline-size; /* shorthand for container-name / container-type */
}

@container card (inline-size > 400px) {
  .content {
    display: flex;
    gap: 2rem;
  }
}

.title {
  /* Fluid type bound to the container width, not the viewport. */
  font-size: clamp(1rem, 4cqi, 2rem);
}

Bileşen odaklı duyarlı stil desenleri için Boyuta Duyarlı Stil ve Akıcı Ölçeklendirme bölümlerine bakın.

5 Yerel yer paylaşımları, sabitleme konumu ve yığınlama bağlamları

Her bir yer paylaşımı temel öğesinin ne zaman kullanılacağı:

  • Geçici, kalıcı olmayan kullanıcı arayüzü (açılır pencereler, toast mesajları, ipuçları) için popover kullanın. En üst katmanda bulunur, z-index yönetimi gerekmez.
  • Odak yakalama ve etkin olmayan bir arka plan gerektiren kalıcı etkileşimler için .showModal() ile <dialog> kullanın.
  • popover ve .showModal() öğelerini aynı öğede birleştirmeyin. Bunlar birbirini dışlayan çalışma zamanı durumlarıdır.

Sabit konumlandırma (yer paylaşımlarının uzamsal düzeni):

  • Bir yer paylaşımını tetikleyicisine göre konumlandırmak ve boyutlandırmak için position-area (veya iç kısımlarda anchor()) ve anchor-size() kullanın.
  • Yer paylaşımı görüntü alanının dışına taştığında tarayıcının yeniden konumlandırmasına izin vermek için position-try-fallbacks: flip-block (veya flip-inline) kullanın.
  • Tek bir position-area değerinde fiziksel ve mantıksal anahtar kelimeleri karıştırmayın. Bir koordinat sistemi seçin.
  • @supports (anchor-name: --x) ile özellik algılama yapın ve mutlak konumlu bir yedek sağlayın.

Uygulama ayrıntıları, polyfill stratejileri ve popover değer referansı için Bildirimli İletişim Kutusu ve Popover Kontrolü ile Konuma Duyarlı İpuçları başlıklı makaleleri inceleyin. Açılır listelere, açılır menülere ve sekme göstergelerine uygulanan sabitleme konumlandırması için Görüntü Alanına Duyarlı Açılır Listeler ve Sabitleme Konumlandırması Sekme Alt Çizgisi başlıklı makaleleri inceleyin.

6 Taşma izleme ve düzen kararlılığı

Düzen kaymalarını, kaydırma çubuklarını ve kırpmayı öngörülebilir şekilde yönetin.

Yapılması gerekenler:

  • Kaydırma çubuklarının yalnızca içerik gerçekten taştığında görünmesi için overflow: auto kullanın.
  • Kaydırma kapsayıcısı oluşturmadan içeriği kırpmak için overflow: clip kullanın. overflow-clip-margin ile taşmayı etkinleştirin.
  • Kaydırma çubukları için yer ayırmak ve içerik büyüdüğünde düzen kaymalarını önlemek için scrollbar-gutter: stable kullanın.
  • İç içe yerleştirilmiş kaydırma bölgelerinde (ör. kenar çubukları, modallar ve listeler) kaydırma zincirlerinin sayfaya yayılmasını önlemek için overscroll-behavior: contain (veya none) kullanın. Aşırı kaydırmanın yerel bir lastik bant sıçramasını tetiklemeden üst kaydırıcıya yayılması gerektiğinde ise ara kaydırma sarmalayıcılarında (ör. kaydırarak gösterme parçaları) overscroll-behavior: chain kullanın.
  • Çok satırlı kısaltma için -webkit-line-clamp + display: -webkit-box + -webkit-box-orient: vertical üçlüsünü kullanın. Önekine rağmen bu kalıp tamamen belirtilmiştir ve desteği sonlandırılmamıştır. Ön eki olmayan line-clamp kısaltmasını da ekleyin. Bu özelliği henüz desteklemeyen tarayıcılar, özelliği zararsız bir şekilde yoksayar. Şunları yapmayın:

  • auto yeterli olduğunda overflow: scroll kullanmayın. scroll, kaydırılacak bir şey olmadığında bile kaydırma çubuklarını zorunlu kılar.

  • Yalnızca kırpma yapmak istediğinizde overflow: hidden kullanmayın. hidden, programatik olarak kaydırılabilen bir kaydırma kapsayıcısı oluşturur.

.scrollable-list {
  max-block-size: 400px;
  overflow-y: auto;
  scrollbar-gutter: stable;       /* Reserve scrollbar space. */
  overscroll-behavior: contain;   /* No scroll chaining into the page. */
}

.snippet {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  line-clamp: 3;                  /* Ignored where unsupported. */
  overflow: clip;
}

overflow: clip ve overflow-clip-margin hakkında ayrıntılı bilgi için Taşma Kırpma Kontrolü başlıklı makaleyi inceleyin. Kaydırarak gösterme kullanıcı arayüzünde overscroll-behavior: chain ile iç içe yerleştirilmiş kaydırma devri için Kaydırarak gösterme bölümüne bakın. Kaydırma çubuğu rengi, boyutlandırması ve teması için Kaydırma çubuğunun rengini veya kalınlığını özelleştirme, Koyu mod ve Kaydırma çubuğunu yüksek kontrast tercihlerine uyarlama başlıklı makaleleri inceleyin.

7 Görüntü alanı mekanikleri ve parça dağıtımı

  • Tarayıcı kullanıcı arayüzü kaymasını (URL çubuğunun daralması/genişlemesi) hesaba katması gereken mobil düzen kapsayıcıları için dvh/dvw kullanın.
  • Tam genişlikte düzen için 100vw kullanmayın. Bu, kaydırma çubuğu genişliğini yok sayar ve yatay taşmaya neden olur. Bunun yerine 100%, 100dvw veya 100svw kullanın.

Duyarlı tasarım giriş noktası (dinamik görüntü alanı birimleri, medya için alan ayırma, akıcı tipografi) için Duyarlı tasarım bölümüne bakın.

8 Izgara çizgisi (diğer adıyla duvar örgüsü)

Spesifikasyon, "grid lanes" (ör. display: grid-lanes) adı altında geliştirilmektedir. Önceki deneysel prototiplerde ise grid-template-rows: masonry kullanılmıştır.

Yapılması gerekenler:

  • DOM sırasının görsel sırayla eşleşmeyebileceğini kabul ederek bugün sıkı paketleme için grid-auto-flow: dense ile ızgara kullanın.
  • Öğeler eşit ağırlıklı kartlar yerine belge parçaları olduğunda, içerik ağırlıklı duvar benzeri akış için çoklu sütun (columns: 3; column-gap: 1rem) kullanın.
  • grid-template-rows: masonry özelliğini yalnızca progresif geliştirme olarak kullanın. @supports ile özellik algılama yapın.

Şunları yapmayın:

  • Temel hedefiniz yakalanana kadar grid-template-rows: masonry özelliğini zorunlu bir şart olarak sunmayın.
.gallery       { columns: 3 200px; column-gap: 1rem; }
.gallery > *   { break-inside: avoid; margin-block-end: 1rem; }

@supports (grid-template-rows: masonry) {
  .gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    grid-template-rows: masonry;
    gap: 1rem;
    columns: unset;
  }
}