CSS บริสุทธิ์เพื่อให้ตอบสนองขนาดตัวอักษรตามจำนวนตัวอักษรแบบไดนามิก


298

ฉันรู้ว่าสิ่งนี้สามารถแก้ไขได้อย่างง่ายดายด้วย Javascript แต่ฉันสนใจเฉพาะโซลูชัน CSS ที่แท้จริงเท่านั้น

ฉันต้องการวิธีปรับขนาดข้อความแบบไดนามิกเพื่อให้เหมาะกับ div ที่ตายตัวเสมอ นี่คือตัวอย่างมาร์กอัพ:

<div style="width: 200px; height: 1em; overflow: hidden;">
  <p>Some sample dynamic amount of text here</p>
</div>

ฉันคิดว่าอาจเป็นไปได้โดยระบุความกว้างของคอนเทนเนอร์เป็น ems และทำให้ขนาดตัวอักษรเป็นตัวรับค่านั้น


1
ว้าวรอ ระบุของwidthในemสิ่ง s ไปทางรอบอื่น ๆ มันwidthขึ้นอยู่กับfont-sizeว่า @JosephSilber นั่นคือสิ่งที่ฉันคิด
Ana

1
ฉันอยากรู้เกี่ยวกับคำถามนี้ ไดรฟ์ที่ใช้โซลูชัน pure css แทนที่จะเขียนฟังก์ชัน javascript อย่างง่ายคืออะไร
Austin Mullins

22
ไดรฟ์เป็นเพราะปัญหาเกิดขึ้นและโซลูชัน CSS ที่แท้จริงน่าทึ่ง คิดเกี่ยวกับความเป็นไปได้ของการประยุกต์ใช้เพียงไม่กี่สไตล์และรู้ว่าเนื้อหาแบบไดนามิกของคุณจะไม่ทำลายการออกแบบ
DMTintner

4
ในกรณีที่ทุกคนสะดุดกับคำถามนี้และไม่รังเกียจการใช้ JS นี่เป็นปลั๊กอินสำหรับการทำมันfittextjs.com
DMTintner

2
fitText มีข้อ จำกัด ตัวอย่างเช่นฉันต้องการเรียกใช้สำหรับหน้าจอขนาดเล็กเกินความกว้าง 500px หรือมากกว่านั้นฉันไม่ต้องการให้ส่วนหัวของฉันระเบิดอีกต่อไป ต้องเขียน JavaScript เพิ่มเติม การแยกข้อกังวลออกอย่างรวดเร็วเมื่อคุณใช้ JavaScript เพื่อจัดวาง มันไม่ได้เป็นเพียงซับด่วน
Costa

คำตอบ:


513

ฉันเพิ่งพบว่าสิ่งนี้เป็นไปได้โดยใช้หน่วย VW เป็นหน่วยที่เกี่ยวข้องกับการตั้งค่าความกว้างวิวพอร์ต มีข้อบกพร่องบางประการเช่นขาดการสนับสนุนเบราว์เซอร์ดั้งเดิม แต่นี่เป็นสิ่งที่ต้องพิจารณาอย่างจริงจังในการใช้งาน นอกจากนี้คุณยังสามารถให้ทางเลือกสำหรับเบราว์เซอร์รุ่นเก่าเช่น:

p {
    font-size: 30px;
    font-size: 3.5vw;
}

http://css-tricks.com/viewport-sized-typography/ และ https://medium.com/design-ux/66bddb327bb1


30
จะให้ 2 ups สำหรับอันนี้ โซลูชั่น CSS สำหรับผู้ชนะ!
Mihkel L.

34
เคล็ดลับสำหรับมืออาชีพ: คุณสามารถป้องกันไม่ให้ข้อความมีขนาดเล็กเกินไปและสามารถควบคุมได้โดยการทำเช่นfont-size:calc(100% + 2vw);เดียวกัน min-font-sizeมันครับ สนับสนุนเบราว์เซอร์จะคล้ายกับcalc vw
Prinzhorn

