Чистый CSS для изменения размера шрифта на основе динамического количества символов

Я знаю, что это можно довольно легко решить с помощью Javascript, но меня интересует только чистое решение CSS.

Мне нужен способ динамического изменения размера текста, чтобы он всегда вписывался в фиксированный div. Вот пример разметки:

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

Ответ 1

Я только выяснил, что это возможно с помощью VW-блоков. Это единицы, связанные с настройкой ширины окна просмотра. Есть некоторые недостатки, такие как отсутствие поддержки браузеров старых версий, но это определенно нужно серьезно рассмотреть. Кроме того, вы все равно можете предоставить резервные копии для старых браузеров, например:

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

http://css-tricks.com/viewport-sized-typography/ а также https://medium.com/design-ux/66bddb327bb1

Ответ 2

CSS3 поддерживает новые измерения, относящиеся к виду порта. Но это не работает в android < 4.4

  • 3.2vw = 3.2% ширины окна просмотра
  • 3.2vh = 3.2% высоты окна просмотра
  • 3.2vmin = Меньше 3.2vw или 3.2vh
  • 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;
}

Используйте размеры в % или em. Просто измените размер базового шрифта, все изменится. В предыдущем случае вы могли просто менять шрифт тела, а не h1, каждый раз, или допускать размер базового шрифта по умолчанию устройства и оставлять все в em

см. kyleschaeffer.com/.... для получения дополнительной информации о em, px и%

Ответ 3

Вас может заинтересовать подход calc:

font-size: calc(4vw + 4vh + 2vmin);

сделано. Значение Tweak соответствует вашему вкусу.

Источник: https://codepen.io/CrocoDillon/pen/fBJxu

Ответ 4

Единственный способ, вероятно, состоит в том, чтобы устанавливать разные ширины для разных размеров экрана, но этот подход довольно неуверен, и вы должны использовать 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;
    }
}

Ответ 5

Я знаю, что у меня возник вопрос с длинными мертвыми, но у меня был тот же вопрос, и я хотел что-то добавить. Пожалуйста, не запрещайте мне это, я чувствовал, что это достаточно важно, чтобы оправдать этот ответ, я удалю, если потребуется. @Joseph Silber ошибается, кодирование всех возможностей на самом деле является жизнеспособным способом сделать это. Причина в том, что на самом деле нет бесконечных возможностей. Ну, технически есть, но 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, ваш сайт не должен ломаться. Это приводит к учету экзотических разрешений, пытаясь создать неприемливое правило ненужным, и идея, что вам нужно кодировать для каждого возможного пикселя настройки по пикселям, является смешной, если кто-то, использующий веб-браузер, не устарел, что ваш сайт, вероятно, не загрузится на все равно.

Ответ 6

Для справки, здесь решение JS, которое изменяет размер шрифта в зависимости от длины текста в контейнере.

Codepen со слегка измененным кодом, но та же идея, что и ниже:

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

    // We only want to scale down long text, so first we reset
    // font-size to 100%, in case this function is called multiple times.
    container.style.fontSize = "100%";

    // Now actually 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 ("...") для усечения еще более длинного текста, например так:

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

Итак, в конечном итоге:

  • Краткий текст: например, "ЯБЛОКИ"

    Полностью визуализированные, красивые большие буквы.

  • Длинный текст: например, "ЯБЛОКИ И ОРАНЖЕВЫЕ"

    Уменьшается на 70% с помощью вышеуказанной функции масштабирования JS.

  • Супер длинный текст: например, "ЯБЛОКИ И ОРАНЖЕВЫЕ И БАНАН..."

    Уменьшается на 70% И усекается с помощью "..." эллипсов, через вышеупомянутую функцию масштабирования JS вместе с правилом CSS.

Вы также можете изучить игру с использованием CSS-межбуквенного интервала, чтобы уменьшить текст при сохранении того же размера шрифта.

Ответ 7

Как упоминалось в комментариях к сообщению @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: fooobar.com/questions/16025/...

Ответ 8

Это решение также может помочь:

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

Это сработало для меня хорошо!

Ответ 10

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

используйте это уравнение.

Для чего-либо большего или меньшего, чем 1440 и 768, вы можете либо присвоить ему статическое значение, либо применить тот же подход.

Недостаток решения vw заключается в том, что вы не можете установить масштабное соотношение, скажем, 5vw при разрешении экрана 1440 может в конечном итоге иметь размер шрифта 60 пикселей, ваш размер шрифта, но при уменьшении ширины окна до 768 он может закончиться будучи 12px, а не минимальный вы хотите. При таком подходе вы можете установить верхнюю и нижнюю границу, а шрифт будет масштабироваться между ними.

Ответ 11

Создайте таблицу поиска, которая вычисляет размер шрифта на основе длины строки внутри вашего <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';
}

Отрегулируйте и настройте все параметры с помощью эмпирического теста.