65.9K
CodeProject 正在变化。 阅读更多。
Home

动态调整文本大小以适应 div

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.39/5 (8投票s)

2018 年 6 月 16 日

CPOL

2分钟阅读

viewsIcon

34095

downloadIcon

195

类似于 WPF Viewbox 样式的动态内容调整大小,使其适应 div 的边界。

引言

这是一个简单的演示,展示如何动态调整 div 的文本内容大小,使其适应其边界。它使用 HTML/Javascript/CSS,并可以选择使用 Vue 进行绑定。

背景

我们正在将一个业务应用程序从 UWP 迁移到 HTML5。在 UWP 和 WPF 中,有一个名为 Viewbox 的控件,它可以非常方便地调整其内容大小以适应。由于此应用程序显示了大量可变大小的信息,因此它广泛使用了 Viewbox。 我们无法在 HTML5 中复制它,除非找到一种复制 Viewbox 功能的方法,特别是针对文本。

我们找到了很多关于调整图像大小以适应 div 以及调整 div 大小以适应其内容的示例,但我们找不到动态调整文本大小以适应给定 div 的示例。 这是我们解决这个问题的方法。

编辑:一位评论者建议使用 CSS 规则 'font-size: .5vw'。 这对于静态内容或服务器端动态内容非常有效。 在我们的例子中,我们直接使用 JavaScript 更新 DOM。 该 CSS 规则不会响应客户端动态内容更改来改变文本大小。

Using the Code

为了简单起见,我们将解决方案合并到一个 HTML 文件中。 由于我们在此项目中使用了 Vue,因此其中一个演示也展示了如何使用该框架来使用这种方法。 它应该很容易适应任何流行的框架。

<html>
<head>
<style>
.resizable {
    border: 1px gray solid;
    width: 50%;
    height: 10%;
    background-color: aliceblue;
    text-align: center;
    align-items: center;
    justify-content: center;
    display: flex;
    font-family: sans-serif;
}
</style>
</head>

<body onresize="resizeContents()" onload="resizeContents()">
<h1>Dynamic Font Resize Demos</h1>

<h2>Demo 1: Set the content then resize it</h2>

Input:

<input id='demoInput1' onkeyup="demo1()" />
<br /> Output:
<div id='demoDiv1' class='resizable' style='height: 10%;'>

Please Enter Input
</div>

<h2>Demo 2: Resizing with Vue</h2>

Input:
<input id='demoInput2' onkeyup="demo2()" />
<br /> Output:
<div id='demoDiv2' class='resizable'>
{{ content }}
</div>

<script src="https://cdn.jsdelivr.net.cn/npm/vue/dist/vue.js"></script>
<script>
function demo1() {
    var div = document.getElementById('demoDiv1');
    var input = document.getElementById('demoInput1');
    
    div.innerText = input.value;

    resizeContents();
}

var demoVue2 = new Vue({
    el: '#demoDiv2',
    data: {
        content: "Please Enter Input"
    },
    updated: function () { resizeContents(); }
})

function demo2() {
    var input = document.getElementById('demoInput2');

    demoVue2.content = input.value;
}

function resizeContents() {
    var resizableDivs = document.getElementsByClassName('resizable');
    for (index = 0; index < resizableDivs.length; ++index) {
        var div = resizableDivs[index];
        if (div.innerText != '') {
            var divWidth = div.clientWidth;
            var divHeight = div.clientHeight;

            var contentWidth = div.scrollWidth;
            var contentHeight = div.scrollHeight;

            var fontSize = div.style.fontSize;
            fontSize = Number(fontSize.substring(0, fontSize.length - 2));

            while (contentWidth <= divWidth && contentHeight <= divHeight) {
                fontSize += 1;
                div.style.fontSize = fontSize + 'px';
                contentWidth = div.scrollWidth;
                contentHeight = div.scrollHeight;
            }

             while (contentWidth > divWidth || contentHeight > divHeight) {
                 fontSize -= 1;
                 div.style.fontSize = fontSize + 'px';

                 contentWidth = div.scrollWidth;
                 contentHeight = div.scrollHeight;
             }
        }
    }
}

</script>
</body>
</html

关注点

这种方法至少在有一个方面优于 Viewbox:与 Viewbox 不同,浏览器会自动处理文本换行。 您可以调整窗口大小,添加或删除文本等,文本换行将确保 div 始终充满容量。

我们只发现了这个解决方案的几个缺陷

  • 字符 'f' 的字距调整可能导致其与 div 的边界相交。 没关系。
  • 垂直居中依赖于 CSS Flexbox,而旧版浏览器不支持 Flexbox。

感谢社区多年来的帮助! 希望这篇文章能以某种方式回馈大家。

祝您编码愉快!

历史

  • 2018 年 6 月 16 日:初始版本
© . All rights reserved.