изменить размер шрифта, чтобы поместиться в div (в одну строку) - PullRequest
60 голосов
/ 04 августа 2010

Были заданы похожие вопросы, но решения совпадают с тем, что я пытаюсь сделать.По сути, у меня есть статья с заголовком (<h1>).Я не хочу контролировать длину заголовка, но также не хочу, чтобы заголовок отображался в нескольких строках.Есть ли способ с помощью CSS или JQuery изменить размер текста в зависимости от ширины тега <div>?

Я знаю, что бы я сделал с псевдокодом, если бы я мог обнаружить перекрытие текста к краю<div>:

var fontize = $("#title").css("font-size");
var i = /*remove unit from integer*/
while( /*text overlaps div*/ ){
    $("#title").css("font-size", --i+"pt");
}

Если есть атрибут CSS, который я могу установить, он будет еще приятнее, но, кажется, я не могу его найти (переполнение не будет работать в этой ситуации).

Ответы [ 14 ]

45 голосов
/ 04 августа 2010

CSS нет, Javascript да

Нет способа сделать это с помощью CSS, но вы можете сделать это в javascript / jQuery. Чтобы помочь вам с вашим псевдокодом, потому что вы уже знаете, что делать. Просто вы не знаете, как определить избыточную ширину.

Лучше всего иметь DIV со следующим (как минимум) стилем:

position: absolute;
visibility: hidden;
white-space: nowrap;
font-family: /* same as your title's */

, затем скопируйте текст и установите начальный размер шрифта. Затем вы можете перебирать цикл while и останавливаться, когда ширина div подходит. Затем установите рассчитанный размер шрифта для исходного заголовка.

Таким образом, эта проверка будет скрыта от глаз пользователя и, следовательно, будет работать быстрее.

КСТАТИ : Это обычный способ работы скриптов textarea с автоматическим ростом. Они используют фиктивные div с теми же настройками стиля, что и исходная текстовая область, и регулируют высоту области по мере того, как пользователь вводит текст. Таким образом, область текста может быть довольно маленькой, но если пользователь вводит много текста, он автоматически увеличивается в соответствии с содержимым.

Во время оптимизации цикла

Вы можете оптимизировать цикл while, чтобы значительно сократить количество итераций, выполнив следующее:

  1. Установить начальный размер шрифта.
  2. получить тестовую ширину DIV.
  3. вычислить коэффициент ширины между orig_div и test_div.
  4. настроить размер шрифта на этот коэффициент, а не увеличивать / уменьшать на одну единицу
  5. test test_div width
22 голосов
/ 07 апреля 2012

У меня была похожая проблема, которая заставила меня написать свой собственный плагин для этого. Взгляните на jquery-quickfit (что очень похоже на решение Роберта Коритника, которое мне действительно нравится).

Чтобы заголовок не занимал несколько строк, просто добавьте стиль css:

white-space:nowrap;

к элементу.

После включения jquery и quickfit в шапку. Вы можете активировать QuickFit с помощью:

$('h1').quickfit();

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

Расчеты кэшируются, что делает его очень быстрым, когда приходится иметь дело с необходимостью подгонки нескольких текстов или подгонкой текста несколько раз, как, например, при изменении размера окна (при изменении размера практически нет потери производительности).

Демонстрация для ситуации, аналогичной вашей

Дополнительная документация, примеры и исходный код находятся на странице проекта.

20 голосов
/ 26 мая 2011

Вот 3 функции, которые я часто использую, чтобы получить ширину текста, высоту и настроить размер в соответствии с шириной контейнера.

  • getTextWidth () вернет вам фактическую ширину текста, содержащегося в инициаторе.
  • getTextHeight (width) вернет фактическую высоту обернутого текста, содержащегося в инициаторе, с определенной указанной шириной.
  • autoTextSize (minSize, maxSize, truncate) изменит размер текста в контейнере так, чтобы он уместился, учитывая минимальный и максимальный размер.
  • autoTruncateText () будет отображать только те символы, которые пользователь может видеть, и заканчивать текст знаком «...».