116
ลงทะเบียนแล้ว แต่ตอนนี้ฉันสงสัยว่าจริง ๆ แล้วตอบคำถามเดิมหรือไม่ ความเข้าใจของฉันคือความยาวข้อความของคุณเป็นแบบไดนามิกและคุณต้องการเปลี่ยนขนาดตัวอักษรให้พอดีกับความกว้างของคุณdiv(200px) วิธีนี้แก้ปัญหาได้อย่างไร
Floremin

26
ฉันเห็นด้วยกับความเชื่อมั่นของ @ Floremin สิ่งนี้จะปรับขนาดตัวอักษรทั้งหมดตามความกว้าง / ความสูงของพอร์ตมุมมองไม่ใช่ที่เก็บของความกว้าง / ความสูงของข้อความ
MickJuice

24
@Floremin ถูกต้องนี่ไม่ได้ตอบคำถาม นี้จะคำนวณขนาดตัวอักษรเป็นหน้าที่ของความกว้างของภาชนะที่ไม่เป็นฟังก์ชั่นความยาวของสตริงที่เกี่ยวข้องกับภาชนะกว้าง
เฮนรี่

113

CSS3รองรับมิติใหม่ที่สัมพันธ์กับการดูพอร์ต แต่นี่ใช้ไม่ได้กับ android <4.4

  1. 3.2vw = 3.2% ของความกว้างของวิวพอร์ต
  2. 3.2vh = 3.2% ของความสูงของวิวพอร์ต
  3. 3.2vmin = ขนาดเล็กกว่า 3.2vw หรือ 3.2vh
  4. 3.2vmax = ใหญ่กว่า 3.2vw หรือ 3.2vh

    body
    {
        font-size: 3.2vw;
    }

ดูcss-tricks.com / ....และดูที่caniuse.com / ....

หรือ

ใช้แบบสอบถามสื่อวิธีที่ง่ายที่สุดคือการใช้มิติใน% หรือ em เพียงเปลี่ยนขนาดตัวอักษรพื้นฐานทุกอย่างจะเปลี่ยน

@media (max-width: @screen-xs) {
    body{font-size: 10px;}
}

@media (max-width: @screen-sm) {
    body{font-size: 14px;}
}


h5{
    font-size: 1.4em;
}

ใช้ส่วนข้อมูลเป็น% หรือ emem เพียงเปลี่ยนขนาดตัวอักษรพื้นฐานทุกอย่างจะเปลี่ยน ก่อนหน้านี้คุณสามารถเปลี่ยนแบบอักษร body และไม่ใช่ h1 ทุกครั้งหรือปล่อยให้ขนาดแบบอักษรพื้นฐานเป็นค่าเริ่มต้นของอุปกรณ์และพักทั้งหมดใน em

ดูkyleschaeffer.com / ....สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ em, px และ%


12
คำถามเกี่ยวกับการปรับสเกลสัมพันธ์กับคอนเทนเนอร์ไม่ใช่กับวิวพอร์ตทั้งหมด
Arnaud Weil

6
... และคำถามก็เกี่ยวกับการไต่ระดับขึ้นอยู่กับจำนวนตัวละคร
Bravo


14

วิธีเดียวที่อาจจะเป็นการตั้งค่าความกว้างที่แตกต่างกันสำหรับขนาดหน้าจอที่แตกต่างกัน แต่วิธีการนี้ไม่ได้ผลและคุณควรใช้โซลูชัน js

h1 {
    font-size: 20px;
}

@media all and (max-device-width: 720px){
    h1 {
        font-size: 18px;
    }
}

@media all and (max-device-width: 640px){
    h1 {
        font-size: 16px;
    }
}

@media all and (max-device-width: 320px){
    h1 {
        font-size: 12px;
    }
}

12

