1504

我很难理解字体缩放。

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

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

如何使网站上的文本相对于其容器进行缩放?我尝试使用em,但这也无法扩展。

我的理由是,当你调整大小时,我的菜单之类的东西会被压扁,所以我需要减少与容器宽度相关px font-size.menuItem其他元素中的 。(例如,在大桌面上的菜单中,22px完美运行。向下移动到平板电脑宽度,16px更合适。)

我知道我可以添加断点,但我真的希望文本可以缩放以及有额外的断点,否则,我最终会在宽度每减少 100 像素时产生数百个断点来控制文本。

4

38 回答 38

1697

编辑:如果容器不是主体CSS Tricks 涵盖了Fitting Text to a Container中的所有选项。

如果容器是主体,您正在寻找的是Viewport-percentage lengths

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

这些值为:

  • vw(视口宽度的百分比)
  • vh(视口高度的百分比)
  • vi(根元素内联轴方向的视口大小的 1%)
  • vb(根元素块轴方向的视口大小的 1%)
  • vmin(或的较小vwvh
  • vmax(较大的或vwvh

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

使用它看起来像这样:

p {
    font-size: 4vw;
}

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

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

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

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

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

此外,查看 CSS-Tricks 以获得更广泛的外观:视口大小的排版

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

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

另外,请查看这篇文章,该文章也使用了一种称为“熔融引导”的技术来调整行高。CSS 中的领先地位

于 2013-11-06T14:40:46.547 回答
391

But what if the container is not the viewport (body)?

This question is asked in a comment by Alex under the accepted answer.

That fact does not mean vw cannot be used to some extent to size for that container. Now to see any variation at all one has to be assuming that the container in some way is flexible in size. Whether through a direct percentage width or through being 100% minus margins. The point becomes "moot" if the container is always set to, let's say, 200px wide--then just set a font-size that works for that width.

Example 1

With a flexible width container, however, it must be realized that in some way the container is still being sized off the viewport. As such, it is a matter of adjusting a vw setting based off that percentage size difference to the viewport, which means taking into account the sizing of parent wrappers. Take this example:

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

Assuming here the div is a child of the body, it is 50% of that 100% width, which is the viewport size in this basic case. Basically, you want to set a vw that is going to look good to you. As you can see in my comment in the above CSS content, you can "think" through that mathematically with respect to the full viewport size, but you don't need to do that. The text is going to "flex" with the container because the container is flexing with the viewport resizing. UPDATE: here's an example of two differently sized containers.

Example 2

You can help ensure viewport sizing by forcing the calculation based off that. Consider this example:

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

The sizing is still based off viewport, but is in essence set up based off the container size itself.

Should Size of the Container Change Dynamically...

If the sizing of the container element ended up changing dynamically its percentage relationship either via @media breakpoints or via JavaScript, then whatever the base "target" was would need recalculation to maintain the same "relationship" for text sizing.

Take example #1 above. If the div was switched to 25% width by either @media or JavaScript, then at the same time, the font-size would need to adjust in either the media query or by JavaScript to the new calculation of 5vw * .25 = 1.25. This would put the text size at the same size it would have been had the "width" of the original 50% container been reduced by half from viewport sizing, but has now been reduced due to a change in its own percentage calculation.

A Challenge

With the CSS3 calc() function in use, it would become difficult to adjust dynamically, as that function does not work for font-size purposes at this time. So you could not do a pure CSS 3 adjustment if your width is changing on calc(). Of course, a minor adjustment of width for margins may not be enough to warrant any change in font-size, so it may not matter.

于 2013-11-06T16:56:56.457 回答
118

SVG的解决方案:

.resizeme {
  resize: both;
  margin: 0;
  padding: 0;
  height: 75px;
  width: 500px;
  background-color: lightblue;
  overflow: hidden;
}
<div class="resizeme">
  <svg
    width="100%"
    height="100%"
    viewBox="0 0 500 75"
    preserveAspectRatio="xMinYMid meet"
    style="background-color:green"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
        <text
          x="0"
          y="75"
          font-size="75"
          fill="black"
        >█Resize This█&lt;/text>
      </svg>
</div>

使用 SVG 和文本换行的解决方案foreignObject

.resizeme {
  resize: both;
  margin: 0;
  padding: 0;
  height: 200px;
  width: 500px;
  background-color: lightblue;
  overflow: hidden;
}
<div class="resizeme">
  <svg
    width="100%"
    height="100%"
    viewBox="0 0 500 200"
    preserveAspectRatio="xMinYMin meet"
  >
      <foreignObject width="100%" height="100%" xmlns="http://www.w3.org/1999/xhtml">
        <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:lightgreen;">
          <h1>heading</h1>
          <p>Resize the blue box.</p>
        </div>
      </foreignObject>
    </svg>
</div>

于 2015-06-18T16:47:30.207 回答
49

在我的一个项目中,我使用 vw 和 vh 之间的“混合”来根据我的需要调整字体大小,例如:

font-size: calc(3vw + 3vh);

我知道这不能回答 OP 的问题,但也许它可以成为其他任何人的解决方案。

于 2016-03-11T08:30:30.347 回答
43

纯 CSS 解决方案calc(),包含 CSS 单元和数学

这正是 OP 所要求的,但可能会让某人开心。这个答案并不容易,需要在开发人员端进行一些研究。

我终于得到了一个使用calc()不同单元的纯 CSS 解决方案。您将需要对公式有一些基本的数学理解来计算calc().

当我解决这个问题时,我必须得到一个全页宽度的响应式标题,并在 DOM 中填充一些父级。我将在这里使用我的价值观,用你自己的价值观代替它们。

对数学

你会需要:

  • 在某些视口中很好地调整了比例。我使用了 320 像素,因此我得到了 24 像素高和 224 像素宽,所以比率是 9.333... 或 28 / 3
  • 容器宽度,我有padding: 3em和全宽,所以这个到了100wv - 2 * 3em

X 是容器的宽度,所以用你自己的表达式替换它或调整值以获得整页文本。R是您将拥有的比率。您可以通过调整某些视口中的值、检查元素的宽度和高度并用您自己的值替换它们来获得它。此外,它是width / heigth;)

x = 100vw - 2 * 3em = 100vw - 6em
r = 224px/24px = 9.333... = 28 / 3

y = x / r
  = (100vw - 6em) / (28 / 3)
  = (100vw - 6em) * 3 / 28
  = (300vw - 18em) / 28
  = (75vw - 4.5rem) / 7

砰!有效!我写

font-size: calc((75vw - 4.5rem) / 7)

到我的标题,它在每个视口中都进行了很好的调整。

但它是如何工作的?

我们需要一些常量。100vw表示视口的全宽,我的目标是建立带有一些填充的全宽标题。

比例。在一个视口中获得宽度和高度让我可以使用比率,并且通过比率我知道在其他视口宽度中的高度应该是多少。手动计算它们会花费大量时间,并且至少会占用大量带宽,因此这不是一个好的答案。

结论

我想知道为什么没有人弄清楚这一点,有些人甚至说这不可能用 CSS 来修补。我不喜欢在调整元素时使用 JavaScript,所以我不接受 JavaScript(忘记 jQuery)的答案,而无需深入挖掘。总而言之,这很好,这是在网站设计中实现纯 CSS 的一步。

对于我的文本中的任何不寻常的约定,我深表歉意,我不是英语母语人士,而且对编写 Stack Overflow 答案也很陌生。

还应该注意的是,我们在某些浏览器中有邪恶的滚动条。例如,在使用 Firefox 时,我注意到这100vw意味着视口的全宽,在滚动条下延伸(内容无法展开!),因此全宽文本必须仔细设置边距,并且最好在许多浏览器和设备上进行测试。

于 2016-09-01T10:27:27.000 回答
28

这个问题有一个很大的哲学。

最简单的做法是为 body 赋予一定的字体大小(我推荐 10),然后所有其他元素的字体都为emor rem。我会给你一个例子来理解这些单位。 Em总是相对于它的父母:

body{font-size: 10px;}
.menu{font-size: 2em;} /* That means 2*10 pixels  = 20 pixels */
.menu li{font-size: 1.5em;} /* That means 1.5*20 pixels = 30 pixels */

Rem总是相对于身体:

body{font-size: 10px;}
.menu{font-size: 2rem;} /* That means 2*10 pixels = 20 pixels */
.menu li{font-size: 1.5rem;} /* that means 1.5*10 pixels = 15 pixels */

然后你可以创建一个脚本来修改相对于你的容器宽度的字体大小。但这不是我推荐的。因为例如在一个 900 像素宽度的容器中,您将拥有一个p字体大小为 12 像素的元素。根据您的想法,这将成为一个 300 像素宽、4 像素字体大小的容器。必须有一个下限。

其他解决方案是使用媒体查询,以便您可以为不同的宽度设置字体。

但我推荐的解决方案是使用一个可以帮助您的 JavaScript 库。还有我目前发现的fittext.js 。

于 2013-11-11T10:01:45.977 回答
26

这是功能:

document.body.setScaledFont = function(f) {
  var s = this.offsetWidth, fs = s * f;
  this.style.fontSize = fs + '%';
  return this
};

然后将所有文档子元素字体大小转换为em's 或%.

然后将类似这样的内容添加到您的代码中以设置基本字体大小。

document.body.setScaledFont(0.35);
window.onresize = function() {
    document.body.setScaledFont(0.35);
}

http://jsfiddle.net/0tpvccjt/

于 2014-01-07T09:43:49.033 回答
23

有一种方法可以在没有JavaScript 的情况下做到这一点!

您可以使用内联 SVG 图像。如果它是内联的,您可以在 SVG 上使用 CSS。您必须记住,使用此方法意味着您的 SVG 图像将响应其容器大小。

尝试使用以下解决方案...

HTML

<div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360.96 358.98" >
      <text>SAVE $500</text>
  </svg>
</div>

CSS

div {
  width: 50%; /* Set your container width */
  height: 50%; /* Set your container height */

}

svg {
  width: 100%;
  height: auto;

}

text {
  transform: translate(40px, 202px);
  font-size: 62px;
  fill: #000;
}

示例: https ://jsfiddle.net/k8L4xLLa/32/

想要更华丽的东西吗?

SVG 图像还允许你用形状和垃圾做很酷的东西。看看这个可扩展文本的伟大用例......

https://jsfiddle.net/k8L4xLLa/14/

于 2018-03-13T15:48:49.540 回答
15

这可能不是超级实用,但是如果您希望字体成为父级的直接功能,而无需任何 JavaScript 侦听/循环(间隔)来读取 div/page 的大小,有一种方法可以做到. 框架。

iframe 中的任何内容都会将 iframe 的大小视为视口的大小。所以诀窍是只制作一个 iframe,其宽度是您希望文本的最大宽度,其高度等于最大高度 * 特定文本的纵横比。

撇开视口单位不能同时出现在文本的父单位旁边的限制(例如,让 % 大小表现得像其他人一样),视口单位确实提供了一个非常强大的工具:能够获得最小/最大尺寸. 你不能在其他任何地方这样做 - 你不能说......让这个 div 的高度成为父 * 东西的宽度。

话虽如此,诀窍是使用 vmin,并设置 iframe 大小,以便 [fraction] * total height 当高度是限制尺寸时是一个很好的字体大小,而 [fraction] * total width 当宽度是限制维度。这就是为什么高度必须是宽度和纵横比的乘积。

对于我的特定示例,您有

.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 只是我的自定义点击拖动功能。

于 2015-04-12T19:22:28.423 回答
9

使用vw, em& co. 肯定有效,但 IMO 它总是需要人工进行微调。

这是我刚刚根据@tnt-rox 的回答编写的一个脚本,它试图自动化人类的触摸:

$('#controller').click(function(){
    $('h2').each(function(){
        var
            $el = $(this),
            max = $el.get(0),
            el = null
        ;
        max =
            max
            ? max.offsetWidth
            : 320
        ;
        $el.css({
            'font-size': '1em',
            'display': 'inline',
        });
        el = $el.get(0);

        el.get_float = function(){
            var
                fs = 0
            ;
            if (this.style && this.style.fontSize) {
                fs = parseFloat(this.style.fontSize.replace(/([\d\.]+)em/g, '$1'));
            }
            return fs;
        };

        el.bigger = function(){
            this.style.fontSize = (this.get_float() + 0.1) + 'em';
        };

        while (el.offsetWidth < max) {
            el.bigger();
        }

        // Finishing touch.
        $el.css({
            'font-size': ((el.get_float() -0.1) +'em'),
            'line-height': 'normal',
            'display': '',
        });
    });  // end of (each)
});    // end of (font scaling test)
div {
  width: 50%;
  background-color: tomato;
  font-family: 'Arial';
}

h2 {
  white-space: nowrap;
}

h2:nth-child(2) {
  font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="button" id="controller" value="Apply" />
<div>
  <h2>Lorem ipsum dolor</h2>
  <h2>Test String</h2>
  <h2>Sweet Concatenation</h2>
  <h2>Font Scaling</h2>
</div>

它基本上将字体大小减小到1em然后开始增加 0.1 直到达到最大宽度。

JSFiddle

于 2017-08-06T12:54:38.107 回答
8

100% 是相对于基本字体大小的,如果您没有设置它,它将是浏览器的用户代理默认值。

为了获得您想要的效果,我将使用一段 JavaScript 代码来调整相对于窗口尺寸的基本字体大小。

于 2013-04-17T09:42:36.477 回答
7

My own solution, jQuery-based, works by gradually increasing the font size until the container gets a big increase in height (meaning it got a line break).

It's pretty simple, but works fairly well, and it is very easy to use. You don't have to know anything about the font being used, everything is taken care of by the browser.

You can play with it on http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

The magic happens here:

var setMaxTextSize=function(jElement) {
    // Get and set the font size into data for reuse upon resize
    var fontSize=parseInt(jElement.data(quickFitFontSizeData)) || parseInt(jElement.css("font-size"));
    jElement.data(quickFitFontSizeData, fontSize);

    // Gradually increase font size until the element gets a big increase in height (i.e. line break)
    var i = 0;
    var previousHeight;
    do
    {
        previousHeight=jElement.height();
        jElement.css("font-size", "" + (++fontSize) + "px");
    }
    while(i++ < 300 && jElement.height()-previousHeight < fontSize/2)

    // Finally, go back before the increase in height and set the element as resized by adding quickFitSetClass
    fontSize -= 1;
    jElement.addClass(quickFitSetClass).css("font-size", "" + fontSize + "px");

    return fontSize;
};
于 2015-03-26T16:35:38.943 回答
7

从艺术上讲,如果您需要在相同宽度内放置两行或多行文本,而不管它们的字符数如何,那么您有很好的选择。

最好找到一个动态的解决方案,这样无论输入什么文本,我们都会得到一个很好的显示。

让我们看看我们如何接近。

var els     = document.querySelectorAll(".divtext"),
refWidth    = els[0].clientWidth,
refFontSize = parseFloat(window.getComputedStyle(els[0],null)
                               .getPropertyValue("font-size"));

els.forEach((el,i) => el.style.fontSize = refFontSize * refWidth / els[i].clientWidth + "px")
#container {
  display: inline-block;
  background-color: black;
  padding: 0.6vw 1.2vw;
}
.divtext {
  display: table;
  color: white;
  font-family: impact;
  font-size: 4.5vw;
}
<div id="container">
  <div class="divtext">THIS IS JUST AN</div>
  <div class="divtext">EXAMPLE</div>
  <div class="divtext">TO SHOW YOU WHAT</div>
  <div class="divtext">YOU WANT</div>
</div>

我们所做的只是获取第一行的宽度(els[0].clientWidth)和字体大小(parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size")))作为参考,然后相应地计算后续行的字体大小。

于 2019-12-02T19:17:34.043 回答
7

使用 CSS 变量

还没有人提到 CSS 变量,这种方法对我来说效果最好,所以:

假设您的页面上有一个列,它是移动用户屏幕宽度的 100%,但宽度为max-width800 像素,因此在桌面上,该列的两侧都有一些空间。将其放在页面顶部:

<script> document.documentElement.style.setProperty('--column-width', Math.min(window.innerWidth, 800)+'px'); </script>

现在您可以使用该变量(而不是内置vw单位)来设置字体的大小。例如

p {
  font-size: calc( var(--column-width) / 100 );
}

这不是CSS 方法,但非常接近。

于 2018-10-09T10:04:35.123 回答
6

试试http://simplefocus.com/flowtype/。这是我用于我的网站的内容,并且效果很好。

于 2013-11-08T22:21:49.757 回答
6

您可能正在寻找这样的东西:

http://jsfiddle.net/sijav/dGsC9/4/
http://fiddle.jshell.net/sijav/dGsC9/4/show/

我使用了 flowtype,它运行良好(但它是 JavaScript 而不是纯 CSS 解决方案):

$('body').flowtype({
    minFont: 10,
    maxFont: 40,
    minimum: 500,
    maximum: 1200,
    fontRatio: 70
});
于 2013-11-10T11:33:05.427 回答
6

在你的 CSS 中,尝试在底部添加这个,改变 320 像素的宽度,让你的设计开始崩溃:

@media only screen and (max-width: 320px) {
  body { font-size: 1em; }
}

然后根据需要在“px”或“em”中给出字体大小。

于 2013-08-01T11:30:31.587 回答
6

我准备了一个使用 CSS 转换而不是字体大小的简单缩放函数。您可以在任何容器内使用它,您不必设置媒体查询等 :)

博客文章: 全宽 CSS 和 JS 可伸缩标题

编码:

function scaleHeader() {
  var scalable = document.querySelectorAll('.scale--js');
  var margin = 10;
  for (var i = 0; i < scalable.length; i++) {
    var scalableContainer = scalable[i].parentNode;
    scalable[i].style.transform = 'scale(1)';
    var scalableContainerWidth = scalableContainer.offsetWidth - margin;
    var scalableWidth = scalable[i].offsetWidth;
    scalable[i].style.transform = 'scale(' + scalableContainerWidth / scalableWidth + ')';
    scalableContainer.style.height = scalable[i].getBoundingClientRect().height + 'px';
  }
}

工作演示: https ://codepen.io/maciejkorsan/pen/BWLryj

于 2017-03-07T11:03:32.337 回答
6

此 Web 组件更改字体大小,以便内部文本宽度与容器宽度匹配。检查演示

你可以像这样使用它:

<full-width-text>Lorem Ipsum</full-width-text>
于 2016-10-30T14:52:22.887 回答
5

我的问题类似,但与标题内的缩放文本有关。我尝试了 Fit Font,但我需要切换压缩器以获得任何结果,因为它解决了一个稍微不同的问题,Text Flow 也是如此。

所以我写了我自己的小插件来减小字体大小以适应容器,假设你有overflow: hiddenwhite-space: nowrap这样即使将字体减小到最小也不允许显示完整的标题,它只会切断它可以显示的内容。

(function($) {

  // Reduces the size of text in the element to fit the parent.
  $.fn.reduceTextSize = function(options) {
    options = $.extend({
      minFontSize: 10
    }, options);

    function checkWidth(em) {
      var $em = $(em);
      var oldPosition = $em.css('position');
      $em.css('position', 'absolute');
      var width = $em.width();
      $em.css('position', oldPosition);
      return width;
    }

    return this.each(function(){
      var $this = $(this);
      var $parent = $this.parent();
      var prevFontSize;
      while (checkWidth($this) > $parent.width()) {
        var currentFontSize = parseInt($this.css('font-size').replace('px', ''));
        // Stop looping if min font size reached, or font size did not change last iteration.
        if (isNaN(currentFontSize) || currentFontSize <= options.minFontSize ||
            prevFontSize && prevFontSize == currentFontSize) {
          break;
        }
        prevFontSize = currentFontSize;
        $this.css('font-size', (currentFontSize - 1) + 'px');
      }
    });
  };
})(jQuery);
于 2015-12-19T01:40:46.577 回答
4

我非常沮丧地尝试实现类似紧凑的文本换行,所以我最终使用了一种基于画布的方法,但没有成功尝试其他方法。我的目标看起来像附件,结果(对我来说)非常困难。希望有一天我们会有一种简单的纯 CSS 方式来做这件事。这种方法的缺点是文本被视为更像图像,但对于某些用例来说这很好。

https://codesandbox.io/s/create-a-canvas-tightly-holding-a-word-st2h1?file=/index.html

此图像是四个全出血画布的 CSS 网格布局的屏幕截图。

在此处输入图像描述

于 2020-08-04T14:52:56.433 回答
4

尝试使用fitText插件,因为视口大小不是这个问题的解决方案。

只需添加库:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

并通过设置文本系数来更改字体大小:

$("#text_div").fitText(0.8);

您可以设置文本的最大值和最小值:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });
于 2017-07-06T14:39:18.143 回答
3

