บรรทัดข้อความที่มีความกว้างเท่ากัน

ฟีเจอร์บนเว็บ: text-fit text-wrap: balance text-box

การจัดวางข้อความแบบโปสเตอร์ที่แต่ละบรรทัดปรับขนาดให้ครอบคลุมความกว้างทั้งหมดของคอนเทนเนอร์จะช่วยสร้างหัวข้อที่โดดเด่นสะดุดตาได้ เมื่อใช้ text-fit เบราว์เซอร์จะปรับขนาดแต่ละบรรทัดในระหว่างการจัดเลย์เอาต์ เพื่อให้ข้อความยังคงถูกต้องเมื่อมีการปรับขนาด การเปลี่ยนแปลงข้อความ และการโหลดแบบอักษร

สำหรับข้อความบรรทัดเดียวที่เติมเต็มคอนเทนเนอร์ (เช่น ส่วนหัวหรือข้อความที่ดึงมา) ให้ใช้ text-fit กับองค์ประกอบนั้นโดยตรง คู่มือนี้ครอบคลุมการจัดวางข้อความหลายบรรทัด

การติดตั้งใช้งานขั้นพื้นฐาน

สำหรับบรรทัดที่บังคับ

  • รวมแต่ละบรรทัดใน <span> ด้วย display: block
  • ใช้ white-space: nowrap กับแต่ละบรรทัดที่บังคับ <span>

หลักเกณฑ์การใช้งานมีดังนี้

  • ใช้ text-fit: grow per-line-all <percentage> ในส่วนหัวเอง
  • ใช้ per-line-all ไม่ใช่ per-line per-line จะข้ามบรรทัดสุดท้ายและบรรทัดที่ลงท้ายด้วยการขึ้นบรรทัดใหม่แบบบังคับ ดังนั้นเมื่อมี 1 บล็อกต่อบรรทัด ระบบจะไม่ปรับขนาดใดๆ
  • grow ใช้ร่วมกับ shrink ไม่ได้ ตั้งค่า font-size พื้นฐานเป็นค่าสูงสุดหรือต่ำสุดก็ได้ โดยขึ้นอยู่กับว่าค่าใดจะเป็นค่าสำรองที่ดีกว่าหรือคำนวณได้ง่ายกว่า และตั้งค่า text-fit เป็น shrink หรือ grow ตามลำดับ หากไม่มีเหตุผลที่จะใช้ shrink ให้เลือก grow + ตั้งค่า font-size เป็นค่าต่ำสุด เนื่องจากปลอดภัยกว่าในกรณีส่วนใหญ่
  • จำกัดการเพิ่มขึ้นหรือลดลงด้วยเปอร์เซ็นต์ (เช่น 300%) เป็นเกณฑ์ป้องกันเสมอ
  • คอนเทนเนอร์ต้องมีขนาดอินไลน์ที่แน่นอน text-fit ไม่เคยเปลี่ยนขนาดที่แท้จริง จึงไม่มีผลกับความกว้าง fit-content/max-content หรือรายการ Flex/Grid ที่มีขนาดเท่ากับเนื้อหา
  • ตัดระยะห่างระหว่างบรรทัดเหนือบรรทัดแรกและใต้บรรทัดสุดท้าย: ดูการจัดข้อความที่แม่นยำ
  • กำหนดให้ line-height มีขนาดเล็ก ไม่เกิน 1 มิฉะนั้นช่องว่างระหว่างบรรทัดของแบบอักษรขนาดต่างๆ จะดูไม่สวยงาม
  • สำคัญ: โปรดทราบว่า font-size ที่คำนวณแล้วจะไม่มีการเปลี่ยนแปลง ดังนั้นระยะห่าง em จะไม่ปรับขนาด
  • หากต้องการหลีกเลี่ยงการเน้นคำที่ขึ้นบรรทัดใหม่โดยไม่ตั้งใจ ให้ใช้ text-wrap: balance หรือ text-wrap: pretty หากมีบรรทัดว่าง

การเว้นวรรค

หากบังคับให้ทุกบรรทัดมีระยะห่างเท่ากัน จะช่วยให้ควบคุมระยะห่างได้มากขึ้น ดังนี้

  • ใช้ text-box: trim-both cap alphabetic กับบล็อกบรรทัดแต่ละบล็อกเพื่อให้กล่องพอดีกับสัญลักษณ์ของตัวเอง โดยจะตัดแต่งโดยใช้เมตริกที่ปรับขนาดแล้ว ดูรายละเอียดเพิ่มเติมได้ที่การจัดข้อความให้ตรงกันอย่างแม่นยำ
  • เว้นระยะห่างระหว่างบรรทัดโดยใช้ Flexbox หรือ Grid + gap ในส่วนหัว ไม่ใช่ line-height จากนั้นช่องว่างจะสม่ำเสมอแทนที่จะเพิ่มขึ้นตามขนาดแบบอักษรของแต่ละบรรทัด

หากบางบรรทัดว่างเปล่า อย่าใช้ text-box เนื่องจากจะตัดเฉพาะบรรทัดแรกและบรรทัดสุดท้ายเท่านั้น ดังนั้นบรรทัดด้านนอกจะอยู่ชิดกับอักขระ ขณะที่ช่องว่างภายในจะยังคงมีระยะห่างระหว่างบรรทัด ให้ line-height ควบคุมระยะห่างทั้งหมด

