将文本完美地适应一个div(高度和宽度),而不影响div的大小

28

提前道歉,我知道这个问题之前已经出现过很多次,但我似乎找不到正确的解决方案(相信我,我已经尝试了几种方案!)

基本上就是老问题:“将文本完美地适应div而不影响div的大小”。除非我是个完全的白痴,否则我相信CSS没有办法做到这一点。所以我的意思基本上是,而不是像这样做:

#someDiv {
font-size: 12px;
}

或者...

#someDiv {
font-size: 1em;
}

我希望能够像这样做:

#someDiv {
font-size: fluid;
}

这意味着不管这个 div 包含什么文本,都将其按比例缩放以适应左右和上下无溢出或空白。

在搜索了无数网站寻找这个 CSS 解决方案后,我现在已经认识到 CSS 无法做到这一点...所以,进入 jQuery。

我在网上找到了几个 jQuery 的解决方案,但它们只会将文本按比例缩放以适应宽度,而我希望它也可以按比例缩放以适应高度。因此,实际上我想对 jQuery 说:

"jQuery,请找到 $(this) div,无论里面包含什么文本,我希望你将其按比例缩放,使其尽可能紧密地填满整个 div 的高度和宽度"。

如果我没有解释清楚,我附上了一个图形来说明我面临的问题和我正在寻找的解决方案。

非常感谢任何帮助。谢谢。

enter image description here


3
@YannickY 显然他的意思是调整文本大小以填充内容div但不溢出。这是可行的,但我一时想不到一个好的方法。如果我有时间,稍后会为您答复:)。 - Maverick
1
不,滚动条是我想要避免的一部分。我基本上希望文本尽可能大或小,以适应给定的 div。没有滚动条。没有溢出。没有空白。只有从上到下和从左到右的纯文本。谢谢。 - Ben Clarke
是否有最小或最大尺寸?font-size受到的影响是唯一的吗?line-heightletter-spacing呢?如果我只输入一个单词,再按回车键会发生什么?你是否只是消除回车并仅允许内联文本?我的意思是,在这种情况下,有太多不同的选项和需要考虑的事情。但是,如果你可以对这些问题和其他一些问题给出一个明确的答案,你就可以使用JavaScript做到接近你想要的东西。 - Adam Merrifield
1
只是想确认一下,如果您有太多字符,那么您会减小字体大小吗?那么在某些时候,字体大小不会太小吗? - Yannick Y
2
我只是在考虑极端情况下的逻辑,无论是几个单词还是太多单词(当涉及到调整文本大小时)。 - Yannick Y
显示剩余5条评论
9个回答

16

以下是相同答案,但使用 Javascript 编写:

var autoSizeText;

autoSizeText = function() {
  var el, elements, _i, _len, _results;
  elements = $('.resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _results = [];
  for (_i = 0, _len = elements.length; _i < _len; _i++) {
    el = elements[_i];
    _results.push((function(el) {
      var resizeText, _results1;
      resizeText = function() {
        var elNewFontSize;
        elNewFontSize = (parseInt($(el).css('font-size').slice(0, -2)) - 1) + 'px';
        return $(el).css('font-size', elNewFontSize);
      };
      _results1 = [];
      while (el.scrollHeight > el.offsetHeight) {
        _results1.push(resizeText());
      }
       return _results1;
    })(el));
  }
  return _results;
};

$(document).ready(function() {
  return autoSizeText();
});

顺便说一下...如果你需要将Coffeescript转换为Javascript,只需访问js2coffee.org


3
以下是相同的答案,但使用Javascript语言: :) 哇,我们不需要下载jQuery库了!太好了!顺便说一下,在jQuery中不需要使用"px"。 - Roko C. Buljan
@RokoC.Buljan JavaScript是一种编程语言,jQuery仅仅是一个库(一个非常棒的库)。这个回答是从CoffeeScript中复制过来的,它是一种不同的编程语言。 - Maverick

10

我没有足够的声望在已接受的答案上进行评论,所以我发表了一个答案。如果height 在css3上有过渡效果,则autoSizeText()$.resizeText 的答案存在问题。我编写了一个简短的jQuery插件来解决这个问题。

