我很难理解字体缩放。

我目前有一个字体大小为100%的网站。但这是100%的吗?这似乎是在16个像素处计算出来的。

我的印象是,100%会以某种方式指代浏览器窗口的大小,但显然不是因为无论窗口大小调整为移动宽度还是宽屏桌面,都是16像素。

如何使站点上的文本与其容器相关?我尝试过使用它们,但这也无法扩展。

我的理由是,当你调整大小时,像我的菜单这样的东西会变得压扁,所以我需要减少.menuItem等元素相对于容器宽度的px字体大小。(例如,在大型桌面上的菜单中,22px的效果非常好。向下移动到平板电脑宽度,16px更合适。)

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


当前回答

这可能不太实用,但如果您希望字体是父级的直接函数,而不需要任何JavaScript侦听/循环(interval)来读取div/页面的大小,那么有一种方法可以做到。Iframes。

iframe中的任何内容都会将iframe的大小视为视口的大小。因此,诀窍是创建一个iframe,其宽度是您希望文本达到的最大宽度,其高度等于特定文本的最大高度*纵横比。

抛开视口单位不能与文本的父单位一起出现的限制(如中所示,具有与其他所有单位相同的%大小),视口单位确实提供了一个非常强大的工具:能够获得最小/最大尺寸。你不能在其他地方这样做-你不能说。。。使这个div的高度等于父对象的宽度。

也就是说,诀窍是使用vmin,并设置iframe大小,当高度是限制维度时,[fract]*总高度是一个好的字体大小,而当宽度是限制维度的时候,[fract]*总宽度。这就是为什么高度必须是宽度和纵横比的乘积。

对于我的特定示例

.main iframe{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: calc(3.5 * 100%);
  background: rgba(0, 0, 0, 0);
  border-style: none;
  transform: translate3d(-50%, -50%, 0);
}

这种方法的一个小烦恼是,您必须手动设置iframe的CSS。如果您附加整个CSS文件,这将占用许多文本区域的大量带宽。所以,我所做的是直接从CSS中附加我想要的规则。

var rule = document.styleSheets[1].rules[4];
var iDoc = document.querySelector('iframe').contentDocument;
iDoc.styleSheets[0].insertRule(rule.cssText);

您可以编写一个小函数来获取CSS规则/所有影响文本区域的CSS规则。

如果没有一些循环/聆听JavaScript,我想不出另一种方法。真正的解决方案是让浏览器提供一种根据父容器缩放文本的方式,并提供相同的vmin/vmax类型功能。

JSFiddle:https://jsfiddle.net/0jr7rrgm/3/(单击一次可将红色方块锁定在鼠标上,再次单击可释放)

大部分JavaScript都是我自定义的点击拖动功能。

其他回答

如果容器不是主体,CSS技巧将覆盖“将文本适配到容器”中的所有选项。

如果容器是主体,则要查找的是视口百分比长度:

视口百分比长度与初始包含块的大小相关。当初始包含块的高度或宽度更改时,将相应地缩放它们。但是,当根元素上的溢出值为auto时,假设不存在任何滚动条。

值为:

vw(视口宽度的%)vh(视口高度的%)vi(根元素内联轴方向上视口大小的1%)vb(根元素块轴方向上视口大小的1%)vmin(vw或vh中较小的一个)vmax(较大或vw或vh)

1v*等于初始包含块的1%。

使用它看起来像这样:

p {
    font-size: 4vw;
}

如您所见,当视口宽度增加时,字体大小也会增加,而无需使用媒体查询。

这些值是一个大小调整单位,就像px或em一样,因此它们也可以用于调整其他元素的大小,例如宽度、边距或填充。

浏览器支持非常好,但您可能需要一个后备方案,例如:

p {
    font-size: 16px;
    font-size: 4vw;
}

查看支持统计信息:http://caniuse.com/#feat=viewport-单位。

此外,请查看CSS技巧以获得更广泛的外观:视口大小的版式

这是一篇关于设置最小/最大尺寸并对尺寸进行更多控制的好文章:精确控制响应式印刷

下面是一篇关于使用calc()设置大小以使文本填充视口的文章:http://codepen.io/CrocoDillon/pen/fBJxu

