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

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

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


当前回答

大多数其他答案使用循环来减少字体大小,直到它适合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标签内的内部元素(如换行或字体很棒的图标)。

其他回答

这是我对OP的答案的修改。

简而言之,许多尝试优化此功能的人抱怨使用了循环。是的,虽然循环可能很慢,但其他方法可能不准确。

因此,我的方法是使用二进制搜索来找到最好的字体大小:

$.fn.textfill = function()
{
    var self = $(this);
    var parent = self.parent();

    var attr = self.attr('max-font-size');
    var maxFontSize = parseInt(attr, 10);
    var unit = attr.replace(maxFontSize, "");

    var minFontSize = parseInt(self.attr('min-font-size').replace(unit, ""));
    var fontSize = (maxFontSize + minFontSize) / 2;

    var maxHeight = parent.height();
    var maxWidth = parent.width();

    var textHeight;
    var textWidth;

    do
    {
        self.css('font-size', fontSize + unit);

        textHeight = self.height();
        textWidth = self.width();

        if(textHeight > maxHeight || textWidth > maxWidth)
        {
            maxFontSize = fontSize;
            fontSize = Math.floor((fontSize + minFontSize) / 2);
        }
        else if(textHeight < maxHeight || textWidth < maxWidth)
        {
            minFontSize = fontSize;
            fontSize = Math.floor((fontSize + maxFontSize) / 2);
        }
        else
            break;

    }
    while(maxFontSize - minFontSize > 1 && maxFontSize > minFontSize);

    self.css('font-size', fontSize + unit);

    return this;
}

function resizeText()
{
  $(".textfill").textfill();
}

$(document).ready(resizeText);
$(window).resize(resizeText);

这也允许元素指定最小和最大字体:

<div class="container">
    <div class="textfill" min-font-size="10px" max-font-size="72px">
        Text that will fill the container, to the best of its abilities, and it will <i>never</i> have overflow.
    </div>
</div>

此外,该算法是无单位的。你可以指定em, rem, %等,它将使用它的最终结果。

这是小提琴:https://jsfiddle.net/fkhqhnqe/1/

你可以使用FitText.js (github页面)来解决这个问题。与TextFill相比是非常小和有效的。TextFill使用了昂贵的while循环,而FitText没有。

FitText也更灵活(我在一个有非常特殊要求的项目中使用它,工作起来像个冠军!)。

HTML:

<div class="container">
  <h1 id="responsive_headline">Your fancy title</h1>
</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jquery.fittext.js"></script>
<script>
  jQuery("#responsive_headline").fitText();
</script>

你也可以设置选项:

<script>
  jQuery("#responsive_headline").fitText(1, { minFontSize: '30px', maxFontSize: '90px'});
</script>

CSS:

#responsive_headline {
   width: 100%;
   display: block;
}

如果你需要它,FitText也有一个非jquery版本。

这是我最后得到的结果:

这是该插件的链接:https://plugins.jquery.com/textfill/ 还有一个来源的链接:http://jquery-textfill.github.io/

;(function($) {
    $.fn.textfill = function(options) {
        var fontSize = options.maxFontPixels;
        var ourText = $('span:visible:first', this);
        var maxHeight = $(this).height();
        var maxWidth = $(this).width();
        var textHeight;
        var textWidth;
        do {
            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();
            fontSize = fontSize - 1;
        } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
        return this;
    }
})(jQuery);

$(document).ready(function() {
    $('.jtextfill').textfill({ maxFontPixels: 36 });
});

我的HTML是这样的

<div class='jtextfill' style='width:100px;height:50px;'>
    <span>My Text Here</span>
</div>

我为AngularJS创建了一个指令——很大程度上受到了GeekyMonkey答案的启发,但没有jQuery依赖。

演示:http://plnkr.co/edit/8tPCZIjvO3VSApSeTtYr?p=preview

标记

<div class="fittext" max-font-size="50" text="Your text goes here…"> < / div >

指令

app.directive('fittext', function() {

  return {
    scope: {
      minFontSize: '@',
      maxFontSize: '@',
      text: '='
    },
    restrict: 'C',
    transclude: true,
    template: '<div ng-transclude class="textContainer" ng-bind="text"></div>',
    controller: function($scope, $element, $attrs) {
      var fontSize = $scope.maxFontSize || 50;
      var minFontSize = $scope.minFontSize || 8;

      // text container
      var textContainer = $element[0].querySelector('.textContainer');

      angular.element(textContainer).css('word-wrap', 'break-word');

      // max dimensions for text container
      var maxHeight = $element[0].offsetHeight;
      var maxWidth = $element[0].offsetWidth;

      var textContainerHeight;
      var textContainerWidth;      

      var resizeText = function(){
        do {
          // set new font size and determine resulting dimensions
          textContainer.style.fontSize = fontSize + 'px';
          textContainerHeight = textContainer.offsetHeight;
          textContainerWidth = textContainer.offsetWidth;

          // shrink font size
          var ratioHeight = Math.floor(textContainerHeight / maxHeight);
          var ratioWidth = Math.floor(textContainerWidth / maxWidth);
          var shrinkFactor = ratioHeight > ratioWidth ? ratioHeight : ratioWidth;
          fontSize -= shrinkFactor;

        } while ((textContainerHeight > maxHeight || textContainerWidth > maxWidth) && fontSize > minFontSize);        
      };

      // watch for changes to text
      $scope.$watch('text', function(newText, oldText){
        if(newText === undefined) return;

        // text was deleted
        if(oldText !== undefined && newText.length < oldText.length){
          fontSize = $scope.maxFontSize;
        }
        resizeText();
      });
    }
  };
});

所提出的迭代解决方案可以在两个方面显著加速:

1)将字体大小乘以某个常数,而不是加或减1。

2)首先,使用零过程常数,比如,将每个循环的大小增加一倍。然后,有了一个大致的想法从哪里开始,做同样的事情,并进行更精细的调整,比如乘以1.1。虽然完美主义者可能想要理想字体的精确整数像素大小,但大多数观察者不会注意到100和110像素之间的区别。如果你是一个完美主义者,那么重复第三次,做更细致的调整。

我没有编写特定的例程或插件来回答确切的问题,而是依赖于基本思想并编写代码的变体来处理各种布局问题,而不仅仅是文本,包括拟合div、跨度、图像……通过宽度、高度、面积、……在容器中,匹配另一个元素....

这里有一个例子:

  var                           nWindowH_px             = jQuery(window).height();
  var                           nWas                    = 0;
  var                           nTry                    = 5;

  do{
   nWas = nTry;
   nTry *= 2;
   jQuery('#divTitle').css('font-size' ,nTry +'px');
  }while( jQuery('#divTitle').height() < nWindowH_px );

  nTry = nWas;

  do{
   nWas = nTry;
   nTry = Math.floor( nTry * 1.1 );
   jQuery('#divTitle').css('font-size' ,nTry +'px');
  }while( nWas != nTry   &&   jQuery('#divTitle').height() < nWindowH_px );

  jQuery('#divTitle').css('font-size' ,nWas +'px');