ฉันรู้ว่าฉันกำลังถามคำถามที่ตายไปนาน แต่ฉันมีคำถามเดียวกันและฉันต้องการเพิ่มบางอย่าง โปรดอย่าแบนฉันสำหรับเรื่องนี้ฉันรู้สึกว่ามันสำคัญพอที่จะพิสูจน์คำตอบนี้ฉันจะลบถ้าจำเป็น @ โจเซฟซิลเบอร์ผิดการเข้ารหัสความเป็นไปได้ทั้งหมดเป็นวิธีปฏิบัติได้จริง เหตุผลก็เพราะมีความเป็นไปได้ไม่ จำกัด ในทางเทคนิคแล้วมี แต่ 99% ของผู้เข้าชมของคุณจะใช้ความละเอียดมาตรฐาน นี่เป็นความจริงเป็นสองเท่าสำหรับมือถือ (เหตุผลหลักสำหรับการออกแบบเว็บที่ตอบสนองได้) เพราะระบบปฏิบัติการมือถือส่วนใหญ่ใช้แอพแบบเต็มหน้าจอโดยไม่มีการปรับขนาดหน้าต่าง

นอกจากนี้ความสูงนั้นไม่เกี่ยวข้องมากนักเนื่องจากแถบเลื่อน (จนถึงจุดหนึ่งผมจะทิ้งหน้าเว็บที่ยาวเกินกว่า 4 หรือ 5 ฟุตทันที แต่นี่ก็เป็นเรื่องจริง) ดังนั้นคุณต้องกังวลเกี่ยวกับความกว้าง และที่จริงแล้วความกว้างเพียงอย่างเดียวที่คุณต้องใช้ในการเขียนโค้ดมีดังนี้: 240, 320, 480 (สำหรับ iThings รุ่นเก่า), 640, 800, 1024, 1280, 1440, 1600, 1920, 2048, 2560 4k มันจะขยายภาพของคุณมากเกินไปและขนาด 2560 ขยายไปถึงความกว้าง 100% ดูดีบนหน้าจอ 4k (ฉันได้ทดสอบสิ่งนี้แล้ว) นอกจากนี้อย่ากังวลกับ 720 (720x480) ตามที่ผู้โพสต์ก่อนหน้าแนะนำ ความละเอียดของมันถูกใช้โดยกล้องดิจิตอลเกือบทั้งหมดและถึงแม้จะเป็นเรื่องผิดปกติ

หากใครบางคนกำลังใช้ความละเอียดที่แปลกใหม่ตัวเรนเดอร์เกือบทุกตัวที่ทำใน 15 ปีที่ผ่านมาจะปัดเศษลงดังนั้นหากความกว้างหน้าจอของใครบางคนพูด 1100 มันจะโหลดกฎ 1024 CSS เว็บไซต์ของคุณไม่ควรหยุด วิธีนี้ทำให้บัญชีมีความละเอียดที่แปลกใหม่โดยพยายามสร้างกฎการตอบสนองที่ไม่จำเป็นและความคิดที่คุณต้องใช้รหัสสำหรับทุกพิกเซลการติดตั้งที่เป็นไปได้นั้นพิกเซลนั้นไร้สาระเว้นแต่ว่ามีคนใช้เว็บเบราว์เซอร์ ทั้งหมดอยู่ดี


1
และตอนนี้ 375 และ 414 สำหรับ iPhone
6/6

อาจง่ายยิ่งขึ้นหากใช้ SASS หรือ Compass และเข้าสู่ฟังก์ชั่น ฟังก์ชั่นสามารถทำงาน CSS ทั้งหมดที่เหมาะกับคุณได้ เขียนเมื่อใช้งานจำนวนมาก
cjbarth

ความสูงค่อนข้างไม่เกี่ยวข้องจนกว่าคุณจะเปิดอุปกรณ์90ºที่ด้านข้างนั่นคือ
Carvo Loco

