我需要将用户输入的文本显示为固定大小的div。我想要的是自动调整字体大小,以使文本尽可能多地填充框中。
所以-如果div为400px x 300px。如果有人输入ABC,那么它确实是大字体。如果他们输入一个段落,那么它将是很小的字体。
我可能想从最大字体大小开始-也许是32px,并且当文本太大而无法容纳容器时,请缩小字体大小直到适合为止。
我需要将用户输入的文本显示为固定大小的div。我想要的是自动调整字体大小,以使文本尽可能多地填充框中。
所以-如果div为400px x 300px。如果有人输入ABC,那么它确实是大字体。如果他们输入一个段落,那么它将是很小的字体。
我可能想从最大字体大小开始-也许是32px,并且当文本太大而无法容纳容器时,请缩小字体大小直到适合为止。
这是我创建的最优雅的解决方案。它使用二进制搜索,进行10次迭代。天真的方法是执行while循环并将字体大小增加1,直到元素开始溢出。您可以使用element.offsetHeight和element.scrollHeight确定元素何时开始溢出。如果scrollHeight大于offsetHeight,则字体大小太大。
二进制搜索是一种更好的算法。它还受您要执行的迭代次数的限制。只需调用flexFont并插入div ID,它将在8px和96px之间调整字体大小。
我花了一些时间研究这个主题并尝试使用不同的库,但是最终我认为这是实际可行的最简单,最直接的解决方案。
请注意,如果需要,可以更改为使用offsetWidth
和scrollWidth
,或将两者都添加到此功能。
// Set the font size using overflow property and div height
function flexFont(divId) {
var content = document.getElementById(divId);
content.style.fontSize = determineMaxFontSize(content, 8, 96, 10, 0) + "px";
};
// Use binary search to determine font size
function determineMaxFontSize(content, min, max, iterations, lastSizeNotTooBig) {
if (iterations === 0) {
return lastSizeNotTooBig;
}
var obj = fontSizeTooBig(content, min, lastSizeNotTooBig);
// if `min` too big {....min.....max.....}
// search between (avg(min, lastSizeTooSmall)), min)
// if `min` too small, search between (avg(min,max), max)
// keep track of iterations, and the last font size that was not too big
if (obj.tooBig) {
(lastSizeTooSmall === -1) ?
determineMaxFontSize(content, min / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall) :
determineMaxFontSize(content, (min + lastSizeTooSmall) / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall);
} else {
determineMaxFontSize(content, (min + max) / 2, max, iterations - 1, obj.lastSizeNotTooBig, min);
}
}
// determine if fontSize is too big based on scrollHeight and offsetHeight,
// keep track of last value that did not overflow
function fontSizeTooBig(content, fontSize, lastSizeNotTooBig) {
content.style.fontSize = fontSize + "px";
var tooBig = content.scrollHeight > content.offsetHeight;
return {
tooBig: tooBig,
lastSizeNotTooBig: tooBig ? lastSizeNotTooBig : fontSize
};
}
这是此解决方案的另一个版本:
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";
}
}
我从Marcus Ekwall分叉了上面的脚本:https : //gist.github.com/3945316并根据我的喜好进行了调整,现在在调整窗口大小时会触发它,以便孩子始终适合其容器。我已将以下脚本粘贴以供参考。
(function($) {
$.fn.textfill = function(maxFontSize) {
maxFontSize = parseInt(maxFontSize, 10);
return this.each(function(){
var ourText = $("span", this);
function resizefont(){
var parent = ourText.parent(),
maxHeight = parent.height(),
maxWidth = parent.width(),
fontSize = parseInt(ourText.css("fontSize"), 10),
multiplier = maxWidth/ourText.width(),
newSize = (fontSize*(multiplier));
ourText.css("fontSize", maxFontSize > 0 && newSize > maxFontSize ? maxFontSize : newSize );
}
$(window).resize(function(){
resizefont();
});
resizefont();
});
};
})(jQuery);
由于性能不好,我发现以前的解决方案都不够用,所以我自己编写了使用简单数学而不是循环的解决方案。在所有浏览器中也应该正常工作。
根据此性能测试案例,它比此处找到的其他解决方案要快得多。
(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中。
其他大多数答案都使用循环来减小字体大小,直到适合div为止,这非常慢,因为每次字体更改大小时页面都需要重新渲染元素。最终,我不得不编写自己的算法,以使其能够以某种方式定期执行其内容,而不会冻结用户浏览器。我添加了一些其他功能(旋转文本,添加填充)并将其打包为jQuery插件,您可以在以下位置获得它:
https://github.com/DanielHoffmann/jquery-bigtext
只需致电
$("#text").bigText();
它将很好地适合您的容器。
在这里查看实际操作:
http://danielhoffmann.github.io/jquery-bigtext/
现在它有一些限制,div必须具有固定的高度和宽度,并且不支持将文本换成多行。
我将努力获得一个设置最大字体大小的选项。
编辑:我发现插件有更多问题,除了标准插件之外,它不能处理其他盒子模型,并且div不能有边距或边框。我会努力的。
Edit2:我现在解决了这些问题和限制,并添加了更多选项。您可以设置最大字体大小,也可以选择使用宽度,高度或同时使用这两者来限制字体大小。我将努力在wrapper元素中接受max-width和max-height值。
Edit3:我已经将插件更新为版本1.2.0。对代码进行了重大清理,并添加了新选项(verticalAlign,horizontalAlign,textAlign),并支持span标记内的内部元素(如换行符或超棒的字体图标)。
尽管我偶尔会为这个答案而投票(谢谢!),但实际上,这并不是解决此问题的最佳方法。请在此处查看其他一些奇妙的答案,尤其是那些发现解决方案而没有循环的答案。
尽管如此,为了参考,这是我的原始答案:
<html>
<head>
<style type="text/css">
#dynamicDiv
{
background: #CCCCCC;
width: 300px;
height: 100px;
font-size: 64px;
overflow: hidden;
}
</style>
<script type="text/javascript">
function shrink()
{
var textSpan = document.getElementById("dynamicSpan");
var textDiv = document.getElementById("dynamicDiv");
textSpan.style.fontSize = 64;
while(textSpan.offsetHeight > textDiv.offsetHeight)
{
textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
}
}
</script>
</head>
<body onload="shrink()">
<div id="dynamicDiv"><span id="dynamicSpan">DYNAMIC FONT</span></div>
</body>
</html>
这是带有类的版本:
<html>
<head>
<style type="text/css">
.dynamicDiv
{
background: #CCCCCC;
width: 300px;
height: 100px;
font-size: 64px;
overflow: hidden;
}
</style>
<script type="text/javascript">
function shrink()
{
var textDivs = document.getElementsByClassName("dynamicDiv");
var textDivsLength = textDivs.length;
// Loop through all of the dynamic divs on the page
for(var i=0; i<textDivsLength; i++) {
var textDiv = textDivs[i];
// Loop through all of the dynamic spans within the div
var textSpan = textDiv.getElementsByClassName("dynamicSpan")[0];
// Use the same looping logic as before
textSpan.style.fontSize = 64;
while(textSpan.offsetHeight > textDiv.offsetHeight)
{
textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
}
}
}
</script>
</head>
<body onload="shrink()">
<div class="dynamicDiv"><span class="dynamicSpan">DYNAMIC FONT</span></div>
<div class="dynamicDiv"><span class="dynamicSpan">ANOTHER DYNAMIC FONT</span></div>
<div class="dynamicDiv"><span class="dynamicSpan">AND YET ANOTHER DYNAMIC FONT</span></div>
</body>
</html>
我喜欢