CSS thuần để làm cho kích thước phông chữ đáp ứng dựa trên số lượng ký tự động


298

Tôi biết rằng điều này có thể được giải quyết khá dễ dàng với Javascript, nhưng tôi chỉ quan tâm đến một giải pháp CSS thuần túy.

Tôi muốn một cách để thay đổi kích thước văn bản một cách linh hoạt để nó luôn phù hợp với một div cố định. Đây là đánh dấu mẫu:

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

Tôi đã nghĩ rằng có lẽ điều này có thể thực hiện được bằng cách chỉ định chiều rộng của container trong EMS và lấy kích thước phông chữ để kế thừa giá trị đó?


1
Wow, đợi đã. Việc chỉ định điều widthtrong ems đi theo cách khác. Đó là widthđiều phụ thuộc vào font-size. @JosephSilber Đó chính xác là những gì tôi nghĩ.
Ana

1
Tôi tò mò về câu hỏi này. Ổ đĩa để sử dụng giải pháp css thuần túy thay vì viết một hàm javascript đơn giản là gì?
Austin Mullins

22
Ổ đĩa chỉ đơn giản là vì sự cố tồn tại và một giải pháp CSS thuần túy sẽ rất tuyệt vời. Hãy suy nghĩ về khả năng áp dụng chỉ một vài phong cách và biết rằng nội dung động của bạn sẽ không bao giờ phá vỡ thiết kế.
DMTintner

4
Chỉ trong trường hợp bất kỳ ai vấp phải câu hỏi này và không bận tâm khi sử dụng JS, đây là một plugin để thực hiện nó fittextjs.com
DMTintner

2
fitText có giới hạn. Ví dụ: tôi chỉ muốn chạy nó cho màn hình nhỏ, ngoài chiều rộng 500px hoặc hơn, tôi không muốn các tiêu đề của mình nổ tung thêm nữa. Điều này đòi hỏi phải viết nhiều JavaScript hơn. Sự phân tách các mối quan tâm bị phá vỡ rất nhanh khi bạn sử dụng JavaScript để bố trí. Nó không bao giờ chỉ là một lớp lót nhanh chóng.
Costa

Câu trả lời:


513

Tôi chỉ phát hiện ra rằng điều này là có thể sử dụng các đơn vị VW. Chúng là các đơn vị liên quan đến việc thiết lập chiều rộng khung nhìn. Có một số nhược điểm, chẳng hạn như thiếu hỗ trợ trình duyệt cũ, nhưng đây chắc chắn là điều cần xem xét nghiêm túc khi sử dụng. Ngoài ra, bạn vẫn có thể cung cấp dự phòng cho các trình duyệt cũ hơn như vậy:

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

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


30
Sẽ cung cấp cho 2 up cho cái này. Giải pháp CSS cho chiến thắng!
Mihkel L.

34
Mẹo chuyên nghiệp: bạn có thể ngăn văn bản trở nên quá nhỏ và lấy lại quyền kiểm soát bằng cách thực hiện font-size:calc(100% + 2vw);hoặc tương tự. Thật là tuyệt min-font-size. Hỗ trợ trình duyệt calctương tự như vw.
Prinzhorn

116
Được nâng cấp, nhưng bây giờ tôi tự hỏi nếu điều này thực sự trả lời câu hỏi ban đầu. Tôi hiểu rằng chiều dài văn bản của bạn là động và bạn muốn thay đổi kích thước phông chữ để luôn vừa với chiều rộng của div(200px). Làm thế nào để giải quyết vấn đề này?
Floremin

26
Tôi đồng ý với tình cảm của @ Floremin. Tỷ lệ này TẤT CẢ các kích thước phông chữ dựa trên chiều rộng / chiều cao của cổng xem, không phải là vùng chứa chiều rộng / chiều cao của văn bản.
MickJuice 18/03/2015

24
@Floremin là đúng, điều này không giải quyết câu hỏi. Điều này tính toán kích thước phông chữ là một hàm của chiều rộng vùng chứa, không phải là hàm của độ dài chuỗi vì nó liên quan đến chiều rộng vùng chứa
henry

113

CSS3 hỗ trợ các kích thước mới liên quan đến cổng xem. Nhưng điều này không hoạt động trong Android <4.4

  1. 3,2vw = 3,2% chiều rộng của khung nhìn
  2. 3,2vh = 3,2% chiều cao của khung nhìn
  3. 3.2vmin = Nhỏ hơn 3.2vw hoặc 3.2vh
  4. 3.2vmax = Lớn hơn 3.2vw hoặc 3.2vh

    body
    {
        font-size: 3.2vw;
    }

