我需要显示用户输入的文本到一个固定大小的div。我想要的是字体大小自动调整,以便文本尽可能多地填充框。

如果div是400px x 300px。如果有人输入ABC,那么字体就很大。如果他们输入一个段落,那么它将是一个很小的字体。

我可能想要从最大字体大小开始——可能是32px,当文本太大而不适合容器时,缩小字体大小直到它适合。


当前回答

只是想增加我的内容表版本。

$.fn.fitInText = function() { this.each(function() { let textbox = $(this); let textboxNode = this; let mutationCallback = function(mutationsList, observer) { if (observer) { observer.disconnect(); } textbox.css('font-size', 0); let desiredHeight = textbox.css('height'); for (i = 12; i < 50; i++) { textbox.css('font-size', i); if (textbox.css('height') > desiredHeight) { textbox.css('font-size', i - 1); break; } } var config = { attributes: true, childList: true, subtree: true, characterData: true }; let newobserver = new MutationObserver(mutationCallback); newobserver.observe(textboxNode, config); }; mutationCallback(); }); } $('#inner').fitInText(); #outer { display: table; width: 100%; } #inner { border: 1px solid black; height: 170px; text-align: center; display: table-cell; vertical-align: middle; word-break: break-all; } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="outer"> <div id="inner" contenteditable=true> TEST </div> </div>

其他回答

这是我对OP的答案的修改。

简而言之,许多尝试优化此功能的人抱怨使用了循环。是的,虽然循环可能很慢,但其他方法可能不准确。

因此,我的方法是使用二进制搜索来找到最好的字体大小:

$.fn.textfill = function()
{
    var self = $(this);
    var parent = self.parent();

    var attr = self.attr('max-font-size');
    var maxFontSize = parseInt(attr, 10);
    var unit = attr.replace(maxFontSize, "");

    var minFontSize = parseInt(self.attr('min-font-size').replace(unit, ""));
    var fontSize = (maxFontSize + minFontSize) / 2;

    var maxHeight = parent.height();
    var maxWidth = parent.width();

    var textHeight;
    var textWidth;

    do
    {
        self.css('font-size', fontSize + unit);

        textHeight = self.height();
        textWidth = self.width();

        if(textHeight > maxHeight || textWidth > maxWidth)
        {
            maxFontSize = fontSize;
            fontSize = Math.floor((fontSize + minFontSize) / 2);
        }
        else if(textHeight < maxHeight || textWidth < maxWidth)
        {
            minFontSize = fontSize;
            fontSize = Math.floor((fontSize + maxFontSize) / 2);
        }
        else
            break;

    }
    while(maxFontSize - minFontSize > 1 && maxFontSize > minFontSize);

    self.css('font-size', fontSize + unit);

    return this;
}

function resizeText()
{
  $(".textfill").textfill();
}

$(document).ready(resizeText);
$(window).resize(resizeText);

这也允许元素指定最小和最大字体:

<div class="container">
    <div class="textfill" min-font-size="10px" max-font-size="72px">
        Text that will fill the container, to the best of its abilities, and it will <i>never</i> have overflow.
    </div>
</div>

此外,该算法是无单位的。你可以指定em, rem, %等,它将使用它的最终结果。

这是小提琴:https://jsfiddle.net/fkhqhnqe/1/

我没有发现任何以前的解决方案是足够的,由于糟糕的性能,所以我自己使用简单的数学,而不是循环。在所有浏览器中都可以正常工作。

根据这个性能测试用例,它比这里找到的其他解决方案快得多。

(function($) {
    $.fn.textfill = function(maxFontSize) {
        maxFontSize = parseInt(maxFontSize, 10);
        return this.each(function(){
            var ourText = $("span", this),
                parent = ourText.parent(),
                maxHeight = parent.height(),
                maxWidth = parent.width(),
                fontSize = parseInt(ourText.css("fontSize"), 10),
                multiplier = maxWidth/ourText.width(),
                newSize = (fontSize*(multiplier-0.1));
            ourText.css(
                "fontSize", 
                (maxFontSize > 0 && newSize > maxFontSize) ? 
                    maxFontSize : 
                    newSize
            );
        });
    };
})(jQuery);

如果你想投稿,我已经把这个添加到Gist。

我用geekMonkey解决方案,但它太慢了。他所做的就是将字体大小调整到最大(maxFontPixels),然后检查它是否适合容器。否则,它将字体大小减小1px,并再次检查。为什么不简单地检查前一个容器的高度并提交该值呢?(是的,我知道为什么,但我现在做了一个解决方案,这只适用于高度,也有一个最小/最大选项)

这里有一个更快的解决方案:

var index_letters_resize;
(index_letters_resize = function() {
  $(".textfill").each(function() {
    var
      $this = $(this),
      height = Math.min( Math.max( parseInt( $this.height() ), 40 ), 150 );
    $this.find(".size-adjust").css({
      fontSize: height
    });
  });
}).call();

$(window).on('resize', function() {
  index_letters_resize();
);

这就是HTML:

<div class="textfill">
  <span class="size-adjust">adjusted element</span>
  other variable stuff that defines the container size
</div>

同样,这个解决方案只检查容器的高度。这就是为什么这个函数不需要检查元素是否在里面。但我也实现了一个最小/最大值(40min, 150max),所以对我来说,这是完美的(也适用于窗口大小调整)。

下面是这个解决方案的另一个版本:

shrinkTextInElement : function(el, minFontSizePx) {
    if(!minFontSizePx) {
        minFontSizePx = 5;
    }
    while(el.offsetWidth > el.parentNode.offsetWidth || el.offsetHeight > el.parentNode.offsetHeight) {

        var newFontSize = (parseInt(el.style.fontSize, 10) - 3);
        if(newFontSize <= minFontSizePx) {
            break;
        }

        el.style.fontSize = newFontSize + "px";
    }
}

这是我最后得到的结果:

这是该插件的链接:https://plugins.jquery.com/textfill/ 还有一个来源的链接:http://jquery-textfill.github.io/

;(function($) {
    $.fn.textfill = function(options) {
        var fontSize = options.maxFontPixels;
        var ourText = $('span:visible:first', this);
        var maxHeight = $(this).height();
        var maxWidth = $(this).width();
        var textHeight;
        var textWidth;
        do {
            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();
            fontSize = fontSize - 1;
        } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
        return this;
    }
})(jQuery);

$(document).ready(function() {
    $('.jtextfill').textfill({ maxFontPixels: 36 });
});

我的HTML是这样的

<div class='jtextfill' style='width:100px;height:50px;'>
    <span>My Text Here</span>
</div>