始终让您的元素具有此属性:

JavaScript:element.style.fontSize = "100%";

或者

CSS:style = "font-size: 100%;"

当你进入全屏时,你应该已经计算了一个比例变量(比例 > 1 或比例 = 1)。然后,全屏:

document.body.style.fontSize = (scale * 100) + "%";

它适用于很少的代码。

于 2016-09-19T20:19:32.400 回答
3

这对我有用:

我尝试根据设置“font-size: 10px”获得的宽度/高度来近似字体大小。基本上,这个想法是“如果我有 20 像素宽和 11 像素高且 `font-size: 10px`,那么计算一个 50 像素宽和 30 像素高的容器的最大字体大小是多少?”

答案是双比例系统:

{ 20:10=50:X, 11:10=30:Y } = { X= (10*50)/20, Y= (10*30)/11 }

现在 X 是一个与宽度匹配的字体大小,而 Y 是一个与高度匹配的字体大小;取最小值

function getMaxFontSizeApprox(el){
    var fontSize = 10;
    var p = el.parentNode;

    var parent_h = p.offsetHeight ? p.offsetHeight : p.style.pixelHeight;
    if(!parent_h)
        parent_h = 0;

    var parent_w = p.offsetHeight ? p.offsetWidth : p.style.pixelWidth;
    if(!parent_w)
        parent_w = 0;

    el.style.fontSize = fontSize + "px";

    var el_h = el.offsetHeight ? el.offsetHeight : el.style.pixelHeight;
    if(!el_h)
        el_h = 0;

    var el_w = el.offsetHeight ? el.offsetWidth : el.style.pixelWidth;
    if(!el_w)
        el_w = 0;

    // 0.5 is the error on the measure that JavaScript does
    // if the real measure had been 12.49 px => JavaScript would have said 12px
    // so we think about the worst case when could have, we add 0.5 to 
    // compensate the round error
    var fs1 = (fontSize*(parent_w + 0.5))/(el_w + 0.5);
    var fs2 = (fontSize*(parent_h) + 0.5)/(el_h + 0.5);

    fontSize = Math.floor(Math.min(fs1,fs2));
    el.style.fontSize = fontSize + "px";
    return fontSize;
}