此外,请查看这篇文章,它使用了一种称为“熔化引线”的技术来调整线条高度。CSS中的熔融铅

但如果容器不是视口(主体)呢?

亚历克斯在2507rkt3的回答下的评论中提出了这个问题。

这一事实并不意味着大众汽车在一定程度上不能用于该集装箱的尺寸。现在要看到任何变化,我们必须假设容器在某种程度上是灵活的。无论是通过直接百分比宽度还是通过100%减去边距。如果容器始终设置为200px宽,那么这一点就变得“无意义”了——然后只需设置一个适用于该宽度的字体大小。

示例1

然而,对于灵活宽度的容器,必须认识到,在某种程度上,容器的大小仍在视口之外。因此,需要根据视口的百分比大小差异调整vw设置,这意味着要考虑父包装的大小。举个例子:

div {
    width: 50%;
    border: 1px solid black;
    margin: 20px;
    font-size: 16px;
    /* 100 = viewport width, as 1vw = 1/100th of that
       So if the container is 50% of viewport (as here)
       then factor that into how you want it to size.
       Let's say you like 5vw if it were the whole width,
       then for this container, size it at 2.5vw (5 * .5 [i.e. 50%])
    */
    font-size: 2.5vw;
}

假设这里的div是主体的子对象,它是100%宽度的50%,在这个基本情况下是视口大小。基本上,你想设定一个对你来说很好的大众汽车。正如我在上面的CSS内容中的评论中所看到的,你可以从数学上考虑整个视口的大小,但你不需要这样做。文本将随着容器“伸缩”,因为容器会随着视口大小的调整而伸缩。下面是两个不同大小的容器的示例。

示例2

通过强制基于此进行计算,可以帮助确保视口大小。考虑以下示例:

html {width: 100%;} /* Force 'html' to be viewport width */
body {width: 150%; } /* Overflow the body */

div {
    width: 50%;
    border: 1px solid black;
    margin: 20px;
    font-size: 16px;
    /* 100 = viewport width, as 1vw = 1/100th of that
       Here, the body is 150% of viewport, but the container is 50%
       of viewport, so both parents factor  into how you want it to size.
       Let's say you like 5vw if it were the whole width,
       then for this container, size it at 3.75vw
       (5 * 1.5 [i.e. 150%]) * .5 [i.e. 50%]
    */
    font-size: 3.75vw;
}

大小仍然基于视口外,但本质上是基于容器大小本身设置的。

如果容器的大小动态变化。。。

如果容器元素的大小最终通过@media断点或JavaScript动态改变了其百分比关系,那么无论基础“目标”是什么,都需要重新计算以保持文本大小的相同“关系”。

以上面的示例#1为例。如果div被@media或JavaScript切换为25%宽度,那么同时,字体大小需要在媒体查询或JavaScript中调整为5vw*.25=1.25的新计算值。这将使文本大小与原始50%容器的“宽度”从视口大小减小一半时的大小相同,但现在由于其自身百分比计算的变化而减小。

挑战

使用CSS calc()函数时,很难动态调整,因为该函数此时不适用于字体大小。因此,如果宽度在calc()上发生变化,则不能进行纯CSS调整。当然,对页边空白宽度的轻微调整可能不足以保证字体大小的任何改变,因此这可能无关紧要。

我刚刚创建了一个演示如何做到这一点。它使用transform:scale()来实现这一点,并使用一些监视元素大小调整的JS。非常适合我的需要。

我想喜欢接受的答案,但从根本上说,符合我的标准的答案都需要使用图书馆。我决定编写一个非常适合我的简单函数,而不是让自己熟悉另一个库,然后找出如何使用它并准备在它不工作时进行调试。

理论:

传入需要匹配的字符串传入要从中继承文本样式的父级可选地传入自定义属性(例如,您将从中继承字体和其他属性的类/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;
  };

use:

    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;`;  

如果问题是宽屏桌面上的字体太大,我认为最简单的CSS方法应该是这样的(假设包装器最大宽度为1000像素)

.specialText{
    font-size: 2.4vw;
}

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

因此,它可以自动调整大小,以适应任何小于容器最大宽度的屏幕,当屏幕更宽时(几乎所有台式机和笔记本电脑),它可以固定大小。