สิ่งนี้ไม่เกี่ยวกับความกว้างของตู้คอนเทนเนอร์ซึ่งมีความเป็นไปได้ที่ไม่มีที่สิ้นสุดอย่างง่ายดาย
mcheah

8

สำหรับการอ้างอิงโซลูชันที่ไม่ใช่ CSS:

ด้านล่างคือ JS บางตัวที่ปรับขนาดแบบอักษรใหม่ตามความยาวข้อความภายในคอนเทนเนอร์

Codepenด้วยรหัสที่ปรับเปลี่ยนเล็กน้อย แต่มีแนวคิดเดียวกันดังนี้:

function scaleFontSize(element) {
    var container = document.getElementById(element);

    // Reset font-size to 100% to begin
    container.style.fontSize = "100%";

    // Check if the text is wider than its container,
    // if so then reduce font-size
    if (container.scrollWidth > container.clientWidth) {
        container.style.fontSize = "70%";
    }
}

สำหรับฉันฉันเรียกใช้ฟังก์ชันนี้เมื่อผู้ใช้ทำการเลือกในเมนูแบบเลื่อนลงจากนั้น div ในเมนูของฉันจะได้รับการเติมข้อมูล (นี่คือที่ที่ฉันมีข้อความไดนามิกเกิดขึ้น)

    scaleFontSize("my_container_div");

นอกจากนี้ฉันยังใช้ CSS ellipses ("... ") เพื่อตัดทอนข้อความที่ยาวขึ้นเช่นกัน:

#my_container_div {
    width: 200px; /* width required for text-overflow to work */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

ดังนั้นในที่สุด:

  • ข้อความสั้น:เช่น "APPLES"

    แสดงผลอย่างเต็มที่ตัวอักษรขนาดใหญ่ที่ดี

  • ข้อความยาว:เช่น "แอปเปิ้ล & ส้ม"

    รับการลดขนาดลง 70% ผ่านฟังก์ชั่นการปรับขนาด JS ด้านบน

  • ข้อความยาวสุด:เช่น "แอปเปิ้ล & ส้ม & กล้วย ... "

    รับลดขนาดลง 70% และถูกตัดทอนด้วย "... " วงรีผ่านฟังก์ชันการปรับขนาด JS ด้านบนพร้อมกับกฎ CSS

คุณสามารถสำรวจการเล่นด้วยระยะห่างระหว่างตัวอักษร CSS เพื่อทำให้ข้อความแคบลงโดยคงขนาดตัวอักษรไว้เหมือนเดิม


โหวตลงขณะที่ผู้ใช้กำลังขอวิธีแก้ปัญหา CSS อย่างแท้จริง
AnotherLongUsername

2

ดังที่หลายคนกล่าวไว้ในความคิดเห็นต่อการโพสต์ของ @ DMTinter OP ได้ถามถึงจำนวน ("จำนวน") ของตัวละครที่เปลี่ยนไป เขายังถามเกี่ยวกับ CSS แต่ตามที่ @Alexander ระบุว่า "ไม่สามารถทำได้ด้วย CSS เท่านั้น" เท่าที่ฉันสามารถบอกได้ว่าดูเหมือนจะเป็นจริงในเวลานี้ดังนั้นจึงเป็นเรื่องจริงที่ผู้คนต้องการทราบสิ่งที่ดีที่สุดถัดไป

ฉันไม่ได้ภูมิใจในสิ่งนี้โดยเฉพาะ แต่มันได้ผล ดูเหมือนว่าจะมีโค้ดจำนวนมากเกินไปที่จะทำให้สำเร็จ นี่คือหลัก:

function fitText(el){
  var text = el.text();
  var fsize = parseInt(el.css('font-size'));
  var measured = measureText(text, fsize);

  if (measured.width > el.width()){
    console.log('reducing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize );
      if(m.width > el.width()){
        el.css('font-size', --fsize + 'px');
      }
      else{
        break;
      }
    }
  }
  else if (measured.width < el.width()){
    console.log('increasing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize);
      if(m.width < el.width()-4){ // not sure why -4 is needed (often)
        el.css('font-size', ++fsize + 'px');
      }
      else{
        break;
      }
    }
  }
}

