JavaScript缩放文本以适应固定Div

时间:2010-11-12 14:54:15

标签: javascript jquery html text

在JavaScript / jQuery中,如何在固定宽度Div内缩放不等长度的文本行,以便一行总是适合Div(作为一行)?

感谢。

23 个答案:

答案 0 :(得分:69)

这有点像黑客,但会做你想做的事。

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

答案 1 :(得分:29)

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/

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

答案 2 :(得分:13)

我已经编写了一个jQuery插件来执行此操作:

http://michikono.github.com/boxfit

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

您唯一需要做的就是在其中定义一个带有文本的div:

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

然后致电:

$('#scale').boxfit()

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

答案 3 :(得分:7)

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

答案 4 :(得分:5)

大多数其他答案都使用循环来缩小字体大小,直到它适合div为止,这非常慢,因为每次字体更改大小时页面都需要重新渲染元素。我最终不得不编写自己的算法,使其以允许我定期更新其内容而不冻结用户浏览器的方式执行。我添加了一些其他功能(旋转文本,添加填充)并将其打包为jQuery插件,您可以在以下位置获取:

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

只需致电

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

它很适合你的容器。

请在此处查看:

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

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

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

答案 5 :(得分:3)

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

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

您需要根据所使用的字体调整factor。 1/3似乎对Times New Roman工作正常。

答案 6 :(得分:2)

在div中,将文本放在没有填充的范围内。然后跨度的宽度将是文本的长度 用于查找要使用的正确字体大小的未经测试的代码:

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

答案 7 :(得分:2)

答案 8 :(得分:2)

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

使用类 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

答案 9 :(得分:2)

在目标类

的支持下修改了@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'));

答案 10 :(得分:1)

我无法弄清楚如何将此添加到sworoc的帖子中,但我想我会分享: 如果您使用任何类型的AJAX导航,Lonesomeday的解决方案会搞砸。我稍微修改了一下:

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

答案 11 :(得分:1)

我(还)制作了另一个插件来解决此问题:

https://github.com/jeremiahrose/perfectFit.js

它生成SVG,因此速度非常快-只需在页面加载时运行一次。能够自动包装和缩放单个单词以使其完全适合div。

答案 12 :(得分:1)

我遇到了类似的问题,这让我为此编写了自己的插件。一种解决方案是使用收缩 - 拟合方法,如上所述。 但是,如果您必须适合多个项目或关注性能,例如,在调整窗口大小时,请查看jquery-quickfit

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

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

Production example, fitting 14x16x2 texts

答案 13 :(得分:1)

这是我对@ teambob的建议(在above comments中)的修改,该建议也考虑了容器的高度:

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

});

请参阅Fiddle

答案 14 :(得分:0)

对于单行文本(如纯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; 
   }
}

答案 15 :(得分:0)

我不确定是否有任何准确的方法来测量文本的宽度(以像素为单位)(因为每个浏览器可能会以不同的方式显示字体)。你可能想尝试使用这个CSS代码,除了根据句子中的字母数做一些“模糊”调整。您可以尝试使用固定宽度的字体(或样式)来显示文本,以便每个字符占用相同的空间量。通过这种方式,您可以做出最佳猜测,如果需要,CSS会在裁剪文本之前至少为您提供一个漂亮的“...”。

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

答案 16 :(得分:0)

这就是我今天发现的:

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

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

    • kw = W/iw
    • kh = H/ih
  4. 在kw和kh之间选择最低:这是想要的FontSize。

  5. 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");
    }
    

答案 17 :(得分:0)

我正在使用香草js。一个对我有用的解决方案是更改水平大小,这是在创建div时,我为给定宽度设置了默认字体大小%。就我而言,我将div包装在一个更大的类中,但是出于这些目的,您可以使用:

document.getElementById("mydiv").fontScale = {scaleVal: scaleFactor, defaultWidth: defaultWidth}

scaleFactor是给定宽度(默认宽度)所需的字体大小(百分比)。然后,当我收到调整大小事件:

let myDiv = document.getElementById("mydiv");
let width = myDiv.offsetWidth;
myDiv.style[fontSize] = String(width/myDiv.fontScale.defaultWidth * myDiv.fontScale.scaleFactor * 100) + "%";

答案 18 :(得分:0)

这是我的解决方案:我在提供的div中测量新div中的文本,以便继承样式。然后我将文本插入带有span的div中以设置font-size。它将最大化为默认字体大小,但会缩小以适应。

它不循环:它只在一次抛弃div中绘制一次文本,然后直接绘制到提供的div。请参阅@Hoffmann回答 - 我只是不喜欢整个&#39;插件&#39;回答这个问题。

需要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>

进行测试:这就是我发现我需要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 font-size。我没有用em或pt进行测试。

答案 19 :(得分:0)

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

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

答案 20 :(得分:0)

我在这里制作了一些帖子并制作了一个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是全局的,并且只应用于元素类型。换句话说,它创建了一个同名的标签,并假设它将具有与我们想要更改的元素相同的CSS属性。如果您不这样做,只需修改创建resizer的行。

答案 21 :(得分:0)

你可以做多件事,比如

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)

答案 22 :(得分:-1)

简单的解决方案

<div class="fitt-text"><span>text</span></div>

js

$(".fitt-text").css('font-size', '1vw');
    
var cw = $(".fitt-text").width();
var w = $(".fitt-text span").width();
var f = cw/w;

$(".fitt-text").css('font-size', f + 'vw');