注意:函数的参数必须是 span 元素或小于其父元素的元素,否则如果子元素和父元素具有相同的宽度/高度,则函数将失败。

于 2018-01-12T21:11:19.930 回答
3

看看我的代码。它使那里的font size smaller任何fit东西。

但我认为这不会带来良好的用户体验

var containerWidth = $("#ui-id-2").width();
var items = $(".quickSearchAutocomplete .ui-menu-item");
var fontSize = 16;

items.each(function(){
    // Displaying a value depends sometimes on your case. You may make it block or inline-table instead of inline-block or whatever value that make the div take overflow width.
    $(this).css({"whiteSpace": "nowrap", "display": "inline-block"});
    while ($(this).width() > containerWidth){
         console.log("$(this).width()" + $(this).width() + "containerWidth" + containerWidth)
         $(this).css("font-size", fontSize -= 0.5);
    }
});

结果

于 2017-03-16T09:10:01.420 回答
3

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

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();
于 2017-10-17T07:22:34.020 回答
3

HTML

<div style="height:100px; width:200px;">
  <div id='qwe'>
    test
  </div>
</div>

最大化字体大小的 JavaScript 代码:

var fontSize, maxHeight, maxWidth, textElement, parentElement;
textElement = document.getElementById('qwe');
parentElement = textElement.parentElement;    
maxHeight = parentElement.clientHeight;
maxWidth = parentElement.clientWidth;
fontSize = maxHeight;
var minFS = 3, maxFS = fontSize;
while (fontSize != minFS) {
  textElement.style.fontSize = `${fontSize}px`;
  if (textElement.offsetHeight < maxHeight && textElement.offsetWidth <= maxWidth) {
    minFS = fontSize;
  } else{
    maxFS = fontSize;
  }
  fontSize = Math.floor((minFS + maxFS)/2);
}
textElement.style.fontSize = `${minFS}px`;
于 2019-08-21T12:13:55.117 回答
2