$.fn.resizeText = function (options) {

    var settings = $.extend({ maxfont: 40, minfont: 4 }, options);

    var style = $('<style>').html('.nodelays ' +
    '{ ' +
        '-moz-transition: none !important; ' +
        '-webkit-transition: none !important;' +
        '-o-transition: none !important; ' +
        'transition: none !important;' +
    '}');

    function shrink(el, fontsize, minfontsize)
    {
        if (fontsize < minfontsize) return;

        el.style.fontSize = fontsize + 'px';

        if (el.scrollHeight > el.offsetHeight) shrink(el, fontsize - 1, minfontsize);
    }

    $('head').append(style);

    $(this).each(function(index, el)
    {
        var element = $(el);

        element.addClass('nodelays');

        shrink(el, settings.maxfont, settings.minfont);

        element.removeClass('nodelays');
    });

    style.remove();
}

要使用这个插件,你只需要调用

 $(selector).resizeText();

我希望这可以帮助其他人节省一些疑难解答的时间。我浪费了20分钟左右,纠结于为什么上面的代码会在我的页面上导致无限循环。


谢谢Kelt。对我来说,被接受的答案没有起作用,看不到文本大小的变化。 你的方法很好... +1 - Shaakir
请添加以下样式以实现完美效果: {overflow-y:scroll; width:100%; max-height:20px; overflow-wrap: break-word;} - Nguyên Ngô Duy

10

最近我也想要类似的东西:

<div class='container'>
    <div class='no-resize'>This text won't be resized and will go out of the div.</div>
    <div class='resize'>This text will be resized and wont go out of the div.</div>
</div>

并且
.no-resize, .resize {
    width: 100px;
    height: 50px;
    border: 1px solid #000;
    color: #000;
    float: left;
    margin-left: 10px;
    font-size: 15px
}

jsfiddle.net/mn4rr/1/上使用 Fiddler 工具。


哇,看起来不错!真的很好!谢谢。这可能是我正在寻找的解决方案。但不幸的是(对我来说),它是用我一点也不了解的CoffeeScript编写的。你知道我该如何用jQuery编写吗?再次感谢。 - Ben Clarke
我使用了js2coffee.org,所以显然得到了与joshboley相同的结果,但是我无法在jsfiddle中以相同的方式运行它。也许你可以。 - Thomas McNaught
1
看起来这个程序做得还不错 --> http://jsfiddle.net/LrCFY/3/ 它可能不是完美的,但现在应该能够胜任这项工作。谢谢大家! - Ben Clarke
1
这个解决方案的问题在于它需要你提前在CSS中手动设置最大字体大小,然后它会自动缩小以适应。我认为这不符合要求:例如:根据内容自动调整大小。我还认为使用像素进行尺寸调整意味着你很少能够精确匹配,使用em值会更好。 - Maverick
好观点@MrN00b——我完全同意。但不幸的是,这是我找到的最接近实际可行的答案。 - Ben Clarke
你收到了一条有关于 JSFiddle 链接的系统消息,为什么不遵守呢? - brasofilo

4
我用jQuery编写了一个插件来解决这个问题,插件在这里:http://jsfiddle.net/c9YNz/2/(已更新以适应调整窗口大小)。
该插件的代码将文本缩小到0.01em大小,然后再放大以适应。以下是插件代码:
$.fn.resizeText = function () {
    var width = $(this).innerWidth();
    var height = $(this).innerHeight();
    var html =  $(this).html();
    var newElem = $("<div>", {
        html: html,
        style: "display: inline-block;overflow:hidden;font-size:0.1em;padding:0;margin:0;border:0;outline:0"
    });

    $(this).html(newElem);
    $.resizeText.increaseSize(10, 0.1, newElem, width, height);

    $(window).resize(function () {
        if ($.resizeText.interval)
            clearTimeout($.resizeText.interval)

        $.resizeText.interval = setTimeout(function () {
            elem.html(elem.find("div.createdResizeObject").first().html());
            elem.resizeText();
        }, 300);
    });
}

$.resizeText = {
    increaseSize: function (increment, start, newElem, width, height) {
        var fontSize = start;

        while (newElem.outerWidth() <= width && newElem.outerHeight() <= height) {
            fontSize += increment;
            newElem.css("font-size", fontSize + "em");
        }

        if (newElem.outerWidth() > width || newElem.outerHeight() > height) {
            fontSize -= increment;
            newElem.css("font-size", fontSize + "em");
            if (increment > 0.1) {
                $.resizeText.increaseSize(increment / 10, fontSize, newElem, width, height);
            }
        }
    }
};

