











如何固定列宽下数字过长时:先继承父级字号,再按设计稿字号逐步 -1 缩小,最小 12;仍超出才 `...`。
适配约定(375 设计稿):
- `html.fontSize = (width / 375) * 100`
- postcss `rootValue: 100` → 设计稿 px 转 rem:`px / 100`
---
## 封装:AutoFitText
```tsx
import { useLayoutEffect, useRef, type ReactNode } from 'react'
/** 与 index.html / postcss-pxtorem 一致 */
const DESIGN_ROOT_VALUE = 100
const MIN_DESIGN_FONT_SIZE = 12
const designPxToRem = (designPx: number) =>
`${designPx / DESIGN_ROOT_VALUE}rem`
interface AutoFitTextProps {
children: ReactNode
className?: string
}
/**
* 默认 inherit;超出后设计稿字号逐步 -1,最小 12;仍超出再省略号。
*/
export const AutoFitText = ({ children, className }: AutoFitTextProps) => {
const ref = useRef<HTMLSpanElement>(null)
useLayoutEffect(() => {
const el = ref.current
if (!el) return
const fit = () => {
el.style.fontSize = ''
el.classList.remove('is-ellipsis')
if (el.clientWidth <= 0) return
if (el.scrollWidth <= el.clientWidth + 1) return
const rootPx =
parseFloat(getComputedStyle(document.documentElement).fontSize) ||
DESIGN_ROOT_VALUE
const inheritedCssPx = parseFloat(getComputedStyle(el).fontSize) || 14
let designSize = Math.round((inheritedCssPx / rootPx) * DESIGN_ROOT_VALUE)
while (
designSize > MIN_DESIGN_FONT_SIZE &&
el.scrollWidth > el.clientWidth + 1
) {
designSize -= 1
el.style.fontSize = designPxToRem(designSize)
}
if (el.scrollWidth > el.clientWidth + 1) {
el.classList.add('is-ellipsis')
}
}
fit()
window.addEventListener('resize', fit, false)
return () => window.removeEventListener('resize', fit, false)
}, [children])
return (
<span
ref={ref}
className={`auto-fit-text${className ? ` ${className}` : ''}`}
>
{children}
</span>
)
}
```
配套样式:
```less
.auto-fit-text {
font-size: inherit;
text-overflow: clip;
&.is-ellipsis {
text-overflow: ellipsis;
}
}
/* 容器必须有固定宽度,文字节点占满宽度,才能正确测溢出 */
.demo-box {
width: 120px;
overflow: hidden;
font-size: 16px;
> span {
display: block;
width: 100%;
max-width: 100%;
overflow: hidden;
white-space: nowrap;
}
}
```
---
## 使用案例(独立 Demo)
```tsx
import { useState } from 'react'
import { AutoFitText } from './auto-fit-text'
export default function AutoFitTextDemo() {
const [text, setText] = useState('12345678901234567890')
return (
<div>
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="输入一段文字试试"
/>
{/* 固定 120px 宽,观察字号缩小 / 省略号 */}
<div className="demo-box">
<AutoFitText>{text}</AutoFitText>
</div>
</div>
)
}
```
效果说明:
1. 输入较短内容:保持父级 `16px`
2. 内容变长:字号逐步降到 `15 → 14 → … → 12`
3. 到 `12` 仍放不下:显示 `...`
---
## 注意点
1. 父容器要有明确宽度,且 `overflow: hidden`
2. 文字节点 `width: 100%` + `white-space: nowrap`,否则 `scrollWidth === clientWidth` 测不准
3. 缩小后写 rem(`设计稿px / 100`),不要写死 `px`
4. 未缩小时清空内联 `fontSize`,继续继承父级字号
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。