मिश्रित आकार वाली टेक्स्ट पंक्ति, दोनों स्पैन के line-height मानों से अधिक ऊँची हो सकती है, क्योंकि बेसलाइन संरेखण उनके ऊपरी और निचले विस्तारों को जोड़ता है। यह मार्गदर्शिका बताती है कि इस अतिरिक्त ऊँचाई का कारण कैसे पता करें और Mac डेस्कटॉप ब्राउज़र में दो लेबल वाली पंक्ति को कैसे समायोजित करें।

सबसे ऊँचा स्पैन ही पंक्ति की ऊँचाई क्यों तय नहीं करता?

एक अमूर्त पेज हेडर की कल्पना करें, जिसमें बड़ा Label A छोटे Label B के बगल में है। दोनों स्पैन में line-height: 40px है, फिर भी उनकी कंटेनर पंक्ति की ऊँचाई 40 CSS पिक्सेल से अधिक है। इसका कारण यह है कि इनलाइन लेआउट में ब्राउज़र आसपास की पंक्ति की गणना करने से पहले बॉक्सों को संरेखित करता है।

सामान्य इनलाइन टेक्स्ट के लिए ब्राउज़र हर बॉक्स के ऊँचाई योगदान की गणना करता है, बॉक्सों को लंबवत संरेखित करता है, फिर उनके संयुक्त विस्तारों को समेटता है। बेसलाइन संरेखण में सबसे ऊँचा ऊपरी किनारा और सबसे निचला निचला किनारा अलग-अलग स्पैन के हो सकते हैं। इसलिए नतीजा किसी भी एक योगदान से अधिक हो सकता है। पैरेंट भी न्यूनतम आकार वाला एक अदृश्य बॉक्स योगदान करता है, जिसे परंपरागत रूप से स्ट्रट कहा जाता है। W3C: पंक्ति-ऊँचाई की गणना

टेक्स्ट के लिए बेसलाइन संरेखण का संदर्भ है। यह उसकी पंक्ति-ऊँचाई के योगदान का लंबवत मध्यबिंदु नहीं है। अलग-अलग आकार के टेक्स्ट को समान पंक्ति-ऊँचाई देने से बेसलाइन के ऊपर और नीचे दोनों हिस्सों की दूरी समान नहीं हो जाती। प्रारंभिक vertical-align मान baseline है। MDN: vertical-align

तीन माप अलग-अलग रखें: फ़ॉन्ट के आरोहण और अवरोहण के मेट्रिक्स, खास अक्षरों की दिखने वाली सीमाएँ, और पंक्ति लेआउट में दिया गया स्थान। स्पैन की रंगीन पृष्ठभूमि या चयन आयत को कंटेनर पंक्ति-बॉक्स का सीधा माप न मानें; CSS इनलाइन पेंटिंग ज्यामिति और पंक्ति-ऊँचाई की गणना में अंतर करता है। W3C: लीडिंग और आधी-लीडिंग

40px के दो योगदानों से 48.4px की पंक्ति कैसे बन सकती है?

स्पष्ट पंक्ति-ऊँचाई वाले सामान्य बेसलाइन-संरेखित टेक्स्ट के लिए उपयोगी गणना यह है: फ़ॉन्ट के आरोहण और अवरोहण के योग को पंक्ति-ऊँचाई से घटाएँ, फिर बची हुई जगह को ऊपर और नीचे बराबर बाँटें। इस अतिरिक्त जगह को लीडिंग कहते हैं; इसका आधा हिस्सा आधी-लीडिंग कहलाता है। CSS Inline Layout Level 3 का Working Draft इस गणना का वर्णन करता है और ऋणात्मक लीडिंग की अनुमति देता है। इसका ड्राफ़्ट दर्जा इसमें शामिल हर नए गुण के लिए ब्राउज़र समर्थन की पुष्टि नहीं करता। W3C: लेआउट सीमाओं की गणना

नीचे दिए गए इनपुट उदाहरण के लिए हैं; ये Arial या किसी Mac फ़ॉन्ट के माप नहीं हैं। मान लें कि पैरेंट स्ट्रट का योगदान छोटे स्पैन के योगदान से मेल खाता है और कोई अन्य इनलाइन सामग्री या लंबवत ऑफ़सेट नहीं है।

योगदान फ़ॉन्ट आरोहण फ़ॉन्ट अवरोहण पंक्ति-ऊँचाई आधी-लीडिंग बेसलाइन के ऊपर बेसलाइन के नीचे
बड़ा स्पैन 32px 8px 40px 0px 32px 8px
छोटा स्पैन 9.6px 2.4px 40px 14px 23.6px 16.4px
पैरेंट स्ट्रट 9.6px 2.4px 40px 14px 23.6px 16.4px