xem css-tricks.com / .... và cũng xem caniuse.com / ....

hoặc là

Sử dụng truy vấn phương tiện. Cách đơn giản nhất là sử dụng kích thước theo% hoặc em. Chỉ cần thay đổi kích thước phông chữ cơ bản, mọi thứ sẽ thay đổi.

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

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


h5{
    font-size: 1.4em;
}

Sử dụng kích thước theo % hoặc em . Chỉ cần thay đổi kích thước phông chữ cơ bản, mọi thứ sẽ thay đổi. Trong lần trước, bạn chỉ có thể thay đổi phông chữ cơ thể chứ không phải h1 mỗi lần hoặc để kích thước phông chữ cơ bản về mặc định của thiết bị và đặt tất cả trong em

xem kyleschaeffer.com / .... để biết thêm thông tin về em, px và%


12
Câu hỏi là về tỷ lệ liên quan đến container, không phải cho toàn bộ khung nhìn.
Arnaud Weil

6
... và các câu hỏi là về nhân rộng dựa trên số lượng ký tự
Bravo


14

Cách duy nhất có lẽ là đặt các độ rộng khác nhau cho các kích thước màn hình khác nhau, nhưng cách tiếp cận này không chính xác và bạn nên sử dụng giải pháp 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

Tôi biết tôi đang đánh giá một câu hỏi đã chết từ lâu, nhưng tôi đã có cùng một câu hỏi và tôi muốn thêm một cái gì đó. Xin đừng cấm tôi vì điều này, tôi cảm thấy nó đủ quan trọng để biện minh cho câu trả lời này, tôi sẽ xóa nếu cần. @Joseph Silber là sai, mã hóa tất cả các khả năng thực sự là một cách khả thi để làm điều này. Lý do là bởi vì thực sự không có khả năng vô hạn. Vâng, về mặt kỹ thuật là có, nhưng 99% khách truy cập của bạn sẽ sử dụng độ phân giải tiêu chuẩn. Điều này hoàn toàn đúng đối với thiết bị di động (lý do chính cho thiết kế web đáp ứng) bởi vì hầu hết các hệ điều hành di động đều chạy ứng dụng toàn màn hình mà không thay đổi kích thước cửa sổ.

Ngoài ra, chiều cao không liên quan nhiều vì thanh cuộn (đến một điểm, tôi sẽ ngay lập tức rời khỏi một trang web dài hơn 4 hoặc 5 feet, nhưng điều này chủ yếu là đúng), vì vậy bạn chỉ cần lo lắng về chiều rộng. Và thực sự, các độ rộng duy nhất bạn cần mã hóa là: 240, 320, 480 (đối với iThings cũ), 640, 800, 1024, 1280, 1440, 1600, 1920, 2048, 2560. Thậm chí đừng bận tâm 4k, nó sẽ làm mờ hình ảnh của bạn quá nhiều và kích thước 2560 được kéo dài đến 100% chiều rộng trông rất ổn trên màn hình 4k (tôi đã thử nghiệm điều này). Ngoài ra, đừng bận tâm với 720 (720x480) như poster trước đã đề xuất. Độ phân giải của nó được sử dụng gần như độc quyền bởi các máy ảnh kỹ thuật số, và thậm chí sau đó nó rất không phổ biến.

Nếu ai đó đang sử dụng độ phân giải kỳ lạ, gần như bất kỳ trình kết xuất nào được thực hiện trong 15 năm qua sẽ làm tròn xuống, vì vậy nếu chiều rộng màn hình của ai đó là, hãy nói. 1100, nó sẽ tải quy tắc 1024 CSS, trang web của bạn không nên phá vỡ. Điều này làm cho việc tính toán các độ phân giải kỳ lạ bằng cách cố gắng tạo ra một quy tắc đáp ứng không cần thiết và ý tưởng rằng bạn cần mã hóa cho mọi pixel thiết lập có thể bằng pixel là vô lý, trừ khi ai đó sử dụng trình duyệt web lỗi thời mà trang web của bạn có thể sẽ không tải tất cả dù sao đi nữa


1
Và bây giờ 375 và 414 cho iPhone 6/6 +: - /
yar1

Có khả năng thậm chí còn dễ dàng hơn nếu sử dụng SASS hoặc La bàn và đi vào các chức năng. Một chức năng có thể làm tất cả những gì CSS làm việc cho bạn; viết một lần sử dụng nhiều.
cjbarth

chiều cao là khá nhiều không liên quan cho đến khi bạn xoay thiết bị 90 độ về phía nó, đó là
Carvo Loco

Điều này không liên quan gì đến chiều rộng của một container mặc dù - trong đó có những khả năng vô hạn dễ dàng.
39

