JavaScript缩放文本以适应固定Div

在JavaScript / jQuery中,如何在一个固定宽度的div内缩放一段变长的文本,这样一行总是可以放入div中(如同一行)?

谢谢。

这有些黑客,但会做你想做的。

<div id="hidden-resizer" style="visibility: hidden"></div> 

将其放置在页面的底部,它不会移动页面上的其他元素。

然后这样做:

 var size; var desired_width = 50; var resizer = $("#hidden-resizer"); resizer.html("This is the text I want to resize."); while(resizer.width() > desired_width) { size = parseInt(resizer.css("font-size"), 10); resizer.css("font-size", size - 1); } $("#target-location").css("font-size", size).html(resizer.html()); 

HTML:

 <div class="box" style="width:700px">This is a sentence</div> <div class="box" style="width:600px">This is a sentence</div> <div class="box" style="width:500px">This is a sentence</div> <div class="box" style="width:400px">This is a sentence</div> 

JavaScript的:

 $( '.box' ).each(function ( i, box ) { var width = $( box ).width(), html = '<span style="white-space:nowrap"></span>', line = $( box ).wrapInner( html ).children()[ 0 ], n = 100; $( box ).css( 'font-size', n ); while ( $( line ).width() > width ) { $( box ).css( 'font-size', --n ); } $( box ).text( $( line ).text() ); }); 

现场演示: http : //jsfiddle.net/e8B9j/2/show/

从URL中删除“/ show /”以查看代码。

我写了一个jQuery插件来做到这一点:

http://michikono.github.com/boxfit

该插件将文本水平和垂直缩放到框内的最大可用大小,然后居中。

你唯一需要做的就是在里面定义一个带有文本的div:

 <div id="scale">some text</div> 

然后打电话给:

 $('#scale').boxfit() 

该方法将接受一些参数来禁用/启用文字换行和居中alignment。

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

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

只需打电话

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

它将很好地适合你的容器。

在这里看到它的行动:

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

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

编辑2:我现在已经修复了这些问题和限制,并增加了更多的选项。 您可以设置最大的字体大小,也可以select使用宽度,高度或两者都限制字体大小(默认值都是)。 我将接受包装器元素中的最大宽度和最大高度值。

对于新的浏览器,您可以使用Inline-SVG。 这可以像通过CSS的图像缩放..! ( width: 100%;

我不知道一个确切的方法,但这里是一个近似值:

 var factor = 1/3; // approximate width-to-height ratio var div = $('#mydiv'); div.css('font-size', div.width() / (div.text().length * factor) + 'px'); 

您将需要根据您使用的字体来调整factor 。 三分之一似乎为时代新罗马工作。

在你的div里面,有一个没有填充的文本。 那么跨度的宽度将是文本的长度。
未经testing的代码find正确的字体大小使用:

 var objSpan = $('.spanThatHoldsText'); var intDivWidth = $('.divThatHasAFixedWidth').width(); var intResultSize; for (var intFontSize = 1; intFontSize < 100; intFontSize++) objSpan.css('font-size', intFontSize); if (objSpan.width() > intDivWidth) { intResultSize = intFontSize - 1; break; } } objSpan.css('font-size', intResultSize); 

这是我想出的咖啡标记解决scheme。 我克隆需要调整字体大小的元素,然后在计算结束时删除它。 为了提高性能,我有一些代码,只有在resize停止200ms后才执行计算。

用class autofont标记元素,这样做是不显眼的。

 # # Automagically resize fonts to fit the width of the # container they are in as much as possible. # fixfonts = -> scaler = 1.2 for element in $('.autofont') size = 1 element = $(element) desired_width = $(element).width() resizer = $(element.clone()) resizer.css 'font-size': "#{size}em" 'max-width': desired_width 'display': 'inline' 'width': 'auto' resizer.insertAfter(element) while resizer.width() < desired_width size = size * scaler resizer.css 'font-size': "#{size}em" $(element).css 'font-size': "#{size / scaler }em" resizer.remove() $(document).ready => fixfonts() timeout = 0 doresize = -> timeout-- if timeout == 0 fixfonts() $(window).resize -> timeout++ window.setTimeout doresize, 200 

支持目标类的@sworoc的修改版本

 function resizeText(text, size, target) { var fontSize = 0; var resizer = $('<span>'); resizer.html(text).hide(); resizer.attr('class', target.attr('class')); $('body').append(resizer); while(resizer.width() < size) { fontSize++ resizer.css("font-size", fontSize); } target.css('font-size', fontSize).html(text); resizer.remove(); } 