如果您有这个HTML代码:
<div class="resizeText" style="width:1200px;height:400px;">
Insert text from slipsum here.
</div>

您可以直接这样调用:

$(document).ready(function () {
    $(".resizeText").resizeText();
});

这不是最好的方式,但我想足以满足你的需求(而且它可行)。


谢谢。但是当我将容器的大小更改为百分比值(对于响应式设计对我很重要)时,似乎会破坏它并使文本溢出容器?--> http://jsfiddle.net/c9YNz/。在我看来,这种方式似乎更加可靠 --> http://jsfiddle.net/LrCFY/3/。 - Ben Clarke
@BenClarke 对于我来说,使用百分比是可以工作的(包括你提供的fiddle链接),你在使用哪个浏览器呢(我没有进行全面的测试)?我刚刚在最新版本的Chrome、IE和Firefox中进行了快速测试,它们都可以正常工作。很好奇为什么它对你无效。 - Maverick
我正在使用最新版的Chrome浏览器。那么这很奇怪?这是一个屏幕截图 --> 屏幕截图 - Ben Clarke
你可能需要再次点击“运行”。我猜这是由于窗口调整大小(或CSS编辑而没有点击“运行”)引起的。我会更新fiddle以随窗口大小调整。 - Maverick
非常奇怪,对我来说,我尝试的每个百分比都有效。多么奇怪。 - Maverick
显示剩余2条评论

2

这是给出答案的略微修改版。

要求:

  1. 包含文本的类具有“resize”类。
  2. 它包含高度和宽度(%,px等)。

此版本的更改:

  1. 我添加了调整大小(通过将事件resize绑定到函数autoSizeText)。这远非理想,但如果我们不经常调整大小,应该没问题。
  2. 在以前的版本中,文本只变小。现在它尝试找到最大的字体而不超出div。

注意:

我不认为代码已准备好投入生产。但如果您发现可以增强的内容,请与社区分享。

var autoSizeText = function () {
    var el, elements, _i, _len;
    elements = $('.resize');
    if (elements.length < 0) {
        return;
    }
    for (_i = 0, _len = elements.length; _i < _len; _i++) {
        el = elements[_i];
        dichoFit = function (el) {

            diminishText = function () {
                var elNewFontSize;
                elNewFontSize = (parseInt($(el).css('font-size').slice(0, -2)) - 1) + 'px';

                return $(el).css('font-size', elNewFontSize);
            };
            augmentText = function () {
                var elNewFontSize;
                elNewFontSize = (parseInt($(el).css('font-size').slice(0, -2)) + 1) + 'px';

                return $(el).css('font-size', elNewFontSize);
            };


            diminishText();
            while (el.scrollHeight < el.offsetHeight) {
                augmentText();
            }
            augmentText();
            while (el.scrollHeight > el.offsetHeight) {
                diminishText();
            }

        }
        dichoFit(el);
    }
};