如果它对任何人都有帮助,这个线程中的大多数解决方案都是将文本包装成多行,形式 e。

但后来我发现了这个,它起作用了:

https://github.com/chunksnbits/jquery-quickfit

示例用法:

$('.someText').quickfit({max:50,tolerance:.4})

于 2017-06-14T06:26:23.710 回答
2

作为 JavaScript 后备(或您唯一的解决方案),您可以使用我的jQuery Scalem 插件reference,它允许您通过传递选项相对于父元素(容器)进行缩放。

于 2017-01-05T07:33:30.257 回答
1

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

于 2018-07-27T17:34:26.990 回答
1

为了使字体大小适合它的容器,而不是窗口,请参阅resizeFont()我在这个问题中共享的功能(其他答案的组合,其中大部分已经在这里链接)。它是使用触发的window.addEventListener('resize', resizeFont);

Vanilla JavaScript:调整字体大小以适应容器

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%获得正确的结果。

于 2017-11-08T14:27:41.930 回答
0

那这个呢?
将父级的字体大小设置为等于其宽度,然后使用百分比作为文本元素字体大小。

.element {
    width: 400px;
    font-size: 400px; /* equal to width */
}

.text {
    width: 10%;  /* will be 40px */
}

当您处理图标时,我发现这非常容易,但也适用于文本。

