html5+div+字体缩放,调整字体大小以适合div(在一行上)

14 个答案:

答案 0 :(得分:45)

CSS no,Javascript yes

你无法用CSS做到这一点,但是你可以在javascript / jQuery中做到这一点。为了帮助您使用伪代码,因为您已经知道该怎么做。只是你不知道如何检测多余的宽度。

最好的方法是让DIV具有以下(至少)风格:

position: absolute;

visibility: hidden;

white-space: nowrap;

font-family: /* same as your title's */

然后将文本复制到它并设置一些起始字体大小。然后你可以迭代你的while循环并在div的宽度合适时停止。然后将计算出的字体大小设置为原始标题。

这样,这种检查将隐藏在用户眼中,因此也可以更快地完成。

BTW:这是自动增长textarea脚本的常用方法。他们使用与原始文本区域具有相同样式设置的虚拟div,并在用户键入文本时调整区域的高度。因此,文本区域最初可能非常小,但如果用户输入大量文本,它将自动增长以适应内容。

循环优化

您可以通过执行以下操作来优化while循环以显着减少迭代次数:

设置起始字体大小。

获得测试DIV的宽度。

计算orig_div和test_div之间的宽度系数。

按此因素调整字体大小,而不是按单位增加/减少

test test_div width

醇>

答案 1 :(得分:22)

我遇到了类似的问题,这让我为此编写了自己的插件。看一下jquery-quickfit(这与我真正喜欢的Robert Koritnik's解决方案非常相似)。

为了防止标题跨越多行,只需添加css样式:

white-space:nowrap;

到元素。

在标题中包含jquery和quickfit之后。您可以使用以下命令触发quickfit:

$('h1').quickfit();

它测量并计算文本的每个字母的大小不变量,以适合并使用它来计算下一个最适合文本的字体大小。

计算被缓存,这使得它在处理多个文本或多次适合文本时非常快,例如,在窗口调整大小时(调整大小几乎没有性能损失)。

项目页面上有更多文档,示例和源代码。

答案 2 :(得分:20)

以下是我经常使用的3个函数来获取文本宽度,高度并将大小调整为容器的宽度。

getTextWidth()会返回启动器中包含的文本的实际宽度。

getTextHeight(width)将返回包含在具有指定宽度的启动器中的包装文本的实际高度。

autoTextSize(minSize,maxSize,truncate)会根据最小和最大尺寸调整容器内的文本大小以使其适合。

autoTruncateText()只会显示用户实际可以看到的字符,并以“...”结束文字。

(function ($) {

$.fn.getTextWidth = function() {

var spanText = $("BODY #spanCalculateTextWidth");

if (spanText.size() <= 0) {

spanText = $("");

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 = $("");

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);

答案 3 :(得分:4)

@Clovis Six

谢谢你的回答。它对我来说非常有用。遗憾的是,我不能仅仅因为投票而感谢你。

注意:我必须更改“$ J(”for“$(”才能使用我的配置。

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:我知道这应该是评论,但评论不允许我正确发布代码。

答案 4 :(得分:4)

今天我创建了一个名为jQuery Responsive Headlines的jQuery插件,它可以完全满足您的需求:它调整标题的字体大小以适应其包含的元素(div,body或其他) 。您可以设置一些不错的选项来自定义插件的行为,我还采取了预防措施,添加对Ben Altmans Throttle / Debounce功能的支持,以便在用户调整大小时提高性能并减轻浏览器/计算机上的负载窗口。在它最简单的用例中,代码看起来像这样:

$('h1').responsiveHeadlines();

...这会将页面元素上的所有h1转换为响应式单行标题,将其大小调整为父/容器元素。

答案 5 :(得分:3)

很简单。为文本创建范围,获取宽度并减小字体大小,直到跨度具有与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);

}

答案 6 :(得分:1)

github上有一个jquery插件可能就是你想要的。它被称为jquery-quickfit。它使用Jquery提供一种快速而肮脏的方法来将文本拟合到其周围的容器中。

HTML:

Text to fit*

使用Javascript:

$(function() {

$('#quickfit').quickfit();

});

答案 7 :(得分:1)

我不喜欢那里的其他解决方案,所以,这是另一个。它需要您正在调整文本内容的标记:

固定高度

不要太久以至于它超过了10px的边界 - 这个想法是,你不希望它在那之下拍摄并调整文本大小变得难以理解。在我们的用例中不是问题,但是如果它可能在你的用例中你想要在运行之前给出一些单独截断的想法。

醇>

它使用二进制搜索来找到最佳大小,因此我怀疑它在这里和其他地方的表现优于其他许多解决方案,只是将字体大小逐步减去一个像素。今天大多数浏览器也支持字体大小的小数,这个脚本有一些好处,因为它会达到最佳答案的.1px内,无论是什么,即使它是一个相对较长的小数。您可以轻松地将max - fontSize < .1更改为除.1之外的其他值,以降低CPU使用率的精度。

用法:

$('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));

});

};

})();

答案 8 :(得分:1)

这可能对您的要求有些过分,但我发现这个库非常有用:

但这对单线只有好处,所以我不确定这是否符合您的要求。

答案 9 :(得分:0)

我做了一些非常小的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");

});

答案 10 :(得分:0)

在这里查看此示例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");

}

});

}

答案 11 :(得分:0)

$.fn.fitToWidth=function(){

$(this).wrapInner("").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();

});

答案 12 :(得分:0)

在某些情况下,您可以在css中完成此操作,但它很脆弱且与上下文有关。

css字体大小可以接受屏幕的相对大小。如果标题的包含元素的大小是相对于屏幕大小的大小,则可以通过简单地设置font-size: 3vw或适当的大小以使文本适合一行而实现此目的。如果调整了屏幕大小,则文本也会随之变化。请注意,宽度将取决于确切的文本内容,并且如果您将字符添加到以前适合一行的文本中,则可能需要调整字体大小。

答案 13 :(得分:0)

我知道这个问题似乎得到了相当彻底的回答,但在某些情况下,这里的解决方案可能会导致其他问题。例如,tkahn的库看起来非常有用,但它改变了附加元素的显示,这可能是一个问题。在我的情况下,它阻止我垂直和水平居中文本。经过一些麻烦和实验之后,我想出了一个简单的方法,包括jQuery,使文本在一行上拟合,而不需要修改父元素的任何属性。请注意,在此代码中,我使用了Robert Koritnik的建议来优化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 = '

' + x[i].innerHTML + '
';

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%);

}

希望这有助于某人!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值