调整fontSize时scrollWidth与clientWidth未更新的问题求助
动态调整字体大小函数失效:scrollWidth与clientWidth数值不更新
我写了一个adjustFontSize函数,想根据元素的scrollWidth动态增大容器的fontSize,直到内容无法容纳容器。但在while循环里打印scrollWidth和clientWidth时,这两个值始终不变,根本触发不了循环终止条件。
我的代码
JavaScript函数
function adjustFontSize(textField) { let fontSize = 10; // 初始字体大小 textField.style.fontSize = fontSize + "px"; // 增大字体直到内容无法容纳 while (textField.scrollWidth <= textField.clientWidth) { fontSize++; textField.style.fontSize = fontSize + "px"; } }
HTML结构
<div id="playerInfoContainer"> <div class="playerInfo winner"> <div class="playerInfoName">Sané</div> <div class="playerInfoPercentage">9 (40,9%)</div> </div> <div class="playerInfo"> <div class="playerInfoName">Hamm</div> <div class="playerInfoPercentage">8 (36,4%)</div> </div> <div class="playerInfo"> <div class="playerInfoName">Gulászci</div> <div class="playerInfoPercentage">5 (22,7%)</div> </div> </div>
CSS样式
#playerInfoContainer { position: absolute; top: 172px; left: 0; width: 267px; height: 599px; text-align: center; display: flex; flex-direction: column; justify-content: space-around; align-items: center; } .playerInfo { width: 200px; } .playerInfoName { font-family: UberEatsFat; } .playerInfoPercentage { font-size: 25px; font-family: UberEatsRegular; }
我试过给子元素设置flex-basis: 0px、flex-shrink: 0来固定宽度,但问题还是没解决。DevTools里能看到超出容器的元素实际scrollWidth大于clientWidth,但代码执行时读取的数值就是不更新。
最小可复现示例(MRE)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <style> #playerInfoContainer { position: absolute; top: 172px; left: 0; width: 267px; height: 599px; text-align: center; display: flex; flex-direction: column; justify-content: space-around; align-items: center; } .playerInfo { width: 200px; } .playerInfo.winner { color: red; } .playerInfoName { font-family: UberEatsFat; } .playerInfoPercentage { font-size: 25px; font-family: UberEatsRegular; } </style> <body> <div id="playerInfoContainer"> <div class="playerInfo winner"> <div class="playerInfoName">Sané</div> <div class="playerInfoPercentage">9 (40,9%)</div> </div> <div class="playerInfo"> <div class="playerInfoName">Hamm</div> <div class="playerInfoPercentage">8 (36,4%)</div> </div> <div class="playerInfo"> <div class="playerInfoName">Gulászci</div> <div class="playerInfoPercentage">5 (22,7%)</div> </div> </body> <script> const playerInfoContainer = document.getElementById("playerInfoContainer"); const playerInfoContainerChildren = playerInfoContainer.children; Array.from(playerInfoContainerChildren).forEach((child) => { console.log("child: ", child); adjustFontSize(child); }); function adjustFontSize(textField) { let fontSize = 10; // 初始字体大小 textField.style.fontSize = fontSize + "px"; // 增大字体直到内容无法容纳 console.log("textfield: ", textField); console.log("scrollWidth: ", textField.scrollWidth); console.log("clientWidth: ", textField.clientWidth); while (textField.scrollWidth <= textField.clientWidth && fontSize < 30) { console.log("scrollWidth: ", textField.scrollWidth); console.log("clientWidth: ", textField.clientWidth); fontSize++; textField.style.fontSize = fontSize + "px"; } console.log("scrollWidth: ", textField.scrollWidth); console.log("clientWidth: ", textField.clientWidth); // 回退一个字号 textField.style.fontSize = fontSize - 6 + "px"; } </script> </html>
问题原因与解决办法
核心原因
- 浏览器重排延迟:JavaScript执行时会批量处理DOM样式更新,循环内连续修改
fontSize后,浏览器不会立刻重排,导致scrollWidth和clientWidth始终读取旧值。 - 目标元素错误:你传入的是
.playerInfo容器,但这个容器宽度固定为200px,子元素文本溢出时只会自动换行,不会让容器的scrollWidth超过clientWidth——真正需要调整的是文本所在的.playerInfoName元素。
修复步骤
1. 调整目标元素
把调整字体的目标改成.playerInfoName(文本所在的元素),而非外层容器。
2. 强制浏览器重排
每次修改字体大小后,读取元素的offsetHeight触发浏览器重排,更新scrollWidth数值。
3. 禁止文本换行
给目标文本元素设置white-space: nowrap,确保字体增大到一定程度时,元素的scrollWidth会超过clientWidth。
修复后的代码
修改后的CSS
.playerInfoName { font-family: UberEatsFat; white-space: nowrap; /* 禁止文本换行 */ width: 100%; /* 继承父容器宽度 */ overflow: hidden; /* 隐藏溢出内容 */ }
修改后的JavaScript
const playerInfoContainer = document.getElementById("playerInfoContainer"); // 遍历所有文本元素 document.querySelectorAll('.playerInfoName').forEach((el) => { adjustFontSize(el); }); function adjustFontSize(textField) { let fontSize = 10; textField.style.fontSize = fontSize + "px"; while (textField.scrollWidth <= textField.clientWidth && fontSize < 30) { fontSize++; textField.style.fontSize = fontSize + "px"; // 强制浏览器重排,更新scrollWidth textField.offsetHeight; } // 回退到最后一个合适的字号 textField.style.fontSize = (fontSize - 1) + "px"; }
额外说明
- 如果需要调整
.playerInfoPercentage的字体大小,可同理遍历该类元素调用调整函数。 - 设置
fontSize < 30的上限是必要的,防止极端情况出现无限循环。
内容的提问来源于stack exchange,提问作者clemens_blrk
相关产品推荐
相关产品推荐

