Подтвердить что ты не робот

Изменить размер шрифта, чтобы он поместился в div (в одной строке)

Были заданы аналогичные вопросы, но решения действительно связаны с тем, что я пытаюсь сделать. В принципе, у меня есть статья с названием (<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, который я могу установить, это будет еще лучше, но я не могу найти его (переполнение не будет работать в этой ситуации).

4b9b3361

Ответ 1

CSS нет, Javascript да

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

Лучшим способом было бы иметь DIV со следующим (по крайней мере) стилем:

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

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

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

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

Пока оптимизация цикла

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

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

Ответ 2

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

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

white-space:nowrap;

к элементу.

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

$('h1').quickfit();

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

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

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

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

Ответ 3

Вот 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

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

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

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

  /**
   * 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: Я знаю, что это должен быть комментарий, но комментарии не позволяют мне правильно отправлять код.

Ответ 5

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

$('h1').responsiveHeadlines();

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

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

Удачи!

Ответ 6

Очень просто. Создайте диапазон для текста, получите ширину и уменьшите размер шрифта, пока диапазон не будет иметь одинаковую ширину контейнера 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); 
}

Ответ 7

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

http://fittextjs.com/

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

Ответ 8

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

  • Усиленная высота

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

Он использует бинарный поиск, чтобы найти лучший размер, поэтому я подозреваю, что он превосходит многие другие решения здесь и в других местах, которые просто изменяют размер шрифта на пиксель снова и снова. Большинство браузеров сегодня также поддерживают десятичные значения в размерах шрифтов, и этот script имеет некоторые преимущества там, так как он получит в пределах .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/

Ответ 9

В 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

Ответ 10

Мое решение, как расширение jQuery на основе Ответ Роберта Коритника:

$.fn.fitToWidth=function(){
    $(this).wrapInner("<span style='display:inline;font:inherit;white-space:inherit;'></span>").each(function(){
        var $t=$(this);
        var a=$t.outerWidth(),
            $s=$t.children("span"),
            f=parseFloat($t.css("font-size"));
        while($t.children("span").outerWidth() > a) $t.css("font-size",--f);
        $t.html($s.html());
    });
}

Это фактически создает временный диапазон, наследующий важные свойства, и сравнивает разницу в ширине. Конечно, цикл while должен быть оптимизирован (уменьшите на процентную разницу, рассчитанную между двумя размерами).

Пример использования:

$(function(){
    $("h1").fitToWidth();
});

Ответ 11

Я делаю очень мало jQuery, чтобы настроить размер шрифта вашего div. Он даже работает с несколькими строками, но только увеличит размер шрифта (вы можете просто установить размер шрифта по умолчанию 1px, если хотите). Я увеличиваю размер шрифта до тех пор, пока не будет разрыв строки, и уменьшит его на 1px. Никаких других причудливых вещей, скрытых div или около того. Просто добавьте класс quickfit в свой div.

$(".quickfit").each(function() {
    var jThis=$(this);
    var fontSize=parseInt(jThis.css("font-size"));
    var originalLines=jThis.height()/fontSize;

    for(var i=0;originalLines>=jThis.height()/fontSize && i<30;i++)
    { jThis.css("font-size",""+(++fontSize)+"px"); }
    jThis.css("font-size",""+(fontSize-1)+"px");
});

Ответ 12

Я понимаю, что на этот вопрос, по-видимому, ответили довольно тщательно, но были случаи, когда решения здесь могли бы вызвать другие проблемы. Например, библиотека tkahn выглядела очень полезной, но она изменила отображение элемента, к которому она привязана, что может оказаться проблемой. В моем случае это мешало мне центрировать текст как по вертикали, так и по горизонтали. После некоторого вовлечения и экспериментирования я придумал простой метод, включающий jQuery, чтобы он соответствовал тексту на одной строке, без необходимости изменять любые атрибуты родительского элемента. Обратите внимание, что в этом коде я использовал предложение Роберта Коритника для оптимизации цикла while. Чтобы использовать этот код, просто добавьте класс "font_fix" в любые div, содержащие текст, который должен соответствовать ему в одной строке. Для заголовка для этого может потребоваться дополнительный div вокруг заголовка. Затем либо вызовите эту функцию один раз для фиксированного размера div, либо установите его для прослушивателя изменения размера и/или ориентации для разных размеров.

function fixFontSize(minimumSize){
  var x = document.getElementsByClassName("font_fix");
  for(var i = 0; i < x.length; i++){
    x[i].innerHTML = '<div class="font_fix_inner" style="white-space: nowrap; display: inline-block;">' + x[i].innerHTML + '</div>';

    var y = x[i].getElementsByClassName("font_fix_inner")[0];
    var size = parseInt($("#" + x[i].id).css("font-size"));

    size *= x[i].clientWidth / y.clientWidth;
    while(y.clientWidth > x[i].clientWidth){
      size--;
      if(size <= minimumSize){
        size = minimumSize;
        y.style.maxWidth = "100%";
        y.style.overflow = "hidden";
        y.style.textOverflow = "ellipsis";
        $("#" + x[i].id).css("font-size", size + "px");
        break;
      }
      $("#" + x[i].id).css("font-size", size + "px");
    }
  }
}

Теперь я добавил дополнительный случай, когда текст отрубается, если он становится слишком маленьким (ниже минимального порога, переданного функции) для удобства. Другое дело, что происходит, когда достигнут порог, который может или не может быть желательным, - это изменение максимальной ширины до 100%. Это должно быть изменено для каждого сценария пользователя. Наконец, вся цель публикации этого ответа в качестве альтернативы заключается в его способности центрировать контент в родительском div. Это легко сделать, добавив атрибуты css во внутренний класс div следующим образом:

.font_fix_inner {
  position: relative;
  float: center;
  top: 50%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}

Надеюсь, это помогло кому-то!

Ответ 13

Посмотрите здесь этот пример http://codepen.io/LukeXF/pen/yOQWNb, вы можете использовать простую функцию при загрузке страницы и изменении страницы, чтобы сделать волшебство. Хотя будьте осторожны, чтобы не отказать клиенту от слишком многих вызовов функций. (Пример имеет задержку).

function resize() {  
    $('.resize').each(function(i, obj) {
        $(this).css('font-size', '8em');

        while ($(this).width() > $(this).parent().width()) {
            $(this).css('font-size', (parseInt($(this).css('font-size')) - 1) + "px");
        }
    });
}

Ответ 14

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

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

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