/* start of styling */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.box {
  display: block;
  background: cornflowerblue;
  height: max-content;
  margin-bottom: 32px;
}


/* end of styling */

.box p {
  font-size: 20%;
}
<div class="box" style="width: 400px; font-size: 400px">
  <p>Text</p>
</div>

<div class="box" style="width: 128px; font-size: 128px">
  <p>Text</p>
</div>


<div class="box" style="width: 10vw; font-size: 10vw">
  <p>Text</p>
</div>

<div class="box" style="width: 64px; font-size: 64px">
  <p>Text</p>
</div>

于 2022-01-01T22:07:30.380 回答
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;
    }
}
于 2018-09-11T14:49:27.803 回答
0

纯CSS在某种程度上是可能的。

.auto-sized-text {
    content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1.3em' width='10em'><text x='0' y='0.9em' fill='red'>Here is a resizing text</text></svg>");
    
    background-color: rgba(0,0,0,0.06);
    animation: grow 2s infinite alternate both;
}

@keyframes grow {
  from { width: 100px; }
  to { width: 300px; }
}
<div class="auto-sized-text">
</div>

解释

contentrule设置元素的内容,它可以是图像的 URL,包括 SVG 图像。SVG 图像可以包含文本,所以基本上你有一个带有文本的背景图像,它会根据其父级的大小调整大小。您也可以使用background-image属性,但与content它不同的是它不会影响元素的布局,因此您需要定义父元素的大小。