การออกแบบภาพ

  • โลโก้จะดูดีที่สุดเมื่อขนาดแบบอักษรระหว่างบรรทัดมีความแตกต่างกันอย่างมาก หลีกเลี่ยงการสร้างโลโก้จากข้อความที่มีบรรทัดสม่ำเสมอเป็นส่วนใหญ่ เนื่องจากจะส่งผลให้ขนาดแบบอักษรไม่เหมือนกันหรือไม่แตกต่างกันมากพอ ซึ่งละเมิดหลักการออกแบบเรื่องความเปรียบต่าง คุณสามารถทำได้โดยบังคับให้บรรทัดสั้นลง โดยตัดคำเพื่อเน้นในบล็อกและปล่อยให้ส่วนที่เหลือตัดคำ เช่น การจัดวางแบบผสม ซึ่งมีความสำคัญอย่างยิ่งเมื่อใช้ร่วมกับ text-wrap: balance
  • ควรใช้ร่วมกับ text-transform: uppercase เมื่อใช้กับสคริปต์ตะวันตก เนื่องจากตัวอักษรที่มีหางขึ้นและหางลงมักจะสร้างพื้นที่ที่ติดอยู่และ/หรือทับซ้อนกับบรรทัดที่อยู่ติดกัน ซึ่งทำให้ผลลัพธ์ดูไม่สวยงามนัก
  • เมื่อบังคับให้ใช้บรรทัดสั้นๆ ให้เลือกคำที่จะช่วยปรับปรุงข้อความหากมีการเน้น
  • ข้อจำกัด: ข้อความที่ขยายใหญ่ขึ้นจะมีน้ำหนักของสายตาเพิ่มขึ้นด้วย และเส้นขอบจะดูหนาขึ้น ปัจจุบันยังไม่มีวิธีถ่วงดุลปัญหานี้ เช่น การลด font-weight สำหรับข้อความขนาดใหญ่ เนื่องจากไม่มีหน่วยที่จะใช้ในการคำนวณ เพราะการปรับขนาดไม่ส่งผลต่อหน่วยที่สัมพันธ์กับแบบอักษร เช่น em

กลยุทธ์สำรอง

สำหรับ text-box

text-box ไม่จำเป็นต้องมีทางเลือกสำรองแยกต่างหาก: ใช้ line-height ขนาดเล็กในล็อกอัปแบบคงที่ด้วย ซึ่งจะไม่มีผลใน text-box และทำให้ช่องว่างแคบลงในกรณีที่ไม่รองรับ โดยแลกกับช่องว่างที่ปรับขนาดตามขนาดแบบอักษรของแต่ละบรรทัด

สำหรับ text-wrap: balance

สำหรับ text-fit

บรรทัดที่บังคับจะมีทางเลือกสำรองที่สั้นและตรงตามที่กำหนด นั่นคือวัดแต่ละบรรทัดที่ขนาดฐานและปรับขนาดตามอัตราส่วนต่อคอนเทนเนอร์ โดยมีขีดจำกัดเดียวกัน

@supports not (text-fit: grow) {
  .lockup > span {
    /* Shrink-wrap each line so its width is the text width */
    width: fit-content;
    /* --text-fit-scale is measured by the script; the cap mirrors the text-fit percentage */
    font-size: min(var(--text-fit-scale, 1) * 1em, 300%);
  }
}
if (!CSS.supports('text-fit', 'grow per-line-all')) {
  const fit = lockup => {
    const lines = [...lockup.querySelectorAll(':scope > span')];
    // Unscale first: on a refit, offsetWidth would otherwise include the previous scale
    for (const line of lines) line.style.removeProperty('--text-fit-scale');
    // MANDATORY: all reads, then all writes. Interleaving them (e.g. reading
    // lockup.clientWidth inside the write loop) forces one reflow per line.
    const scales = lines.map(line => lockup.clientWidth / line.offsetWidth);
    lines.forEach((line, i) => line.style.setProperty('--text-fit-scale', scales[i]));
  };
  // Refit on resize and font load
  for (const lockup of document.querySelectorAll('.lockup')) {
    new ResizeObserver(() => fit(lockup)).observe(lockup);
  }
}

บรรทัดที่ไม่มีการบังคับขึ้นบรรทัดใหม่จะไม่มีการสำรองที่เชื่อถือได้ (ไม่ทราบการขึ้นบรรทัดใหม่จนกว่าจะมีการจัดเลย์เอาต์) การเพิ่มประสิทธิภาพแบบต่อเนื่องเป็นส่วนหัวที่สมดุลซึ่งมีขนาดฐานที่ยืดหยุ่น เช่น clamp(2rem, 1rem + 5cqi, 5rem) ใน Lockup แบบผสม สคริปต์ด้านบนยังคงพอดีกับบรรทัดที่บังคับ บล็อกที่ตัดขึ้นบรรทัดใหม่จะวัดความกว้างเท่ากับคอนเทนเนอร์ ดังนั้นจึงคงสเกล 1 ไว้และมีขนาดฐานที่ยืดหยุ่นเท่านั้น

หากการปรับข้อความให้พอดีเป็นสิ่งสำคัญ ให้พิจารณาใช้ไลบรารี JS (เช่น fitty) ซึ่งจะโหลดแบบมีเงื่อนไขเฉพาะในกรณีที่ไม่รองรับ text-fit เท่านั้น