8

Để tham khảo, một giải pháp không phải CSS:

Dưới đây là một số JS thay đổi kích thước phông chữ tùy thuộc vào độ dài văn bản trong vùng chứa.

Codepen với mã được sửa đổi một chút, nhưng cùng một ý tưởng như dưới đây:

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%";
    }
}

Đối với tôi, tôi gọi hàm này khi người dùng thực hiện lựa chọn trong trình đơn thả xuống và sau đó một div trong menu của tôi sẽ được điền (đây là nơi tôi có văn bản động xuất hiện).

    scaleFontSize("my_container_div");

Ngoài ra, tôi cũng sử dụng các dấu chấm lửng CSS ("...") để cắt bớt văn bản thậm chí còn dài hơn , như vậy:

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

Vì vậy, cuối cùng:

  • Văn bản ngắn: ví dụ "ỨNG DỤNG"

    Kết xuất hoàn toàn, chữ lớn đẹp.

  • Văn bản dài: ví dụ: "ỨNG DỤNG & NGUY HIỂM"

    Được giảm tỷ lệ 70%, thông qua chức năng mở rộng quy mô JS ở trên.

  • Văn bản siêu dài: ví dụ: "ỨNG DỤNG & ORANGES & BANAN ..."

    Được giảm 70% VÀ bị cắt bớt bằng dấu chấm lửng "...", thông qua chức năng chia tỷ lệ JS ở trên cùng với quy tắc CSS.

Bạn cũng có thể khám phá việc chơi với khoảng cách chữ CSS để làm cho văn bản hẹp hơn trong khi vẫn giữ nguyên kích thước phông chữ.


đã bỏ phiếu khi người dùng đang yêu cầu một giải pháp CSS thuần túy
AnotherLongUsername 11/11/19

2

Như nhiều người đã đề cập trong các bình luận cho bài đăng của @ DMTinter, OP đã hỏi về số lượng ("số tiền") của các ký tự thay đổi. Ông cũng đã hỏi về CSS, nhưng như @Alexander chỉ ra, "không thể chỉ với CSS". Theo như tôi có thể nói, điều đó dường như là đúng vào thời điểm này, vì vậy cũng có vẻ hợp lý rằng mọi người sẽ muốn biết điều tốt nhất tiếp theo.

Tôi không đặc biệt tự hào về điều này, nhưng nó hoạt động. Có vẻ như một số lượng mã quá mức để thực hiện nó. Đây là cốt lõi:

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;
      }
    }
  }
}

Đây là một thùng rác: http://jsbin.com/pidavon/edit?html,css,js,console,output
Vui lòng đề xuất các cải tiến có thể có cho nó (tôi không thực sự quan tâm đến việc sử dụng canvas để đo văn bản ... dường như thích quá nhiều chi phí (?)).

Cảm ơn @Pete cho chức năng đo lường: https://stackoverflow.com/a/4032497/442665


2

Giải pháp này cũng có thể giúp:

$(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');
        }
    }); 
  });

Nó làm việc tốt cho tôi!


Làm thế nào điều này đưa từ-quấn vào tài khoản?
Leif Neland


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

sử dụng phương trình này.

Đối với bất kỳ thứ gì lớn hơn hoặc nhỏ hơn 1440 và 768, bạn có thể cung cấp cho nó một giá trị tĩnh hoặc áp dụng cách tiếp cận tương tự.

Hạn chế với giải pháp vw là bạn không thể đặt tỷ lệ tỷ lệ, giả sử 5vw ở độ phân giải màn hình 1440 có thể có kích thước phông chữ 60px, kích thước phông chữ ý tưởng của bạn, nhưng khi bạn thu nhỏ chiều rộng cửa sổ xuống 768, nó có thể kết thúc là 12px, không phải là tối thiểu bạn muốn. Với phương pháp này, bạn có thể đặt ranh giới trên và ranh giới dưới của mình và phông chữ sẽ tự điều chỉnh ở giữa.


-2

Tạo bảng tra cứu tính toán kích thước phông chữ dựa trên độ dài của chuỗi bên trong của bạn <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';
}

Điều chỉnh và điều chỉnh tất cả các tham số bằng thử nghiệm thực nghiệm.


Kiểm tra thực nghiệm cho các tham số về cơ bản là tìm kiếm nhị phân với độ phức tạp thời gian: O (log n).
Hãy để tôi nói về nó vào

Bạn thực sự quên gọi hàm này, cũng cần truy cập độ dài mảng với thuộc tính của nó.
lukk

@lukk: Cảm ơn đã phản hồi. Đã sửa nó ngay.
Hãy để tôi nói về nó vào
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.