Taban çizgisine hizalanmış satır içi görsellerden oluşan yatay bir satırda, taban çizgisi her görselin alt kenar boşluğu kenarından geçer. Bu kılavuz, Mac’te Chrome’da bu koordinatın nasıl bulunacağını, küçük bir işaretleyiciyle nasıl kontrol edileceğini ve bu yöntemin ne zaman geçerli olmadığının nasıl anlaşılacağını gösterir.
Yalnızca görsel içeren bir satırın neden taban çizgisi vardır?
Yalnızca görsellerden oluşan bir satır yine de CSS satır içi düzenine katılır. Başarıyla görüntülenen bir img, yerine geçen bir öğedir: tarayıcı, görselini metin olarak değerlendirmek yerine kutusunu CSS kurallarına göre düzenler. WHATWG bu görüntüleme davranışını HTML Standardı’nın görsel görüntüleme kurallarında belgeliyor.
Olağan yatay satır içi düzende, kendine özgü bir metin taban çizgisi olmayan bir görsel, taban çizgisi hizalamasında alt kenar boşluğu kenarını kullanır. Bunun sonucunda, farklı yüksekliklerdeki iki taban çizgisine hizalı görsel aynı taban çizgisini paylaşabilirken üst kenarları farklı yüksekliklerde kalabilir. Bu kural görsellerin kutularıyla ilgilidir; görsellerin içindeki çizimi incelemez. Bkz. CSS 2, dikey hizalama.
Üç farklı sınır önemlidir:
| Sınır | Anlamı | Taban çizgisi referansı olarak uygun mu? |
|---|---|---|
| Görünen çizimin kenarı | Görselin görünen piksellerinin bittiği yer | Hayır; dosyada şeffaf boşluk olabilir |
| Görselin kenarlık kutusunun altı | getBoundingClientRect() tarafından döndürülen alt kenar |
Evet; alt kenar boşluğu hesaba katıldıktan ve taban çizgisi hizalaması doğrulandıktan sonra |
| Satır kutusunun altı | CSS satırının tamamının alt sınırı | Hayır; taban çizgisinin altına uzanabilir |
Görünür harf olmasa bile üst öğenin yazı tipi ve line-height değerleri önemini korur. CSS, strut adı verilen görünmez, yazı tipine dayalı bir katkıyı tanımlar; bu katkı satırın asgari yüksekliğini ve derinliğini belirlemeye yardımcı olur. Bu, bir görsel taban çizgisine otururken satırın altında neden boşluk kaldığını açıklar. CSS Satır İçi Düzen belirtimi, bu yazı tipi ölçülerini ve düzen sınırlarını açıklar; erişilen yayımlanmış sürüm bir Çalışma Taslağıdır, bu nedenle daha yeni özelliklerinin tüm tarayıcılarda desteklendiği varsayılmamalıdır.
Mevcut bir sayfadaki taban çizgisi nasıl bulunur?
Mac’inizde Chrome’da inceleyebileceğiniz bir sayfayla başlayın. Bir görsele sağ tıklayın ve İnceleyi seçin. Chrome, öğe seçiliyken Elements panelini açar; Styles bölmesi, uygulanan CSS’yi gösterir. Google bu iş akışını Chrome DevTools’u açma başlıklı belgede açıklar.
Koordinatı hesaplamadan önce şu koşulları kontrol edin:
- Görsel, hedef satırda normal satır içi akışa katılıyor.
- Etkin hizalaması
vertical-align: baseline. - Yazma modu yatay.
- Görselde veya üst öğelerinde ölçümü etkileyen bir dönüşüm ya da görsel konumlandırma kaydırması yok.
- Kendi taban çizgisi davranışı olan çevreleyici bir sarmalayıcıyı değil, görselin kendisini ölçüyorsunuz.
Bu koşullar hesaplamanın kapsamını belirler. Örneğin, vertical-align: bottom bir öğeyi satırın altına hizalarken middle, üst öğenin taban çizgisini artı x-yüksekliğinin yarısını kullanır. Bu değerlerin hiçbiri, görselin alt kenarının üst öğenin taban çizgisini gösterdiği anlamına gelmez. MDN bu ayrımları vertical-align başvurusunda açıklar.
Bu koşullar sağlandığında, tüm mesafeleri CSS pikseli cinsinden ifade ederek şu ilişkiyi kullanın:
baselineY = imageBorderBoxBottom + imageMarginBottom
getBoundingClientRect(), görünüm alanına göre kenarlık kutusunun alt koordinatını verir. Dikdörtgeni dolgu ve kenarlıkları içerir; bu nedenle bunlar ikinci kez eklenmemelidir. Kenar boşlukları bu dikdörtgenin dışında kalır. MDN, döndürülen geometrik bilgiyi ve koordinat sistemini Element.getBoundingClientRect() belgesinde açıklar.
Yalnızca örnek amacı taşıyan bir hesaplama için, görselin kenarlık kutusunun alt koordinatının 240.5 ve alt kenar boşluğunun 6 olduğunu varsayalım. Bu durumda taban çizgisi, görünüm alanının üstünden 246.5 CSS pikseli aşağıdadır. Kapsayıcının kenarlık kutusunun üstü 200 ise bu taban çizgisi, kapsayıcının üst kenarlık kenarından 46.5 CSS pikseli aşağıdadır. Bu, kenarlık kenarından ölçülen bir uzaklıktır; içerik kenarından ölçüldüğü varsayılamaz.
Karşılaştırma amacıyla aynı satırdaki, koşulları sağlayan başka bir görseli de ölçün. Yükseklikleri farklı olsa bile alt kenar boşluğu kenarı aynı taban çizgisini göstermelidir. Sonuçlar uyuşmuyorsa CSS’yi değiştirmeden önce hizalamayı, sarmalayıcıları, konumlandırmayı veya satır kaydırmayı inceleyin. Karşılaştırma sırasında kesirli değerleri koruyun.
Sonuç taban çizgisi işaretleyicisiyle nasıl doğrulanır?
Yararlı bir tanılama yöntemi; genişliği, yüksekliği, kenar boşlukları, dolgusu ve kenarlıkları sıfır olan, taban çizgisine hizalanmış boş bir satır içi blok kullanmaktır. Akış içi satır kutuları olmadığından taban çizgisi alt kenar boşluğu kenarıdır. Tüm bu boyutlar sıfırken bu kenar, ölçülen dikey konumuyla çakışır. Bu, CSS 2 satır içi blok taban çizgisi kuralına dayanır.
Aşağıdaki eksiksiz konsol programı, iki nötr dikdörtgen görsel ve bir işaretleyiciyle geçici bir örnek oluşturur. Örneğin iç stillerini sayfanın olağan seçicilerinden ayrı tutmak için gölge kökü kullanır. Programı, belge veya gövdesinde dönüşüm bulunmayan, standart moddaki bir belgede çalıştırın. Yalnızca kendi yapay satırını ölçer; mevcut bir sayfanın içeriğini ölçmez.
Chrome’un DevTools kısayolları belgesinde açıklandığı gibi Command + Option + J tuşlarıyla Consoleu açın ve programı çalıştırın. Herhangi bir kitaplık kurulumu ya da harici görsel dosyası gerekmez. Örnek, dikdörtgenlerini standart Canvas API ile oluşturur.
(async () => {
if (document.compatMode !== "CSS1Compat") {
throw new Error("Use a standards-mode document for this demonstration.");
}
const host = document.createElement("div");
host.style.cssText =
"all:initial;position:fixed;top:16px;left:16px;" +
"z-index:2147483647;background:white;padding:16px;" +
"color:#222;font:16px/1.5 sans-serif;";
const root = host.attachShadow({ mode: "open" });
const label = document.createElement("div");
label.textContent = "Sample A and Sample B";
const row = document.createElement("div");
row.style.cssText =
"display:block;position:relative;width:280px;" +
"margin:0;padding:0;border:0;white-space:nowrap;" +
"writing-mode:horizontal-tb;font:16px/24px sans-serif;" +
"background:#eee;";
const close = document.createElement("button");
close.textContent = "Remove demonstration";
close.addEventListener("click", () => host.remove());
root.append(label, row, close);
document.body.append(host);
try {
const images = [];
const samples = [
{ label: "Sample A", height: 32, color: "#777" },
{ label: "Sample B", height: 48, color: "#aaa" }
];
for (const sample of samples) {
const canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = sample.height;
const context = canvas.getContext("2d");
if (!context) throw new Error("A 2D canvas context is required.");
context.fillStyle = sample.color;
context.fillRect(0, 0, canvas.width, canvas.height);
const image = document.createElement("img");
image.alt = sample.label;
image.width = 64;
image.height = sample.height;
image.style.cssText =
"display:inline;vertical-align:baseline;" +
"margin:0 12px 0 0;padding:0;border:0;";
image.src = canvas.toDataURL("image/png");
row.append(image);
images.push(image);
}
await Promise.all(images.map(image => image.decode()));
if (!host.isConnected) return;
const marker = document.createElement("span");
marker.style.cssText =
"display:inline-block;vertical-align:baseline;" +
"width:0;height:0;margin:0;padding:0;border:0;" +
"font-size:0;line-height:0;";
row.append(marker);
const baselineY = marker.getBoundingClientRect().bottom;
const rowTop = row.getBoundingClientRect().top;
console.table(images.map(image => ({
sample: image.alt,
imageBottom: image.getBoundingClientRect().bottom,
markerBaseline: baselineY,
baselineFromRowTop: baselineY - rowTop
})));
const guide = document.createElement("div");
guide.style.cssText =
"position:absolute;left:0;right:0;height:1px;" +
"background:#222;pointer-events:none;";
guide.style.top = `${baselineY - rowTop}px`;
row.append(guide);
} catch (error) {
host.remove();
throw error;
}
})();
Program, ölçüm yapmadan önce her iki görselin de çözülmesini bekler. Belgelenen HTMLImageElement.decode() yöntemi bir promise döndürür ve çözme başarısız olursa reddedilebilir; bu durumda program geçici paneli kaldırır ve hatayı bildirir.
Her iki görselin de alt kenar boşluğu sıfırdır; bu nedenle bildirilen imageBottom değerlerinin markerBaseline ile eşleşmesi gerekir. İnce yatay kılavuz bu koordinatı gösterir. Satırın arka planı, altta kalan boşluğu da taban çizgisinden ayırt etmenizi sağlar. İşiniz bittiğinde Remove demonstrationı seçin.
Kontrollü bir deney için, görsel stilindeki alt kenar boşluğunu 0 değerinden 6px değerine değiştirin. Görsellerin kenarlık kutularının alt kenarları, işaretleyicinin taban çizgisinin altı CSS pikseli üstünde olmalıdır. Ortak koordinatı bulmak için önceki formülü uygulayın. Böylece örnek içinde iki bağımsız referansınız olur: görselin kenar boşluğu kenarı ve boş işaretleyici.
Bu yöntem ne zaman farklı bir yaklaşım gerektirir?
İşaretleyici tanılama amacıyla eklenir; dolayısıyla oluşan düzeni ölçer. Rastgele seçilmiş mevcut bir paragrafa işaretleyici eklemek, satır kırma olanağı yaratabilir veya düzeni başka şekilde etkileyebilir. Ön koşullar sağlanıyorsa mevcut görsel hesaplamasını tercih edin. Gerçek içeriğe işaretleyici eklerseniz aynı görsellerin aynı satırda kaldığını ve konumlarının değişmediğini doğrulayın.
| Durum | Uygun sonraki adım |
|---|---|
Görsellerde top, bottom veya middle hizalaması kullanılıyor |
Bu hizalama kuralını inceleyin; taban çizgisine hizalı görseller için kullanılan formülü değiştirmeden uygulamayın |
| Görsel satır içi blok bir sarmalayıcının içinde | Son satırdaki içerikten kaynaklanabilen sarmalayıcının taban çizgisini inceleyin |
| Görseller birden fazla satıra kayıyor | Her satır için taban çizgisini ayrı belirleyin |
| Üst öğe flex veya grid düzeni kullanıyor | Satırı satır içi bir satır olarak değerlendirmeden önce bu düzenin hizalama kurallarını inceleyin |
| Belgede dikey yazma kullanılıyor | Alt kenar y-koordinatı yerine yazma modunu dikkate alan taban çizgisi kurallarını kullanın |
| Görsel başarıyla yüklenmemiş | Görüntülenen görsel kutusu olarak değerlendirmeden önce görüntülenme durumunu belirleyin |
Son koşul önemlidir; çünkü WHATWG görüntülenen görseller, yüklenmekte olan görseller ve alternatif metin için farklı görüntüleme yolları tanımlar. Bu nedenle etiketi gösteren bozuk bir görsel, ölçmek istediğiniz ve başarıyla görüntülenen görselden farklı yorumlanmayı gerektirebilir. Bkz. HTML görsel görüntüleme kuralları.
Birkaç görsel dikdörtgeninin üst koordinatları benziyor diye ortak bir taban çizgisi olduğu sonucuna varmayın. Farklı yüksekliklerdeki görseller aynı taban çizgisini paylaşabilir ve üst kenarları farklı olabilir. Buna karşılık, üst kenarların hizalı olması taban çizgisi hizalamasını kanıtlamaz. Hangi kutuların aynı satıra katıldığını ve hangi hizalama kuralının geçerli olduğunu doğrulayın.
Metin ölçüm API’leri veya şekillendirme kitaplıkları yanıtı verebilir mi?
Burada kullanılan tarayıcı geometri yöntemleri, özel bir satır taban çizgisi alanı yerine dikdörtgenler döndürür. Range.getClientRects(), bir aralığın kapladığı alanları incelemeye yardımcı olabilir; ancak döndürdüğü dikdörtgenler taban çizgisi koordinatını doğrudan vermez. MDN bu arayüzü Range.getClientRects() belgesinde açıklar.
Canvas metrikleri başka bir soruya yanıt verir: bir parça canvas metninin, canvas bağlamında seçilen metin taban çizgisine göre konumu. Örneğin, actualBoundingBoxAscent ve actualBoundingBoxDescent, metnin mürekkep sınırlarını bu referansa göre açıklar. Mevcut bir DOM görsel satırının konumunu doğrudan vermezler. Bkz. MDN’nin TextMetrics belgeleri.
Bir metin şekillendirme kitaplığının sorumluluğu da tarayıcı satır düzeninden daha sınırlıdır. HarfBuzz kılavuzu, kitaplığın metin aralıklarını şekillendirdiğini ve glif düzeni bilgisi sağladığını; paragraf satırlarını bölme ve iki yana yaslamanın ise kapsamı dışında kaldığını belirtir. Dolayısıyla HarfBuzz’ı kurmak, tarayıcıdaki yalnızca görsellerden oluşan bir satırın ölçümünü sağlamaz. Belgelenmiş kapsamı bu sınırı açıklamaya yardımcı olur.
Yatay ve yalnızca görsellerden oluşan bir satırda önce normal satır içi akışı ve taban çizgisi hizalamasını doğrulayın. Ardından koşulları sağlayan bir görselin kenarlık kutusunun alt koordinatını okuyup alt kenar boşluğunu ekleyin. Görünür bir çapraz kontrol gerektiğinde kontrollü bir düzende sıfır boyutlu işaretleyiciyi kullanın; iki referans uyuşmadığında biçimlendirme bağlamını yeniden değerlendirin.
Kaynaklar
HTML Standardı: Görüntüleme — WHATWG.
HTML Standardı: Canvas öğesi — WHATWG.
Chrome DevTools’u açma — Google Chrome for Developers.
vertical-align CSS özelliği — MDN Web Docs.
Element: getBoundingClientRect() yöntemi — MDN Web Docs.
HTMLImageElement: decode() yöntemi — MDN Web Docs.
Range: getClientRects() yöntemi — MDN Web Docs.
TextMetrics — MDN Web Docs.
HarfBuzz ne yapmaz? — HarfBuzz.