这种方法的问题是,您需要在 SVG 中定义文本的颜色、大小和位置。他们不会从父母那里继承。但是你可以通过 Sass 和 Less 变得聪明。此解决方案也可能存在可访问性问题。

我不建议在任何地方使用它。但它在某些情况下应该相当有用。

于 2021-09-16T00:12:39.493 回答
0

这是一个纯 CSS 解决方案,您承认断点是必要的,但也需要文本缩放:

我知道我可以添加断点,但我真的希望文本可以缩放以及有额外的断点,否则......

这是一种使用方法:

  1. 自定义属性
  2. 断点的媒体查询
  3. clamp()2022 年 2 月的浏览器支持率相当不错,达到 93%)
  4. calc()

如果可以使用一个通用缩放因子来控制每个屏幕容器内的所有max-width文本缩放,那么您需要做的就是按比例缩放自定义属性max-width,并将该因子应用于 1计算

基本设置如下所示:

:root {
  --scaling-factor: 1
}

.parent {
  font-size: 30px
}

.largest {
  font-size: clamp(60%, calc(var(--scaling-factor) * 100%), 100%); 
}

.middle {
  font-size: clamp(60%, calc(var(--scaling-factor) * 85%), 100%); 
}

.smallest {
  font-size: clamp(60%, calc(var(--scaling-factor) * 70%), 100%); 
}

