You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多语言场景下,如何让固定百分比容器内多行文本自适应缩小?

解决方案:多语言弹性页面文本自适应固定比例容器

哈哈,德语文本的长度确实是多语言弹性页面的噩梦!我之前做类似项目时也被坑过,结合你给出的代码和需求——固定百分比尺寸的区块内文本随语言切换自动缩小、不能用<br>换行,给你几个实用的解决方案:


方案1:纯CSS实现(最简单,无依赖)

利用CSS的clamp()函数结合容器的百分比尺寸,动态调整字体大小,同时确保文本填满容器且不溢出。

修改你的样式代码:

.text-title {
  margin: 5.8% 5.6% 0 5.6%;
  width: 88.8%;
  background: blue;
  font-weight: bold;
  height: 6.315%;
  max-height: 6.315%;
  /* 新增适配样式 */
  display: flex;
  align-items: center; /* 垂直居中文本 */
  overflow: hidden; /* 防止溢出 */
  text-align: left;
  /* 用clamp设置字体范围:最小12px,最大基于容器高度的vh值,中间自动适配 */
  font-size: clamp(12px, calc(6.315vh * 0.8), calc(5.55vh));
}

.text-box-content2 li {
  height: [你的列表项固定高度百分比];
  max-height: [同上];
  display: flex;
  align-items: center;
  overflow: hidden;
  font-size: clamp(10px, calc([列表项高度百分比]vh * 0.75), calc(3.41vh));
}

优点:

  • 无需额外依赖,性能最好
  • 自动适配窗口 resize 和文本内容变化
  • 现代浏览器完全支持(clamp()是CSS3标准,IE除外)

方案2:优化第三方库用法(Fitty/ReactFitText)

你之前尝试的库没生效,大概率是没监听语言切换后的文本内容变化,或者没设置合理的字体范围。这里以Fitty为例,给出React适配代码:

步骤1:安装Fitty

npm install fitty

步骤2:修改你的React组件

import React, { Component, createRef } from 'react';
import ratioFrame from '../../components/ratioFrame';
import withLocale from '../../modules/translate/withLocale';
import fitty from 'fitty';

class PageBFE extends Component {
  constructor(props) {
    super(props);
    this.titleRef = createRef();
    // 存储列表项的ref
    this.listRefs = Array(6).fill().map(() => createRef());
  }

  // 初始化Fitty
  initFitty = () => {
    // 处理标题
    if (this.titleRef.current) {
      fitty(this.titleRef.current, {
        minSize: 12, // 最小字体
        maxSize: parseInt(this.props.formatText(5.55)), // 最大字体(复用你的formatText)
        observe: true // 监听文本内容变化(关键!语言切换时自动重新计算)
      });
    }
    // 处理列表项
    this.listRefs.forEach(ref => {
      if (ref.current) {
        fitty(ref.current, {
          minSize: 10,
          maxSize: parseInt(this.props.formatText(3.41)),
          observe: true
        });
      }
    });
  };

  componentDidMount() {
    this.initFitty();
  }

  // 语言切换时重新初始化
  componentDidUpdate(prevProps) {
    if (prevProps.translate !== this.props.translate) {
      this.initFitty();
    }
  }

  render() {
    const { size, translate } = this.props;
    const textKeys = ['text1','text2','text3','text4','text5','text6','text7'];
    
    return (
      <>
        <div className="content bgPage2" style={size}>
          <div ref={this.titleRef} className="text-title">
            {translate(`presentation1.page2.${textKeys[0]}`)}
          </div>
          <ul className="text-box-content2 liStyle">
            {textKeys.slice(1).map((key, idx) => (
              <li ref={this.listRefs[idx]} key={idx}>
                {translate(`presentation1.page2.${key}`)}
              </li>
            ))}
          </ul>
        </div>
      </>
    );
  }
}

export default withLocale(ratioFrame(PageBFE));

优点:

  • 成熟库,无需自己处理复杂的尺寸计算
  • 支持监听内容和容器变化

方案3:自定义React Hook(最灵活)

如果不想用第三方库,可以自己写一个Hook,监听文本内容和容器尺寸变化,动态计算合适的字体大小:

步骤1:创建useFitText.js Hook

import { useEffect, useState } from 'react';

export const useFitText = (ref, minFontSize = 10, maxFontSize = 30) => {
  const [fontSize, setFontSize] = useState(maxFontSize);

  const adjustFontSize = () => {
    if (!ref.current) return;
    const container = ref.current;
    const content = container.firstChild;
    if (!content) return;

    let currentSize = maxFontSize;
    container.style.fontSize = `${currentSize}px`;

    // 当内容高度超过容器时,逐步缩小字体
    while (content.offsetHeight > container.offsetHeight && currentSize > minFontSize) {
      currentSize--;
      container.style.fontSize = `${currentSize}px`;
    }

    setFontSize(currentSize);
  };

  useEffect(() => {
    adjustFontSize();
    // 监听窗口resize和文本内容变化
    window.addEventListener('resize', adjustFontSize);
    const observer = new MutationObserver(adjustFontSize);
    if (ref.current) {
      observer.observe(ref.current, { childList: true, subtree: true });
    }
    // 清理监听
    return () => {
      window.removeEventListener('resize', adjustFontSize);
      observer.disconnect();
    };
  }, [ref, minFontSize, maxFontSize]);

  return fontSize;
};

步骤2:在组件中使用Hook

import React, { useRef } from 'react';
import ratioFrame from '../../components/ratioFrame';
import withLocale from '../../modules/translate/withLocale';
import { useFitText } from './useFitText';

const PageBFE = ({ size, translate, formatText }) => {
  const titleRef = useRef(null);
  // 复用你的formatText设置最大字体
  const titleFontSize = useFitText(titleRef, 12, parseInt(formatText(5.55)));

  const listRefs = Array(6).fill().map(() => useRef(null));
  const listFontSizes = listRefs.map(ref => useFitText(ref, 10, parseInt(formatText(3.41))));

  const textKeys = ['text1','text2','text3','text4','text5','text6','text7'];

  return (
    <>
      <div className="content bgPage2" style={size}>
        <div 
          ref={titleRef}
          className="text-title"
          style={{ fontSize: `${titleFontSize}px` }}
        >{translate(`presentation1.page2.${textKeys[0]}`)}</div>
        <ul className="text-box-content2 liStyle">
          {textKeys.slice(1).map((key, idx) => (
            <li 
              ref={listRefs[idx]}
              key={idx}
              style={{ fontSize: `${listFontSizes[idx]}px` }}
            >{translate(`presentation1.page2.${key}`)}</li>
          ))}
        </ul>
      </div>
    </>
  );
};

export default withLocale(ratioFrame(PageBFE));

优点:

  • 完全自定义,不需要依赖第三方库
  • 可以根据需求调整计算逻辑(比如支持水平溢出的处理)

内容的提问来源于stack exchange,提问作者Novol

火山引擎 最新活动