(function ($) {
  $.fn.getTextWidth = function() {
    var spanText = $("BODY #spanCalculateTextWidth");

    if (spanText.size() <= 0) {
      spanText = $("<span id='spanCalculateTextWidth' style='filter: alpha(0);'></span>");
      spanText.appendTo("BODY");
    }

    var valu = this.val();
    if (!valu) valu = this.text();

    spanText.text(valu);

    spanText.css({
      "fontSize": this.css('fontSize'),
      "fontWeight": this.css('fontWeight'),
      "fontFamily": this.css('fontFamily'),
      "position": "absolute",
      "top": 0,
      "opacity": 0,
      "left": -2000
    });

    return spanText.outerWidth() + parseInt(this.css('paddingLeft')) + 'px';
  };

  $.fn.getTextHeight = function(width) {
    var spanText = $("BODY #spanCalculateTextHeight");

    if (spanText.size() <= 0) {
      spanText = $("<span id='spanCalculateTextHeight'></span>");
      spanText.appendTo("BODY");
    }

    var valu = this.val();
    if (!valu) valu = this.text();

    spanText.text(valu);

    spanText.css({
      "fontSize": this.css('fontSize'),
      "fontWeight": this.css('fontWeight'),
      "fontFamily": this.css('fontFamily'),
      "top": 0,
      "left": -1 * parseInt(width) + 'px',
      "position": 'absolute',
      "display": "inline-block",
      "width": width
    });

    return spanText.innerHeight() + 'px';
  };

  /**
   * Adjust the font-size of the text so it fits the container.
   *
   * @param minSize     Minimum font size?
   * @param maxSize     Maximum font size?
   * @param truncate    Truncate text after sizing to make sure it fits?
   */
  $.fn.autoTextSize = function(minSize, maxSize, truncate) {
    var _self = this,
        _width = _self.innerWidth(),
        _textWidth = parseInt(_self.getTextWidth()),
        _fontSize = parseInt(_self.css('font-size'));

    while (_width < _textWidth || (maxSize && _fontSize > parseInt(maxSize))) {
      if (minSize && _fontSize <= parseInt(minSize)) break;

      _fontSize--;
      _self.css('font-size', _fontSize + 'px');

      _textWidth = parseInt(_self.getTextWidth());
    }

    if (truncate) _self.autoTruncateText();
  };

  /**
   * Function that truncates the text inside a container according to the
   * width and height of that container. In other words, makes it fit by chopping
   * off characters and adding '...'.
   */
  $.fn.autoTruncateText = function() {
    var _self = this,
        _width = _self.outerWidth(),
        _textHeight = parseInt(_self.getTextHeight(_width)),
        _text = _self.text();

    // As long as the height of the text is higher than that
    // of the container, we'll keep removing a character.
    while (_textHeight > _self.outerHeight()) {
      _text = _text.slice(0,-1);
      _self.text(_text);
      _textHeight = parseInt(_self.getTextHeight(_width));
      _truncated = true;
    }

    // When we actually truncated the text, we'll remove the last
    // 3 characters and replace it with '...'.
    if (!_truncated) return;
    _text = _text.slice(0, -3);

    // Make sure there is no dot or space right in front of '...'.
    var lastChar = _text[_text.length - 1];
    if (lastChar == ' ' || lastChar == '.') _text = _text.slice(0, -1);
    _self.text(_text + '...');
  };
})(jQuery);
4 голосов
/ 17 июля 2013

Сегодня я создал плагин jQuery под названием jQuery Responsive Headlines , который делает именно то, что вы хотите: он регулирует размер шрифта заголовка, чтобы он помещался внутри содержащего его элемента (div, body или что-то еще).Есть несколько хороших опций, которые вы можете настроить, чтобы настроить поведение плагина, и я также принял меры предосторожности, чтобы добавить поддержку функциональности Ben Altmans Throttle / Debounce, чтобы повысить производительность и облегчить загрузку браузера / компьютера, когда пользователь изменяет размерокно.В простейшем случае код будет выглядеть следующим образом:

$('h1').responsiveHeadlines();

..., который превратит все h1 на элементах страницы в отзывчивые заголовки в одну строку, которые подгоняют их размеры к элементу parent / container.

Вы найдете исходный код и более подробное описание плагина на этой странице GitHub .

Удачи!

4 голосов
/ 29 июня 2011

@ Кловис Шесть благодарю за ответ.Это очень полезно для меня.Жаль, что я не могу поблагодарить вас больше, чем просто за голосование.

Примечание: я должен изменить "$ J (" на "$ ("), чтобы он работал в моей конфигурации.

evendo, это выходит за рамки этого вопроса, а не использования SO, я расширил ваш код, чтобы он работал для многострочного бокса с max-height.

  /**
   * Adjust the font-size of the text so it fits the container
   *
   * support multi-line, based on css 'max-height'.
   * 
   * @param minSize     Minimum font size?
   * @param maxSize     Maximum font size?
   */
  $.fn.autoTextSize_UseMaxHeight = function(minSize, maxSize) {
    var _self = this,
        _width = _self.innerWidth(),
        _boxHeight = parseInt(_self.css('max-height')),
        _textHeight = parseInt(_self.getTextHeight(_width)),
        _fontSize = parseInt(_self.css('font-size'));

    while (_boxHeight < _textHeight || (maxSize && _fontSize > parseInt(maxSize))) {
      if (minSize && _fontSize <= parseInt(minSize)) break;

      _fontSize--;
      _self.css('font-size', _fontSize + 'px');

      _textHeight = parseInt(_self.getTextHeight(_width));
    }
  };

PS: я знаю этодолжен быть комментарием, но комментарии не позволяют правильно разместить код.

3 голосов
/ 11 декабря 2014