用法

 resizeText("@arunoda", 350, $('#username')); 

我无法弄清楚如何将这个添加到sworoc的post,但我想我会分享无论如何:如果您使用任何types的AJAX导航,Lonesomeday的解决scheme会搞砸。 我稍微修改它为:

 if ($('#hidden-resizer').length == 0){ $('<div />', {id: 'hidden-resizer'}).hide().appendTo(document.body); } 

我有一个类似的问题,这使我为此写了自己的插件。 如上所述,一个解决scheme是使用缩小到适合的方法。 但是,如果你必须适应多个项目或关注性能,例如,在窗口resize,看看jquery-quickfit 。

它为文本的每个字母测量和计算尺寸不变的尺寸,并使用它来计算适合文本到容器中的下一个最佳字体尺寸。

计算caching,这使得处理多个文本或不得不适应文本多次,如窗口resize时,速度非常快(从第二次resize的前锋几乎没有性能影响)。

生产实例,拟合14x16x2文本

这是我对@ teambob的build议(在上面的评论中 )的修改,也考虑到了容器的高度:

 <div class="box" style="width:700px; height:200px">This is a sentence</div> <div class="box" style="width:600px; height:100px">This is a sentence</div> <div class="box" style="width:500px; height:50px">This is a sentence</div> <div class="box" style="width:400px; height:20px">This is a sentence</div> 

接着..

 $('.box').each(function(i, box) { var width = $(box).width(), height = $(box).height(), html = '<span style="white-space:nowrap">', line = $(box).wrapInner(html).children()[0], maxSizePX = 2000; $(box).css('font-size', maxSizePX); var widthFontSize = Math.floor(width/$(line).width()*maxSizePX), heightFontSize = Math.floor(height/$(line).height()*maxSizePX), maximalFontSize = Math.min(widthFontSize, heightFontSize, maxSizePX); $(box).css('font-size', maximalFontSize); $(box).text($(line).text()); }); 

看小提琴

检查这个例子! 它使用jquery,工作正常。

编辑: 更好的一个http://plugins.jquery.com/project/TextFill

https://github.com/jquery-textfill/jquery-textfill

我不确定是否有任何准确的方法来测量文本的像素宽度(这是你真正要找的问题的根源),因为每个浏览器可能会显示不同的字体。 你可能想尝试使用这个CSS代码,除了根据句子中的字母数量来做一些“模糊”resize。 您可以尝试使用固定宽度的字体(或样式)来显示文本,以便每个字符占用相同的空间量。 这样,你可以做出最好的猜测,如果需要的话,在裁剪文本之前,CSS至less会给你一个不错的“…”。

 .truncate { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } 

你可以做很多事情

 overflow:hidden 

这削减了额外的线路

overflow:auto //这显示滚动条

看到这个

http://www.w3schools.com/Css/pr_pos_overflow.asp

试着做这个//检查文本的长度

 if($('#idfortext').length>sometthing) { var fontsize=10; } $('#yourid').css('font-size',fontsize) 