इस बेसलाइन-संरेखित उदाहरण में, हर तरफ़ के सबसे बड़े विस्तार को अलग-अलग लें: max(32, 23.6, 23.6) + max(8, 16.4, 16.4) = 48.4px। हर योगदान कुल 40px का है, लेकिन ऊपर की सीमा बड़ा स्पैन तय करता है, जबकि नीचे की सीमा छोटा स्पैन और पैरेंट तय करते हैं। यह गणना दस्तावेज़ीकृत लेआउट गणना से निकली है, ब्राउज़र के माप का पूर्वानुमान नहीं है। W3C: इनलाइन लेआउट मॉडल

इसलिए जाँच का सवाल है: हर किनारा कौन तय कर रहा है? छोटे स्पैन की पंक्ति-ऊँचाई घटाने से उसका निचला योगदान हट सकता है, जबकि पैरेंट स्ट्रट का वही योगदान बना रह सकता है।

Mac पर इसे कैसे दोहराएँ और जाँचें?

इस प्रक्रिया के लिए अपने Mac पर Chrome इस्तेमाल करें। नया टैब खोलें, about:blank पर जाएँ, फिर Console खोलने के लिए Command + Option + J दबाएँ। Chrome JavaScript चलाने के लिए इस शॉर्टकट का दस्तावेज़ देता है। Chrome DevTools: परिचय

नीचे दिया पूरा प्रोग्राम उस खाली टैब में चलाएँ। यह समान लेबल वाली तीन कृत्रिम पंक्तियाँ बनाता है, उनके माप दिखाता है और प्रदर्शन की शैलियों को एक साथ रखने के लिए शैडो रूट का उपयोग करता है। किसी पैकेज को इंस्टॉल करने या बाहरी लाइब्रेरी की आवश्यकता नहीं है। इसे दोबारा चलाने पर पिछला प्रदर्शन बदल जाएगा।

(async () => {
  document.getElementById('line-box-demo')?.remove();
  const host = document.createElement('div');
  host.id = 'line-box-demo';
  document.body.append(host);
  const root = host.attachShadow({ mode: 'open' });
  const style = document.createElement('style');
  style.textContent = `
    :host { display: block; padding: 24px; color: #222; background: #fff; }
    .label { margin: 20px 0 6px; font: 14px Arial, sans-serif; }
    .row { font: 12px/40px Arial, sans-serif; white-space: nowrap;
      margin: 0; padding: 0; border: 0; background: #e8eef4; }
    .large { font-size: 40px; line-height: 40px; }
    .small { font-size: 12px; line-height: 40px; }
    .trim-span .small, .trim-both .small { line-height: 12px; }
    .trim-both { font-size: 40px; }
  `;
  root.append(style);
  const cases = [
    ['', 'Shared 40px line-height'],
    ['trim-span', 'Smaller span only'],
    ['trim-both', 'Parent and smaller span']
  ];
  const rows = cases.map(([className, label]) => {
    const caption = document.createElement('p');
    caption.className = 'label';
    caption.textContent = label;
    const row = document.createElement('div');
    row.className = `row ${className}`;
    for (const [size, text] of [['large', 'Label A'], ['small', ' Label B']]) {
      const span = document.createElement('span');
      span.className = size;
      span.textContent = text;
      row.append(span);
    }
    root.append(caption, row);
    return { label, row };
  });
  await document.fonts.ready;
  console.table(rows.map(({ label, row }) => ({
    case: label,
    parentLineHeight: getComputedStyle(row).lineHeight,
    largeLineHeight: getComputedStyle(row.children[0]).lineHeight,
    smallLineHeight: getComputedStyle(row.children[1]).lineHeight,
    rowHeight: row.getBoundingClientRect().height
  })));
})();

प्रोग्राम document.fonts.ready का इंतज़ार करता है, जो दस्तावेज़ के फ़ॉन्ट लोड होने और उससे जुड़े लेआउट कार्य पूरे होने के बाद हल होता है। यदि बाद में कोई दूसरा फ़ॉन्ट जोड़ें या सामग्री बदलें, तो उस बदलाव के स्थिर होने के बाद फिर से मापें। MDN: FontFaceSet.ready

तीनों पंक्तियों को नियंत्रित तुलना के रूप में देखें। पहली में दोनों स्पैन और पैरेंट की पंक्ति-ऊँचाई 40px है। दूसरी में केवल छोटे स्पैन की पंक्ति-ऊँचाई घटाकर 12px की गई है। तीसरी में पैरेंट का फ़ॉन्ट आकार भी 40px किया गया है, जिससे उसका स्ट्रट बड़े टेक्स्ट के फ़ॉन्ट आकार और पंक्ति-ऊँचाई से मेल खाता है। यदि दूसरी पंक्ति ऊँची बनी रहती है, लेकिन तीसरी छोटी हो जाती है, तो यह तुलना पैरेंट के योगदान की पहचान करती है।