Очень просто.Создайте интервал для текста, получите ширину и уменьшайте размер шрифта, пока интервал не будет иметь такую ​​же ширину контейнера div:

while($("#container").find("span").width() > $("#container").width()) {
    var currentFontSize = parseInt($("#container").find("span").css("font-size")); 
    $("#container").find("span").css("font-size",currentFontSize-1); 
}
1 голос
/ 29 августа 2014

На github доступен плагин jquery, который, вероятно, просто делает то, что вы хотите.Это называется jquery-quickfit.Он использует Jquery для обеспечения быстрого и грязного подхода к размещению текста в окружающем контейнере.

HTML:

<div id="quickfit">Text to fit*</div>

Javascript:

<script src=".../jquery.min.js" type="text/javascript" />
<script src="../script/jquery.quickfit.js" type="text/javascript" />

<script type="text/javascript">
  $(function() {
    $('#quickfit').quickfit();
  });
</script>

Дополнительная информация: https://github.com/chunksnbits/jquery-quickfit

1 голос
/ 18 июля 2014

Я не был влюблен в другие решения, так что вот еще одно. Требуется тег, размер которого вы изменяете внутри:

  1. Фиксированная высота

  2. Не так долго, чтобы оно перешло границы в 10 пикселей - идея в том, что вы не хотите, чтобы он стрелял ниже этого и изменял размер текста, чтобы стать нечитаемым. Не проблема в нашем случае использования, но если это возможно в вашем случае, вы бы хотели подумать об отдельном усечении перед запуском этого.

Он использует бинарный поиск, чтобы найти лучший размер, поэтому я подозреваю, что он превосходит многие другие решения здесь и в других местах, которые просто уменьшают размер шрифта на пиксель снова и снова. В настоящее время большинство браузеров также поддерживают десятичные дроби в размерах шрифтов, и этот сценарий имеет некоторые преимущества, поскольку он будет в пределах .1px от лучшего ответа, каким бы он ни был, даже если это относительно длинный десятичный знак. Вы можете легко изменить max - fontSize < .1 на другое значение, отличное от .1, чтобы получить меньшую точность при меньшем использовании ЦП.

Использование:

$('div.event').fitText();

Код:

(function() {
    function resizeLoop(testTag, checkSize) {
        var fontSize = 10;
        var min = 10;
        var max = 0;
        var exceeded = false;

        for(var i = 0; i < 30; i++) {
            testTag.css('font-size', fontSize);
            if (checkSize(testTag)) {
                max = fontSize;
                fontSize = (fontSize + min) / 2;
            } else {
                if (max == 0) {
                    // Start by growing exponentially
                    min = fontSize;
                    fontSize *= 2;
                } else {
                    // If we're within .1px of max anyway, call it a day
                    if (max - fontSize < .1)
                        break;

                    // If we've seen a max, move half way to it
                    min = fontSize;
                    fontSize = (fontSize + max) / 2;
                }
            }
        }

        return fontSize;
    }

    function sizeText(tag) {
        var width = tag.width();
        var height = tag.height();

        // Clone original tag and append to the same place so we keep its original styles, especially font
        var testTag = tag.clone(true)
        .appendTo(tag.parent())
        .css({
            position: 'absolute',
            left: 0, top: 0,
            width: 'auto', height: 'auto'
        });

        var fontSize;

        // TODO: This decision of 10 characters is arbitrary. Come up
        // with a smarter decision basis.
        if (tag.text().length < 10) {
            fontSize = resizeLoop(testTag, function(t) {
                return t.width() > width || t.height() > height;
            });
        } else {
            testTag.css('width', width);
            fontSize = resizeLoop(testTag, function(t) {
                return t.height() > height;
            });
        }

        testTag.remove();
        tag.css('font-size', fontSize);
    };

    $.fn.fitText = function() {
        this.each(function(i, tag) {
            sizeText($(tag));
        });
    };
})();

http://jsfiddle.net/b9chris/et6N6/1/

1 голос
/ 12 января 2012

Это может быть излишним для того, что вам нужно, но я нашел эту библиотеку очень полезной:

http://fittextjs.com/

Это хорошо только для отдельных строк, поэтому я неуверен, если это соответствует вашим требованиям.

0 голосов
/ 05 мая 2019

Вы можете сделать это в css при определенных обстоятельствах, но это хрупко и зависит от контекста.

css размеры шрифта могут принимать относительные размеры кэкран.Если содержащий элемент для вашего заголовка имеет размер относительно размера экрана, вы можете сделать это, просто установив font-size: 3vw или соответствующий размер, чтобы текст помещался на одной строке.Если размер экрана будет изменен, текст будет следовать его примеру.Обратите внимание, что ширина будет зависеть от точного содержания текста, и если вы добавляете символы в текст, который раньше помещался на одной строке, вам может потребоваться настроить размер шрифта.

См. Эту скрипку: https://jsfiddle.net/mguk8v27/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...