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

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

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


当前回答

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

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

(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上面的插件,但增加了字体大小:

$.fn.textfill = function(options) {
        var defaults = { innerTag: 'span', padding: '10' };
        var Opts = jQuery.extend(defaults, options);

        return this.each(function() {
            var ourText = $(Opts.innerTag + ':visible:first', this);
            var fontSize = parseFloat(ourText.css('font-size'),10);
            var doNotTrepass = $(this).height()-2*Opts.padding ;
            var textHeight;

            do {
                ourText.css('font-size', fontSize);
                textHeight = ourText.height();
                fontSize = fontSize + 2;
            } while (textHeight < doNotTrepass );
        });
    };

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

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

编辑:此代码用于在HTML5视频的顶部显示注释。当视频调整大小时(当浏览器窗口调整大小时),它会动态地改变字体大小。注释被连接到视频(就像YouTube上的注释一样),这就是代码使用实例而不是直接使用DOM句柄的原因。

根据请求,我将抛出一些代码,我用来实现这一点。(HTML5视频上方的文本框。)代码是很久以前写的,坦率地说,我认为它相当混乱。因为这个问题已经被回答了,而且答案在很久以前就已经被接受了,所以我就不麻烦重写了。但是如果有人想把这个简化一点,欢迎你!

// Figure out the text size:
var text = val['text'];
var letters = text.length;
var findMultiplier = function(x) { // g(x)
    /* By analysing some functions with regression, the resulting function that
     gives the best font size with respect to the number of letters and the size
     of the note is:
     g(x) = 8.3 - 2.75x^0.15 [1 < x < 255]
     f(x) = g(letters) * (x / 1000)^0.5
     Font size = f(size)
     */
    return 8.3 - 2.75 * Math.pow(x, 0.15);
};

var findFontSize = function(x) { // f(x)
    return findMultiplier(letters) * Math.pow(x / 1000, 0.5);
};

val.setFontSizeListener = function() {
    p.style.fontSize = '1px'; // So the text should not overflow the box when measuring.
    var noteStyle = window.getComputedStyle(table);
    var width = noteStyle.getPropertyValue('width');
    var height = noteStyle.getPropertyValue('height');
    var size = width.substring(0, width.length - 2) * height.substring(0, height.length - 2);
    p.style.fontSize = findFontSize(size) + 'px';
};
window.addEventListener('resize', val.setFontSizeListener);

您可能需要将这些数字从font-family调整为font-family。一个很好的方法就是下载一个叫做GeoGebra的免费图形可视化工具。更改文本的长度和框的大小。然后手动设置大小。将手工结果绘制到坐标系统中。然后输入我在这里发布的两个方程,然后调整数字,直到“我的”图形符合你自己手动绘制的点。

大多数其他答案使用循环来减少字体大小,直到它适合div,这是非常缓慢的,因为页面需要重新渲染元素每次字体改变大小。我最终不得不编写自己的算法,使它能够定期更新内容,而不会冻结用户浏览器。我添加了一些其他功能(旋转文本,添加填充),并将其打包为jQuery插件,你可以在:

https://github.com/DanielHoffmann/jquery-bigtext

简单的电话

$("#text").bigText();

它会非常适合你的容器。

在这里看到它的行动:

http://danielhoffmann.github.io/jquery-bigtext/

现在它有一些限制,div必须有固定的高度和宽度,它不支持将文本包装成多行。

我将努力获得一个选项来设置最大字体大小。

编辑:我发现了更多的问题与插件,它不处理其他盒子模型除了标准的和div不能有边缘或边界。我会努力的。

Edit2:我现在已经修复了这些问题和限制,并添加了更多选项。你可以设置最大字体大小,你也可以选择限制字体大小使用宽度,高度或两者。我将在包装器元素中接受max-width和max-height值。

Edit3:我已经将插件更新到1.2.0版本。对代码和新选项(verticalAlign, horizontalAlign, textAlign)进行了重大清理,并支持span标签内的内部元素(如换行或字体很棒的图标)。

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

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

(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。