我在这里做了几个post,并制作了一个jQuery插件。 我发现从底部开始往上走并不是很高效,所以我假定当前的字体大小是接近的,并从那里开始工作。

  $.fn.fitTextToWidth = function(desiredWidth) { // In this method, we want to start at the current width and grow from there, assuming that we are close to the desired size already. var $el = $(this); var resizer = $('<'+$el.get(0).tagName+' />').css({'vsibility':'hidden','position':'absolute','left':'-9999px','display':'inline'}).html($el.html()); resizer.appendTo(document.body); var size = parseInt($el.css('font-size')); resizer.css('font-size',size+'px'); var growing = desiredWidth > resizer.width() ? true : false; var adder = growing ? 1 : -1; do { size += adder; resizer.css('font-size',size+'px'); } while(((growing && resizer.width()<desiredWidth) || (!growing && resizer.width()>desiredWidth)) && size>10 && size<100); if (growing) size -= 2; //we never want to go over resizer.remove(); $el.css('font-size',size+'px'); } // Example use: $('#main h1').fitTextToWidth(350); 

唯一的问题是,它假定元素的CSS是全局的,只适用于元素types。 换句话说,它会创build一个同名的标签,并假定它将具有与我们想要更改的元素相同的CSS属性。 如果这不适用于你,只要修改resizer被创build的那一行。

插件来适应容器的宽度和高度

http://blissitec.github.io/scaletextjs/

这里是我的解决scheme:我测量在提供的分区内的一个新的div的文本,所以样式应该inheritance。 然后我插入文本到一个跨度的div来设置字体大小。 它会超出默认的字体大小,但会缩小以适应。

它不会循环:它只在直接绘制到提供的div之前在一个丢弃的div中绘制一次文本。 看@霍夫曼答案 – 我只是不喜欢一个完整的“插件”来回答这个问题。

需要jQuery的。

 var txt = txt || {} txt.pad_factor = 1.1; txt.insertText_shrinkToFit = function(div,text) { var d = txt.cache || $('<div></div>'); txt.cache = d; d.css('white-space','nowrap'); d.css('position','absolute'); d.css('top','-10000px'); d.css('font-size','1000px'); var p = $(div); var max_w = parseInt(p.css('max-width')) || p.width(); var max_h = parseInt(p.css('font-size')); p.append(d); d.html(text); var w = d.width() * txt.pad_factor; d.remove(); var h = Math.floor(max_w*1000/w); var s = ( max_h < h ? max_h : h ) + "px"; p.html('<SPAN style="font-size:' + s + '">' + text + '</SPAN>'); } 

例如:

 <html><head><script src=http://code.jquery.com/jquery-latest.min.js></script> <script>/*insert code, from above, here.*/</script></head><body> <div id=mysmalldiv style="max-width:300px;font-size:50px"></div> <script> txt.insertText_shrinkToFit("#mysmalldiv","My super long text for this div."); </script> </body></html> 

对于testing:这是我如何发现,我需要1.1 pad_factor; 你可以调整到你的需求。

 <div id=mytestdiv style="max-width:300px;font-size:50px"></div> <script> var t = "my text "; var i = 0; var f = function() { t += i + " "; txt.insertText_shrinkToFit("#mytestdiv",t); i++; if(i < 100) setTimeout(f,1000); } f(); </script> 

注意:这是假设PX字体大小。 我没有testing与EM或PT。

有一种很好的方法可以在纯CSS中为单行文本(如标题等)执行此操作:

 h1{ font-size: 4.5vw; margin: 0 0 0 0; line-height: 1em; height: 1em; } h1:after{ content:""; display: inline-block; width: 100%; } 

确保你的字体大小足够保持头1行。 使用'vw'(视口宽度)而不是'px'可以很容易地做到这一点,并且可以同时进行缩放。 当你的浏览器窗口很大时,浏览器的宽度会变得很糟糕,许多网站使用它来在真正的宽屏幕上使网站保持一定的宽度:

 body{ max-width: 820px; margin: 0 auto; } 

为了确保你的字体不是基于视口窗口的大小,一旦网站的其他部分停止缩放,使用这个:

 @media(min-width:820px){ h1{ font-size: 30px; } } 

这是我今天发现的:

  1. 设置一个非常大的假字体大小(f)到目标文本
  2. 测量文本容器的宽度(w)高度(h)并除以字体大小(f):

    • iw = w/f
    • ih = h/f
  3. 用iw除以主容器宽度(W)和用主容器高度(H)除以ih:

    • kw = W/iw
    • kh = H/ih
  4. 在kw和kh之间select最低:这是所需的FontSize。

https://jsfiddle.net/pinkynrg/44ua56dv/

 function maximizeFontSize($target) { var testingFont = 1000; $target.find(".text-wrapper").css("font-size", testingFont+"px"); var textWidth = $(".text-wrapper").width()/1000; var textHeight = $(".text-wrapper").height()/1000; var width = $(".container").width(); var height = $(".container").height(); var kWidth = width/textWidth; var kHeight = height/textHeight; var fontSize = kWidth < kHeight ? kWidth : kHeight; // finally $(".text-wrapper") .css("font-size", fontSize+"px") .css("line-height", height+"px"); } 

这是不可能的。 我已经考虑了很多,并进行了研究。 问题是有这么多的变数。 看看safari / firefox / IE上的同一个网站。 看看字体大小看起来有些不同吗? 现在去看看它在Linux / Mac / iPhone ……..

如果您确实find解决scheme,请在此处发布!

解决scheme发现我看….这太棒了!