然后嵌套您的媒体查询,如下所示(或您的断点所需的任何内容):

@media (max-width: 1200px) {
  :root {
    --scaling-factor: 0.9
  }
  @media (max-width: 800px) {
    :root {
      --scaling-factor: 0.8
    }
    @media (max-width: 600px) {
      :root {
        --scaling-factor: 0.5 /* nope, because the font-size is floored at 60% thanks to clamp() */
      }
    }
  }
}

这可以最大限度地减少您的媒体查询标记。

优点

  1. 一个自定义属性控制所有缩放...无需为每个媒体断点添加多个声明
  2. 的使用设置了应该是clamp()什么的下限,所以你确保你的文本永远不会太小(这里的下限是父母的 60% )font-sizefont-size

请参阅此 JSFiddle以获取演示。调整窗口大小,直到最小宽度,段落都相同font-size

于 2022-02-28T17:05:23.633 回答
-1

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

.specialText{
    font-size: 2.4vw;
}

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

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

于 2016-06-28T04:34:28.473 回答
-2

我刚刚创建了一个演示如何做到这一点。它使用transform:scale()一些监视元素调整大小的 JS 来实现这一点。很好地满足我的需求。

于 2020-07-06T14:03:00.937 回答
-2

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

真正的答案在于transform 属性允许您通过倾斜、旋转、平移或缩放来直观地操作元素:

https://css-tricks.com/almanac/properties/t/transform/

于 2018-11-02T18:32:36.143 回答