基于容器大小的字体缩放

1755

我很难理解字体缩放。

目前我有一个网站,正文的font-size为100%。100%是相对于什么呢?这似乎计算出16像素。

我一直以为100%会与浏览器窗口大小有关, 但显然不是这样,因为无论窗口是否调整大小到移动设备或全屏桌面,都是16像素。

我该如何使网站上的文本根据其容器自适应缩放?我试过使用em,但它也不能缩放。

我的想法是,当您调整大小时,像菜单这样的东西会变形,因此我需要减少与容器宽度相关的.menuItem等元素的pxfont-size。(例如,在大型桌面上的菜单中,22px非常完美。在平板电脑宽度下,16px更合适。)

我知道我可以添加断点,但我真的希望文本能够自适应缩放,并且拥有额外的断点,否则,我将控制文本的每100像素宽度而拥有数百个断点。


51
你需要的是响应式或视口尺寸字体。http://css-tricks.com/viewport-sized-typography/ - gearsdigital
12
看看 **FitText**。 - Patsy Issa
4
使用CSS容器查询 - Janosh
@PatsyIssa 有没有 fittext 的 React 版本? - undefined
41个回答

1
如果您想将其放置在特定容器(如div)中,请使用以下代码:
width: max-content;

同时微调font-size非常有帮助,例如font-size: 75%


1

对于动态文本,该插件非常有用:

http://freqdec.github.io/slabText/

只需添加CSS:

.slabtexted .slabtext
{
    display: -moz-inline-box;
    display: inline-block;
    white-space: nowrap;
}
.slabtextinactive .slabtext
{
    display: inline;
    white-space: normal;
    font-size: 1em !important;
    letter-spacing: inherit !important;
    word-spacing: inherit !important;
    *letter-spacing: normal !important;
    *word-spacing: normal !important;
}
.slabtextdone .slabtext
{
    display: block;
}

脚本内容如下:

$('#mydiv').slabText();

0

直接使用媒体查询似乎是一种更简单、更易理解的解决方案,可以根据可能是动态的容器大小调整字体大小。

下面的代码将字体大小调整为容器的大小,无论容器是否缩放到视口的大小,或者是否达到了其最大值。如果您有非100%宽度的容器,可以相应地调整vw

.container {
    width: 100%;
    max-width: 600px;
}
.headline {
    font-size: 20vw;
}
.subhead {
    font-size: 5vw;
}
@media (min-width:600px) {
    .headline {
        font-size: 120px;
    }
    .subhead {
        font-size: 32px;
    }
}

0

您可以根据窗口宽度插值字体大小:

font-size: calc(
      ${minFontSizeInPixel} *
        (
          1px -
            clamp(
              0px,
              (100vw - ${minWindowWidth}px) /
                (${maxWindowWidth} - ${minWindowWidth}),
              1px
            )
        ) + ${maxFontSizeInPixel} *
        clamp(
          0px,
          (100vw - ${minWindowWidth}px) /
            (${maxWindowWidth} - ${minWindowWidth}),
          1px
        )
    );

0

我本想喜欢那个被接受的答案,但基本上符合我的标准的答案都需要使用一个库。与其熟悉另一个库,然后弄清楚如何使用它并准备调试它(如果它不起作用),我决定编写一个简单的函数,这个函数对我来说完美地工作。

理论:

  • 传入您需要适配的字符串
  • 传入您将从中继承文本样式的父级
  • 可选地传入自定义属性(例如,您将从中继承字体和其他属性的类/ID,或仅自定义内联样式)
  • 函数将在屏幕外创建一个具有该文本、父级和这些属性的文本元素,字体大小为1px,并测量它
  • 然后,在循环中,它将逐像素增加字体大小,直到超过宽度限制;一旦完成,它将返回最后一个适合的字体大小
  • 然后,它删除测试元素
  • 当然,所有这些都发生得非常快