अपने ब्राउज़र के नतीजों पर भरोसा करें; उदाहरण के 48.4px मान की अपेक्षा न करें। प्रोग्राम हर पंक्ति को getBoundingClientRect() से मापता है, जो पैडिंग और बॉर्डर समेत किसी एलिमेंट का बाउंडिंग आयत लौटाता है। यहाँ पंक्तियों में न पैडिंग है, न बॉर्डर; उनमें एक ही बिना लिपटी पंक्ति है और ऊँचाई अपने-आप तय होती है, इसलिए उनकी ऊँचाई पंक्ति-बॉक्स की ऊँचाई का उपयोगी अनुमान देती है। इसी API से स्पैन को मापने पर उसका आयत मापा जाएगा, कंटेनर पंक्ति-बॉक्स सीधे दिखाई नहीं देगा। MDN: getBoundingClientRect()

मौजूदा लेआउट में क्या जाँचना चाहिए?

संबंधित टेक्स्ट पर Control-क्लिक करें और Inspect चुनें। Elements में दोनों स्पैन और उनके कंटेनिंग ब्लॉक को देखें। घोषणाओं का पता लगाने के लिए Styles और लागू मान देखने के लिए Computed इस्तेमाल करें; इनहेरिट किए गए गुणों की जाँच के लिए ज़रूरत पड़ने पर Show All चालू करें। Chrome इन दृश्यों और उनके गुण फ़िल्टर का दस्तावेज़ देता है। Chrome DevTools: CSS सुविधाओं का संदर्भ

हर भाग के लिए font-family, font-size, line-height, display और vertical-align दर्ज करें। केवल दोनों स्पैन देखने के बजाय पैरेंट से शुरुआत करें। फिर कारण अलग करने के लिए यह क्रम अपनाएँ:

  1. लेआउट मॉडल की पुष्टि करें। पता करें कि बच्चे सामान्य इनलाइन प्रवाह में हैं या फ़्लेक्स अथवा ग्रिड आइटम हैं।
  2. एक ही पंक्ति की पुष्टि करें। चौड़ा परीक्षण क्षेत्र और छोटे कृत्रिम लेबल इस्तेमाल करें, ताकि टेक्स्ट लपेटने से माप भ्रमित न हो।
  3. संरेखण जाँचें। ऊपर दी गई सरल गणना लागू करने से पहले बेसलाइन शिफ़्ट या डिफ़ॉल्ट से अलग लंबवत संरेखण को अस्थायी रूप से हटाएँ।
  4. एक बार में एक योगदान बदलें। छोटे स्पैन की पंक्ति-ऊँचाई घटाकर मापें, फिर पैरेंट के फ़ॉन्ट और पंक्ति-ऊँचाई के योगदान को अलग-अलग जाँचें।
  5. वास्तविक स्थितियाँ बहाल करें। कारण पता चलने के बाद अपेक्षित फ़ॉन्ट, उपलब्ध चौड़ाई और टेक्स्ट के साथ फिर जाँचें।

इनहेरिटेंस भी जाँचें। इकाई रहित line-height: 1.2 एक गुणक आगे देता है, जिसे हर वंशज अपने फ़ॉन्ट आकार पर लागू करता है। 40px जैसी लंबाई आगे जाने पर एक निश्चित लंबाई देती है, जब तक कि उसे ओवरराइड न किया जाए; प्रतिशत की गणना घोषित करने वाले एलिमेंट के फ़ॉन्ट आकार के आधार पर होती है। इन विकल्पों से छोटे टेक्स्ट को अनपेक्षित रूप से अधिक लीडिंग मिल सकती है। normal फ़ॉन्ट और ब्राउज़र पर निर्भर करता है, इसलिए इसे किसी निश्चित संख्यात्मक मान की धारणा के रूप में इस्तेमाल नहीं करना चाहिए। MDN: line-height के मान और इनहेरिटेंस

अपेक्षित नतीजे के लिए कौन-सा समायोजन ठीक रहेगा?

दो लेबल किस चीज़ का प्रतिनिधित्व करते हैं, उसके अनुसार समायोजन चुनें। अलग-अलग लेबलों से बने छोटे हेडर की ज़रूरतें, लपेटने वाले पैराग्राफ़ में शामिल शब्दों से अलग होती हैं।