$(document).ready(function () {
    autoSizeText();
    $(window).resize(function resizeText(){
        autoSizeText()
    })
});
.sizable{
 width: 50vw;
 height: 50vh;
 border: 2px solid darkred;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <div class='sizable resize'>
  I am a sizable div and I have explicit width and height.
</div>


这是一个非常出色的答案,似乎在其他答案的基础上有很大的改进。然而,如果我从最大化状态恢复窗口,脚本似乎会失败。我必须开始调整窗口大小才能激活脚本。您知道是否有一种方法可以修改以实现这一点吗? - geekTechnique

0

我遇到了同样的问题,解决方案基本上是使用JavaScript来控制字体大小。 在Codepen上可以查看这个例子:

https://codepen.io/ThePostModernPlatonic/pen/BZKzVR

尝试调整它的大小。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
<style>
</style>
</head>
<body>
<div style="height:100vh;background-color: tomato;" id="wrap">        
  <h1 class="quote" id="quotee" style="padding-top: 56px">Because too much "light" doesn't <em>illuminate</em> our paths and warm us, it only blinds and burns us.</h1>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
  var multiplexador = 3;
  initial_div_height = document.getElementById ("wrap").scrollHeight;
  setInterval(function(){ 
    var div = document.getElementById ("wrap");
    var frase = document.getElementById ("quotee");
    var message = "WIDTH div " + div.scrollWidth + "px. "+ frase.scrollWidth+"px. frase \n";
    message += "HEIGHT div " + initial_div_height + "px. "+ frase.scrollHeight+"px. frase \n";           
    if (frase.scrollHeight < initial_div_height - 30){
      multiplexador += 1;
      $("#quotee").css("font-size", multiplexador); 
    }
    console.log(message);          
  }, 10);
</script>
</html>

0

这是我的版本。使用ES6构建,位于React项目中。

export function autoSizeText(container, attempts=30) {
  let setChildrenToInheritFontSize = ( el ) => {
    el.style.fontSize = 'inherit';
    _.each( el.children, (child) => {
      setChildrenToInheritFontSize( child );
    });
  };


  let resizeText = (el) => {
    attempts--;
    let elNewFontSize;
    if( el.style.fontSize === "" ||  el.style.fontSize === "inherit" ||  el.style.fontSize === "NaN" ){
      elNewFontSize = '32px'; // largest font to start with
    } else {
      elNewFontSize = (parseInt(el.style.fontSize.slice(0, -2)) - 1) + 'px';
    }
    el.style.fontSize = elNewFontSize;

    // this function can crash the app, so we need to limit it
    if( attempts <= 0 ) {
      return;
    }

    if ( (el.scrollWidth > el.offsetWidth) || (el.scrollHeight > el.offsetHeight)) {
      resizeText(el);
    }
  };
  setChildrenToInheritFontSize( container );
  resizeText(container);
}

0

最近我遇到一个问题,我有一个最大宽度的 div,它接收来自文本输入框的文本,我需要让这段文本适应这个 div 的宽度。下面是我解决这个问题的方法(使用简单的 JavaScript,没有插件):

function addName(){
    let maxWidth = 550;
    let defaultFontSize = 50;
    let entry = document.getElementById('nameInput').value;
    let nameDiv = document.getElementById('name');
    let fontSize = nameDiv.style["font-size"];
    fontSize = fontSize.replace('px','');
    fontSize = parseInt(fontSize);
    nameDiv.innerText = entry;
    if (nameDiv.clientWidth > maxWidth) {
        fontSize = fontSize - 2.5;
        nameDiv.style["font-size"] = `${fontSize}px`;
    } else if (nameDiv.clientWidth < maxWidth && fontSize < defaultFontSize ) {
        fontSize = fontSize + 2.5;
        nameDiv.style["font-size"] = `${fontSize}px`;
    }
}
#name {
    height: 70px;
    line-height: 70px;
    text-align: center;
    overflow: hidden;
    width: auto;
    display: table; /*THAT DOES THE MAGIC*/
    margin: auto;
    border: 1px solid black
/* THE BORDER IS FOR TEST PURPOSES TO SEE WHAT'S HAPPENING WITH THE DIV*/
}
<input type="text" id="nameInput" oninput="addName()">
<div id="name" style="font-size: 50px;"></div>


0

抱歉回复晚了,但可以节省许多时间, 我编写了这段代码,在调整窗口大小时完美运行。

function fitTextInDiv(){
    if($this.find('.text-wrapper').height() > $this.find('.aligned-text').height() ){
        while( $this.find('.text-wrapper').height() > $this.find('.aligned-text').height() ) {
             $this.find('.aligned-text').css('font-size', (parseFloat($this.find('.aligned-text').css('font-size')) + 0.1) + "px" );
        }
    }
    else if($this.find('.text-wrapper').height() < $this.find('.aligned-text').height() ){
        while( $this.find('.text-wrapper').height() < $this.find('.aligned-text').height() ) {
            $this.find('.aligned-text').css('font-size', (parseFloat($this.find('.aligned-text').css('font-size')) - 0.1) + "px" );
        }

     }
}

其中text-wrapper是父元素,aligned-text是子div。您必须指定父元素的高度和宽度。在调整大小时,您可以使用jquery设置父元素的高度和宽度,然后调用此函数。

我编写这段代码是因为我尝试了许多插件,但它们不支持调整窗口大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接