นี่คือ JS Bin: http://jsbin.com/pidavon/edit?html,css,js,console,output
กรุณาแนะนำการปรับปรุงที่เป็นไปได้ (ฉันไม่สนใจใช้ผ้าใบเพื่อวัดข้อความ ... ดูเหมือน ชอบค่าใช้จ่ายมากเกินไป (?))

ขอบคุณ @Pete สำหรับฟังก์ชั่น measureText: https://stackoverflow.com/a/4032497/442665


2

วิธีนี้อาจช่วย:

$(document).ready(function () {
    $(window).resize(function() {
        if ($(window).width() < 600) {
            $('body').css('font-size', '2.8vw' );
        } else if ($(window).width() >= 600 && $(window).width() < 750) {
            $('body').css('font-size', '2.4vw');
        } 
         // and so on... (according to our needs)
        } else if ($(window).width() >= 1200) {
            $('body').css('font-size', '1.2vw');
        }
    }); 
  });

มันใช้งานได้ดีสำหรับฉัน!


สิ่งนี้คำนึงถึงการตัดคำอย่างไร
Leif Neland


2
calc(42px + (60 - 42) * (100vw - 768px) / (1440 - 768));

ใช้สมการนี้

สำหรับสิ่งที่ใหญ่กว่าหรือเล็กกว่า 1440 และ 768 คุณสามารถกำหนดเป็นค่าคงที่หรือใช้วิธีการเดียวกัน

ข้อเสียเปรียบกับวิธีแก้ปัญหา vw คือคุณไม่สามารถตั้งอัตราส่วนอัตราส่วนได้กล่าวว่า 5vw ที่ความละเอียดหน้าจอ 1440 อาจกลายเป็นขนาดตัวอักษร 60px ขนาดตัวอักษรความคิดของคุณ แต่เมื่อคุณลดความกว้างของหน้าต่างลงเหลือ 768 อาจสิ้นสุดลง เป็น 12px ไม่ใช่ขั้นต่ำที่คุณต้องการ ด้วยวิธีการนี้คุณสามารถตั้งค่าขอบเขตบนและขอบเขตล่างของคุณและแบบอักษรจะปรับขนาดตัวเองในระหว่าง


-2

สร้างตารางการค้นหาที่คำนวณ font-size <div>ขึ้นอยู่กับความยาวของสตริงภายในของคุณ

const fontSizeLookupTable = () => {
  // lookup table looks like: [ '72px', ..., '32px', ..., '16px', ..., ]
  let a = [];
  // adjust this based on how many characters you expect in your <div>
  a.length = 32;
  // adjust the following ranges empirically
  a.fill( '72px' ,     );
  a.fill( '32px' , 4 , );
  a.fill( '16px' , 8 , );
  // add more ranges as necessary
  return a;
}

const computeFontSize = stringLength => {
  const table = fontSizeLookupTable();
  return stringLength < table.length ? table[stringLength] : '16px';
}

ปรับและปรับพารามิเตอร์ทั้งหมดโดยการทดสอบเชิงประจักษ์


การทดสอบเชิงประจักษ์สำหรับพารามิเตอร์นั้นเป็นการค้นหาแบบไบนารี่ที่มีความซับซ้อนของเวลา: O (บันทึก n)
ให้ฉันพูดเกี่ยวกับเรื่องนี้

คุณลืมที่จะเรียกฟังก์ชั่นนี้จริง ๆ แล้วยังต้องเข้าถึงความยาวของอาเรย์ด้วยคุณสมบัติ
ลูก

@ lukk: ขอบคุณสำหรับความคิดเห็น แก้ไขทันที
ให้ฉันพูดเกี่ยวกับเรื่องนี้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.