अपेक्षित नतीजा आज़माने के लिए समायोजन क्या जाँचना है
टेक्स्ट की साझा बेसलाइन बनाए रखें छोटे स्पैन को उपयुक्त पंक्ति-ऊँचाई दें और पैरेंट के फ़ॉन्ट मेट्रिक्स को मुख्य टेक्स्ट के अनुरूप करें पैरेंट स्ट्रट अब अवांछित निचला विस्तार न दे
अलग लेबलों के ऊपरी किनारे संरेखित करें दोनों इनलाइन स्पैन पर vertical-align: top आज़माएँ बदला हुआ बेसलाइन संबंध डिज़ाइन के अनुकूल हो
पंक्ति के भीतर अलग लेबलों को केंद्रित करें align-items: center वाले फ़्लेक्स कंटेनर का उपयोग करें कम चौड़ाई पर व्यवहार और आइटम का लपेटना लेआउट के अनुकूल रहे
पैराग्राफ़ का निरंतर प्रवाह बनाए रखें इनलाइन टेक्स्ट रखें और सोच-समझकर इनहेरिट की गई पंक्ति-ऊँचाई के मान चुनें बनी हुई सभी पंक्तियों में मिश्रित टेक्स्ट के लिए पर्याप्त जगह हो

vertical-align: top किसी एलिमेंट और उसके वंशजों को पंक्ति के ऊपरी किनारे पर संरेखित करता है। middle की परिभाषा अलग है: यह एलिमेंट के मध्यबिंदु को पैरेंट की बेसलाइन और उसकी x-ऊँचाई के आधे के योग से संरेखित करता है। इसलिए इसका मतलब पूरी पंक्ति के भीतर ज्यामितीय रूप से केंद्रित करना नहीं है, और संरेखण बदलने से अंतिम ऊँचाई की गारंटी नहीं मिलती। MDN: vertical-align के मान

दो स्वतंत्र लेबलों के लिए, align-items के ज़रिए फ़्लेक्सबॉक्स स्पष्ट क्रॉस-अक्ष संरेखण देता है। केंद्र संरेखण और बेसलाइन संरेखण अलग-अलग डिज़ाइन विकल्प हैं। फ़्लेक्सबॉक्स पर जाने से लेआउट संदर्भ बदलता है; इसलिए इसका उपयोग तब करें जब लेबल अलग-अलग आइटम हों और कम चौड़ाई पर नतीजे का आकलन करें। MDN: align-items

पंक्ति-ऊँचाई कम करने से टेक्स्ट अपने लेआउट योगदान के बाहर भी पेंट हो सकता है। जगह कम करने के बाद पड़ोसी पंक्तियाँ जाँचें; केवल कॉम्पैक्ट मापा हुआ बॉक्स यह साबित नहीं करता कि टेक्स्ट बिना ओवरलैप के समा रहा है। W3C: लीडिंग और आधी-लीडिंग

क्या कैनवस के माप ब्राउज़र के पंक्ति लेआउट की जगह ले सकते हैं?

कैनवस के माप इससे जुड़ा एक सवाल हल करते हैं। WHATWG measureText() को परिभाषित करता है और फ़ॉन्ट के आरोहण-अवरोहण मेट्रिक्स को खास टेक्स्ट की वास्तविक बाउंडिंग सीमाओं से अलग बताता है। ये माप कैनवस पर चित्रण के लिए उपयोगी हैं, लेकिन इंक-बाउंड माप में आसपास के DOM पैरेंट का स्ट्रट, इनलाइन संरेखण और पंक्ति-ऊँचाई के योगदान शामिल नहीं होते। इस पंक्ति की ऊँचाई का अनुमान लगाने के लिए अकेले इनका उपयोग न करें। WHATWG: TextMetrics

प्रयोग करते समय टेक्स्ट-शेपिंग की सीमाएँ बरकरार रखें। CSS के अनुसार, जब कोई प्रभावी फ़ॉर्मैटिंग बदलाव न हो तो एलिमेंट की सीमाओं के पार शेपिंग जारी रहनी चाहिए, जबकि कुछ सीमाओं—जिनमें गैर-प्रारंभिक लंबवत संरेखण शामिल है—पर शेपिंग टूटनी चाहिए। अक्षरों को अलग-अलग लपेटकर मापने से बचें: ग्रैफ़ीम क्लस्टर या लिगेचर को तोड़ने से नतीजे असंगत हो सकते हैं। पूरे लेबल या अर्थपूर्ण टेक्स्ट खंडों को एक साथ रखें। W3C: एलिमेंट की सीमाओं के पार टेक्स्ट प्रोसेसिंग और शेपिंग

अतिरिक्त ऊँचाई का कारण जानने के लिए पता करें कि पैरेंट समेत कौन-सा भाग ऊपर की सीमा तय करता है और कौन-सा नीचे की। उनके पंक्ति-ऊँचाई योगदान समायोजित करें या लेबल के उद्देश्य के अनुकूल संरेखण मॉडल चुनें, फिर अपेक्षित टेक्स्ट और फ़ॉन्ट के साथ पूरी पंक्ति को दोबारा मापें।

स्रोत