限制:

  • 我不关心动态屏幕调整大小,因为这与我的上下文无关。我只关心在生成文本时运行时的屏幕大小。
  • 我依赖于一个小型辅助函数,我还在代码中其他地方使用它,它基本上存在于 mithril.js 的一个函数版本中;老实说,我在几乎每个项目中都使用这个小函数,它值得学习。
  function findMaxFontSize(
    string="a string", 
    parent=document.body, 
    attributes={id:'font-size-finder',class:'some-class-with-font'}
  ) {
    // by using parent, we can infer the same font inheritance;
    // you can also manually specify fonts or relevant classes/id with attributes if preferred/needed
    attributes.style = 'position:absolute; left:-10000; font-size:1px;' + (attributes.style || "");
    let testFontEl = createEl('p', attributes, string);
    parent.appendChild(testFontEl);
    let currentWidth = testFontEl.offsetWidth;
    let workingFontSize = 1;
    let i = 0;
    while (currentWidth < maxWidth && i < 1000) {
      testFontEl.style.fontSize = Number(testFontEl.style.fontSize.split("px")[0]) + 1 + "px";
      currentWidth = testFontEl.offsetWidth;
      if (currentWidth < maxWidth) {
        workingFontSize = testFontEl.style.fontSize;
      }
      i++; // safety to prevent infinite loops
    }
    console.log("determined maximum font size:",workingFontSize,'one larger would produce',currentWidth,'max width allowed is',maxWidth,'parent is',parent);
    parent.removeChild(testFontEl);
    return workingFontSize.split("px")[0];
  }

// utility function, though you could easily modify the function above to work without this.
  // normally these have no default values specified, but adding them here
  // to make usage clearer.
  function createEl(tag="div", attrs={class:'some-class'}, children=[]) {
    let el = document.createElement(tag);
    if (attrs) {
      Object.keys(attrs).forEach(attr => {
        el.setAttribute(attr, attrs[attr])
      })
    }
    if (children) {
      children = Array.isArray(children) ? children : [children];
      for (let child of children) {
        if (typeof child === "number") child = ""+child;
        if (typeof child === "string") {
          el.insertAdjacentText("afterbegin", child);
        }
        else {
          try {
            el.appendChild(child)
          } catch (e) {
            debugger
          }
        }
      }
    }
    return el;
  };

使用:

    const getUsername = () => "MrHarry";
    const username = getUsername();
    const anchor = document.querySelector('.container');
    const titleFontSize = findMaxFontSize(`Welcome, ${username}`, anchor, {style:'font-weight:900;'});
    const titleFontStyle = `font-size:${titleFontSize}px;`;  

0

我刚刚创建了一个演示,展示如何实现它。它使用transform:scale()来实现,并配合一些JS来监视元素的大小调整。对我的需求来说效果很好。


-1
为了使字体大小适应其容器而不是窗口,请参见我在此问题中分享的resizeFont()函数(其他答案的组合,其中大部分已在此处链接)。它使用window.addEventListener('resize', resizeFont);触发。 < p > Vanilla JavaScript: Resize font-awesome to fit container

JavaScript:

function resizeFont() {
  var elements  = document.getElementsByClassName('resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _len = elements.length;
  for (_i = 0; _i < _len; _i++) {
    var el = elements[_i];
    el.style.fontSize = "100%";
    for (var size = 100; el.scrollHeight > el.clientHeight; size -= 10) {
      el.style.fontSize = size + '%';
    }
  }
}

你可以使用vw/vh作为备选方案,使用JavaScript动态分配emrem单位,确保字体在禁用JavaScript时也能按比例缩放到窗口大小。

.resize类应用于包含要缩放的文本的所有元素。

在添加窗口调整大小事件监听器之前触发该函数。然后,当页面加载时以及调整大小时,任何不适合其容器的文本都会被缩小。

注意:默认的font-size必须设置为emrem%才能实现正确的结果。


-1
如果问题是在宽屏桌面上字体太大,我认为最简单的CSS方法应该是这样的(假设包装器最大宽度为1000像素)。
.specialText{
    font-size: 2.4vw;
}

@media only screen and (min-width: 1000px) {
    .specialText {
        width: 24px;
    }
}

因此,它会自动适应任何小于容器最大宽度的屏幕,并在屏幕更宽时保持固定大小(就像几乎所有台式机和笔记本电脑一样)。


-1

3
欢迎提供解决方案的链接,但请确保您的答案在没有链接的情况下依然有用:添加链接周围的上下文,以便其他用户了解它的存在意义和作用,然后引用链接页面上最相关的部分,以防目标页面不可用。 只包含链接的答案可能会被删除。 - Samuel Liew

-1

我没有看到任何关于CSS flex属性的答案,但它也可以非常有用。


8
你能详细说明一下吗? - Peter Mortensen
你可以在谷歌上找到相关教程。 - Smart Coder

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