简体   繁体   English

基于容器大小的字体缩放

[英]Font scaling based on size of container

I'm having a hard time getting my head around font scaling.我很难理解字体缩放。

I currently have a website with a body font-size of 100%.我目前有一个正文font-size为 100% 的网站。 100% of what though? 100% 的是什么? This seems to compute out at 16 pixels.这似乎以 16 像素计算出来。

I was under the impression that 100% would somehow refer to the size of the browser window, but apparently not because it's always 16 pixels whether the window is resized down to a mobile width or full-blown widescreen desktop.我的印象是 100% 会以某种方式引用浏览器 window 的大小,但显然不是,因为无论将 window 调整为移动宽度还是全屏宽屏桌面,它始终为 16 像素。

How can I make the text on my site scale in relation to its container?如何使网站上的文本相对于其容器缩放? I tried using em , but this doesn't scale either.我尝试使用em ,但这也无法扩展。

My reasoning is that things like my menu become squished when you resize, so I need to reduce the px font-size of .menuItem among other elements in relation to the width of the container.我的理由是,当您调整大小时,像我的菜单这样的东西会被压扁,所以我需要减少.menuItempx font-size以及与容器宽度相关的其他元素。 (For example, in the menu on a large desktop, 22px works perfectly. Move down to tablet width and 16px is more appropriate.) (例如,在大型桌面上的菜单中, 22px效果很好。向下移动到平板电脑宽度, 16px更合适。)

I'm aware I can add breakpoints, but I really want the text to scale as well as having extra breakpoints, otherwise, I'll end up with hundreds of breakpoints for every 100pixels decrease in width to control the text.我知道我可以添加断点,但我真的希望文本能够缩放以及有额外的断点,否则,我将在宽度每减少 100 像素时得到数百个断点来控制文本。

If the container is not the body, CSS Tricks covers all of your options in Fitting Text to a Container .如果容器不是主体,CSS Tricks 涵盖了将文本放入容器中的所有选项。

If the container is the body, what you are looking for is Viewport-percentage lengths :如果容器是主体,您正在寻找的是Viewport-percentage lengths

The viewport-percentage lengths are relative to the size of the initial containing block .视口百分比长度初始包含块的大小有关。 When the height or width of the initial containing block is changed, they are scaled accordingly.当初始包含块的高度或宽度发生变化时,它们会相应地缩放。 However, when the value of overflow on the root element is auto, any scroll bars are assumed not to exist.但是,当根元素上的溢出值为 auto 时,假定不存在任何滚动条。

The values are:这些值为:

  • vw (% of the viewport width) vw (视口宽度的百分比)
  • vh (% of the viewport height) vh (视口高度的百分比)
  • vi (1% of the viewport size in the direction of the root element's inline axis) vi (根元素内联轴方向的视口大小的 1%)
  • vb (1% of the viewport size in the direction of the root element's block axis) vb (根元素块轴方向的视口大小的 1%)
  • vmin (the smaller of vw or vh ) vmin (较小的vwvh
  • vmax (the larger or vw or vh ) vmax (较大的或vwvh

1 v* is equal to 1% of the initial containing block. 1 v* 等于初始包含块的 1%。

Using it looks like this:使用它看起来像这样:

p {
    font-size: 4vw;
}

As you can see, when the viewport width increases, so do the font-size , without needing to use media queries.如您所见,当视口宽度增加时, font-size也会增加,而无需使用媒体查询。

These values are a sizing unit, just like px or em , so they can be used to size other elements as well, such as width, margin, or padding.这些值是一个大小单位,就像pxem一样,因此它们也可以用于调整其他元素的大小,例如宽度、边距或填充。

Browser support is pretty good, but you'll likely need a fallback, such as:浏览器支持非常好,但您可能需要一个备用方案,例如:

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

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

Also, check out CSS-Tricks for a broader look: Viewport Sized Typography此外,查看 CSS-Tricks 以获得更广泛的外观:视口大小的排版

Here's a nice article about setting minimum/maximum sizes and exercising a bit more control over the sizes: Precise control over responsive typography这是一篇关于设置最小/最大尺寸和对尺寸进行更多控制的好文章: 精确控制响应式排版

And here's an article about setting your size using calc() so that the text fills the viewport: http://codepen.io/CrocoDillon/pen/fBJxu这是一篇关于使用 calc() 设置大小以便文本填充视口的文章:http: //codepen.io/CrocoDillon/pen/fBJxu

Also, please view this article, which uses a technique dubbed 'molten leading' to adjust the line-height as well.另外,请查看这篇文章,该文章也使用了一种称为“熔融引导”的技术来调整行高。 Molten Leading in CSS CSS 中的领先地位

But what if the container is not the viewport (body)?但是如果容器不是视口(主体)呢?

This question is asked in a comment by Alex under the accepted answer .这个问题是 Alex 在接受的答案下的评论中提出的。

That fact does not mean vw cannot be used to some extent to size for that container.这个事实并不意味着vw在某种程度上不能用于该容器的大小。 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.无论是通过直接百分比width还是通过 100% 减去边距。 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.如果容器总是设置为,比如说200px宽,那么这个点就变得“没有意义”——然后只需设置一个适用于该宽度的font-size

Example 1示例 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.因此,需要根据与视口的百分比大小差异来调整vw设置,这意味着要考虑父包装器的大小。 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.假设这里的divbody的一个孩子,它是100%宽度的50% ,这是这个基本情况下的视口大小。 Basically, you want to set a vw that is going to look good to you.基本上,您想设置一个看起来不错的vw 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.正如您在我对上述 CSS 内容的评论中看到的那样,您可以在数学上“思考”关于完整视口大小的问题,但您不需要这样做。 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示例 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.如果容器元素的大小最终通过@media断点或通过 JavaScript 动态改变其百分比关系,那么无论基本“目标”是什么,都需要重新计算以保持文本大小的相同“关系”。

Take example #1 above.以上面的示例 #1 为例。 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 .如果通过@media或 JavaScript 将div切换为25%的宽度,那么同时, font-size需要在媒体查询或 JavaScript 中调整为新的计算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.这将使文本大小与原始50%容器的“宽度”从视口大小减少一半时的大小相同,但现在由于其自身的百分比计算发生变化而减小。

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.使用CSS3 calc()函数时,动态调整会变得很困难,因为此时该函数不适用于font-size So you could not do a pure CSS 3 adjustment if your width is changing on calc() .因此,如果您的宽度在calc()上发生变化,则无法进行纯 CSS 3 调整。 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.当然,对边距宽度的细微调整可能不足以保证font-size发生任何变化,因此可能无关紧要。

Solution with SVG: 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█</text> </svg> </div>

Solution with SVG and text-wrapping using foreignObject : 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>

In one of my projects I use a "mixture" between vw and vh to adjust the font size to my needs, for example:在我的一个项目中,我使用 vw 和 vh 之间的“混合”来根据我的需要调整字体大小,例如:

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

I know this doesn't answer the OP's question, but maybe it can be a solution to anyone else.我知道这不能回答 OP 的问题,但也许它可以成为其他任何人的解决方案。

Pure-CSS solution with calc() , CSS units and math带有calc() 、CSS 单位和数学的纯 CSS 解决方案

This is precisely not what OP asks, but may make someone's day.这正是 OP 所要求的,但可能会让某人开心。 This answer is not spoon-feedingly easy and needs some researching on the developer end.这个答案并不容易,需要在开发人员端进行一些研究。

I came finally to get a pure-CSS solution for this using calc() with different units.我终于使用具有不同单位的calc()获得了一个纯 CSS 解决方案。 You will need some basic mathematical understanding of formulas to work out your expression for calc() .您需要对公式有一些基本的数学理解才能计算出calc()的表达式。

When I worked this out, I had to get a full-page-width responsive header with some padding few parents up in DOM.当我解决这个问题时,我必须得到一个全页宽度的响应式标题,并在 DOM 中填充一些父级。 I'll use my values here, replace them with your own.我将在这里使用我的价值观,用你自己的价值观代替它们。

To mathematics对数学

You will need:你会需要:

  • Nicely adjusted ratio in some viewport.在某些视口中很好地调整了比例。 I used 320 pixels, thus I got 24 pixels high and 224 pixels wide, so the ratio is 9.333... or 28 / 3我使用了 320 像素,因此我得到了 24 像素高和 224 像素宽,所以比率是 9.333... 或 28 / 3
  • The container width, I had padding: 3em and full width so this got to 100wv - 2 * 3em容器宽度,我有padding: 3em和全宽,所以它达到100wv - 2 * 3em

X is the width of container, so replace it with your own expression or adjust the value to get full-page text. X 是容器的宽度,所以用你自己的表达式替换它或调整值以获得整页文本。 R is the ratio you will have. R是你将拥有的比率。 You can get it by adjusting the values in some viewport, inspecting element width and height and replacing them with your own values.您可以通过调整某些视口中的值、检查元素的宽度和高度并用您自己的值替换它们来获得它。 Also, it is width / heigth ;)此外,它是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

And bang!砰! It worked!有效! I wrote我写

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

to my header and it adjusted nicely in every viewport.到我的标题,它在每个视口中都进行了很好的调整。

But how does it work?但它是如何工作的?

We need some constants up here.我们需要一些常量。 100vw means the full width of viewport, and my goal was to establish full-width header with some padding. 100vw表示视口的全宽,我的目标是建立带有一些填充的全宽标题。

The ratio.比例。 Getting a width and height in one viewport got me a ratio to play with, and with ratio I know what the height should be in other viewport width.在一个视口中获得宽度和高度让我可以使用比率,并且通过比率我知道在其他视口宽度中的高度应该是多少。 Calculating them with hand would take plenty of time and at least take lots of bandwidth, so it's not a good answer.手动计算它们会花费大量时间,并且至少会占用大量带宽,因此这不是一个好的答案。

Conclusion结论

I wonder why no-one has figured this out and some people are even telling that this would be impossible to tinker with CSS.我想知道为什么没有人弄清楚这一点,有些人甚至说这不可能用 CSS 来修补。 I don't like to use JavaScript in adjusting elements, so I don't accept JavaScript (and forget about jQuery) answers without digging more.我不喜欢在调整元素时使用 JavaScript,所以我不接受 JavaScript(忘记 jQuery)的答案,而无需深入挖掘。 All in all, it's good that this got figured out and this is one step to pure-CSS implementations in website design.总而言之,这很好,这是在网站设计中实现纯 CSS 的一步。

I apologize of any unusual convention in my text, I'm not native speaker in English and am also quite new to writing Stack Overflow answers.对于我的文本中的任何不寻常的约定,我深表歉意,我不是英语母语人士,而且对编写 Stack Overflow 答案也很陌生。

It should also be noted that we have evil scrollbars in some browsers.还应该注意的是,我们在某些浏览器中有邪恶的滚动条。 For example, when using Firefox I noticed that 100vw means the full width of viewport, extending under scrollbar (where content cannot expand!), so the fullwidth text has to be margined carefully and preferably get tested with many browsers and devices.例如,在使用 Firefox 时,我注意到100vw表示视口的全宽,在滚动条下延伸(内容无法展开!),因此全宽文本必须仔细设置边距,最好在许多浏览器和设备上进行测试。

There is a big philosophy for this issue.这个问题有一个很大的哲学。

The easiest thing to do would be to give a certain font-size to body (I recommend 10), and then all the other element would have their font in em or rem .最简单的做法是给 body 赋予一定的字体大小(我推荐 10),然后所有其他元素的字体都会在emrem中。 I'll give you an example to understand those units.我会给你一个例子来理解这些单位。 Em is always relative to its parent: 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 is always relative to body: Rem总是相对于 body:

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 */

And then you could create a script that would modify font-size relative to your container width.然后你可以创建一个脚本来修改相对于你的容器宽度的字体大小。 But this isn't what I would recommend.但这不是我推荐的。 Because in a 900 pixels width container for example you would have a p element with a 12 pixels font-size let's say.因为例如在一个 900 像素宽度的容器中,您将拥有一个p元素,其字体大小为 12 像素。 And on your idea that would become an 300 pixels wide container at 4 pixels font-size.根据您的想法,这将成为一个 300 像素宽、4 像素字体大小的容器。 There has to be a lower limit.必须有一个下限。

Other solutions would be with media queries, so that you could set font for different widths.其他解决方案是使用媒体查询,以便您可以为不同的宽度设置字体。

But the solutions that I would recommend is to use a JavaScript library that helps you with that.但我推荐的解决方案是使用一个可以帮助您的 JavaScript 库。 And fittext.js that I found so far.还有我目前发现的fittext.js

Here is the function:这是功能:

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

Then convert all your documents child element font sizes to em 's or % .然后将所有文档子元素字体大小转换为em%

Then add something like this to your code to set the base font size.然后将类似这样的内容添加到您的代码中以设置基本字体大小。

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

http://jsfiddle.net/0tpvccjt/ http://jsfiddle.net/0tpvccjt/

There is a way to do this without JavaScript!有一种方法可以在没有JavaScript 的情况下做到这一点!

You can use an inline SVG image.您可以使用内联 SVG 图像。 You can use CSS on an SVG if it is inline.如果它是内联的,您可以在 SVG 上使用 CSS。 You have to remember that using this method means your SVG image will respond to its container size.您必须记住,使用此方法意味着您的 SVG 图像将响应其容器大小。

Try using the following solution...尝试使用以下解决方案...

HTML HTML

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

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

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

Want something more flashy?想要更华丽的东西吗?

SVG images also allow you to do cool stuff with shapes and junk. SVG 图像还允许你用形状和垃圾做很酷的东西。 Check out this great use case for scalable text...看看这个可扩展文本的伟大用例......

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

This may not be super practical, but if you want a font to be a direct function of the parent, without having any JavaScript that listens/loops (interval) to read the size of the div/page, there is a way to do it.这可能不是超级实用,但是如果您希望字体成为父级的直接功能,而无需任何 JavaScript 侦听/循环(间隔)来读取 div/page 的大小,有一种方法可以做到. Iframes.框架。

Anything within the iframe will consider the size of the iframe as the size of the viewport. iframe 中的任何内容都会将 iframe 的大小视为视口的大小。 So the trick is to just make an iframe whose width is the maximum width you want your text to be, and whose height is equal to the maximum height * the particular text's aspect ratio.所以诀窍是只制作一个 iframe,其宽度是您希望文本的最大宽度,其高度等于最大高度 * 特定文本的纵横比。

Setting aside the limitation that viewport units can't also come along side parent units for text (as in, having the % size behave like everyone else), viewport units do provide a very powerful tool: being able to get the minimum/maximum dimension.撇开视口单位不能同时出现在文本的父单位旁边的限制(例如,让 % 大小表现得像其他人一样),视口单位确实提供了一个非常强大的工具:能够获得最小/最大尺寸. You can't do that anywhere else - you can't say...make the height of this div be the width of the parent * something.你不能在其他任何地方这样做 - 你不能说......让这个 div 的高度成为父 * 东西的宽度。

That being said, the trick is to use vmin, and to set the iframe size so that [fraction] * total height is a good font size when the height is the limiting dimension, and [fraction] * total width when the width is the limiting dimension.话虽如此,诀窍是使用 vmin,并设置 iframe 大小,以便 [fraction] * total height 当高度是限制尺寸时是一个很好的字体大小,而 [fraction] * total width 当宽度是限制维度。 This is why the height has to be a product of the width and the aspect ratio.这就是为什么高度必须是宽度和纵横比的乘积。

For my particular example, you have对于我的特定示例,您有

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

The small annoyance with this method is that you have to manually set the CSS of the iframe.这种方法的小烦恼是您必须手动设置 iframe 的 CSS。 If you attach the whole CSS file, that would take up a lot of bandwidth for many text areas.如果附加整个 CSS 文件,则会占用许多文本区域的大量带宽。 So, what I do is attach the rule that I want directly from my CSS.所以,我要做的是直接从我的 CSS 中附加我想要的规则。

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

You can write small function that gets the CSS rule / all CSS rules that would affect the text area.您可以编写小函数来获取 CSS 规则/所有会影响文本区域的 CSS 规则。

I cannot think of another way to do it without having some cycling/listening JavaScript.如果没有一些循环/监听 JavaScript,我想不出另一种方法来做到这一点。 The real solution would be for browsers to provide a way to scale text as a function of the parent container and to also provide the same vmin/vmax type functionality.真正的解决方案是让浏览器提供一种方法来缩放文本作为父容器的功能,提供相同的 vmin/vmax 类型功能。

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (click once to lock the red square to the mouse, and click again to release) JSFiddle: https ://jsfiddle.net/0jr7rrgm/3/(单击一次将红色方块锁定到鼠标,再次单击释放)

Most of the JavaScript in the fiddle is just my custom click-drag function.小提琴中的大部分 JavaScript 只是我的自定义点击拖动功能。

Using vw , em & co.使用vwem & co。 works for sure, but IMO it always needs a human's touch for fine-tuning.肯定有效,但 IMO 它总是需要人工进行微调。

Here's a script I just wrote based on @tnt-rox' answer that tries to automatize that human's touch:这是我刚刚根据@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>

It basically reduces the font-size to 1em and then starts incrementing by 0.1 until it reaches maximum width.它基本上将字体大小减小到1em ,然后开始增加 0.1,直到达到最大宽度。

JSFiddle JSFiddle

Artistically, if you need to fit two or more lines of text within the same width regardless of their character count then you have nice options.从艺术上讲,如果您需要在相同宽度内放置两行或多行文本,而不管它们的字符数如何,那么您有不错的选择。

It's best to find a dynamical solution so whatever text is entered we end up with a nice display.最好找到一个动态的解决方案,这样无论输入什么文本,我们都会得到一个很好的显示。

Let's see how we may approach.让我们看看我们如何接近。

 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>

All we do is to get the width ( els[0].clientWidth ) and the font size ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size")) ) of the first line as a reference and then just calculate the subsequent lines font size accordingly.我们所做的就是获取第一行的宽度( els[0].clientWidth )和字体大小( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size")) )参考,然后相应地计算后续行的字体大小。

100% is relative to the base font size, which, if you haven't set it, would be the browser's user-agent default. 100% 是相对于基本字体大小的,如果您没有设置它,它将是浏览器的用户代理默认值。

To get the effect you're after, I would use a piece of JavaScript code to adjust the base font size relative to the window dimensions.为了获得您想要的效果,我将使用一段 JavaScript 代码来调整相对于窗口尺寸的基本字体大小。

I've prepared a simple scale function using CSS transform instead of font-size.我准备了一个使用 CSS 转换而不是字体大小的简单缩放函数。 You can use it inside of any container, you don't have to set media queries, etc. :)您可以在任何容器内使用它,您不必设置媒体查询等 :)

Blog post: Full width CSS & JS scalable header博客文章: 全宽 CSS 和 JS 可伸缩标题

The code:编码:

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

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

Use CSS Variables使用 CSS 变量

No one has mentioned CSS variables yet, and this approach worked best for me, so:还没有人提到 CSS 变量,这种方法对我来说效果最好,所以:

Let's say you've got a column on your page that is 100% of the width of a mobile user's screen, but has a max-width of 800px, so on desktop there's some space on either side of the column.假设您的页面上有一个列,它是移动用户屏幕宽度的 100%,但max-width为 800 像素,因此在桌面上,该列的两侧都有一些空间。 Put this at the top of your page:将其放在页面顶部:

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

And now you can use that variable (instead of the built-in vw unit) to set the size of your font.现在您可以使用该变量(而不是内置的vw单位)来设置字体的大小。 Eg例如

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

It's not a pure CSS approach, but it's pretty close.这不是CSS 方法,但非常接近。

Inside your CSS, try adding this at the bottom changing the 320 pixels width for wherever your design starts breaking:在你的 CSS 中,尝试在底部添加这个,改变 320 像素的宽度,让你的设计开始崩溃:

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

Then give the font-size in "px" or "em" as you wish.然后根据需要在“px”或“em”中给出字体大小。

Try http://simplefocus.com/flowtype/ .试试http://simplefocus.com/flowtype/ This is what I use for my sites, and it has worked perfectly.这是我用于我的网站的内容,并且效果很好。

You may be you looking for something like this:您可能正在寻找这样的东西:

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

I have used flowtype , and it's working great (however it's JavaScript and not a pure CSS solution):我使用了 flowtype ,它运行良好(但它是 JavaScript 而不是纯 CSS 解决方案):

$('body').flowtype({
    minFont: 10,
    maxFont: 40,
    minimum: 500,
    maximum: 1200,
    fontRatio: 70
});

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).我自己的基于 jQuery 的解决方案通过逐渐增加字体大小来工作,直到容器高度大幅增加(这意味着它有一个换行符)。

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/您可以在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;
};

This web component changes the font size so the inner text width matches the container width.此 Web 组件更改字体大小,以便内部文本宽度与容器宽度匹配。 Check the demo .检查演示

You can use it like this:你可以像这样使用它:

<full-width-text>Lorem Ipsum</full-width-text>

I was very frustrated trying to achieve a fitty-like tight text wrapping so I ended up using a canvas-based method which I arrived at by unsuccessfully trying other methods.我非常沮丧地试图实现一种类似紧凑的文本换行,所以我最终使用了一种基于画布的方法,但我尝试其他方法没有成功。 What I was aiming for looks like the attached which turns out to be surprisingly difficult (for me).我的目标看起来像附件,结果(对我来说)非常困难。 Hopefully one day we will have a simple CSS-only way of doing this.希望有一天我们会有一种简单的纯 CSS 方式来做这件事。 Downsides of this approach is the text is treated more like an image, but for some use cases this is fine.这种方法的缺点是文本被视为更像图像,但对于某些用例来说这很好。

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

This image is a screenshot of a CSS Grid layout of four full-bleed canvases.此图像是四个全出血画布的 CSS 网格布局的屏幕截图。

在此处输入图像描述

My problem was similar, but related to scaling text within a heading.我的问题类似,但与标题内的缩放文本有关。 I tried Fit Font, but I needed to toggle the compressor to get any results, since it was solving a slightly different problem, as was Text Flow.我尝试了 Fit Font,但我需要切换压缩器以获得任何结果,因为它解决了一个稍微不同的问题,Text Flow 也是如此。

So I wrote my own little plugin that reduced the font size to fit the container, assuming you have overflow: hidden and white-space: nowrap so that even if reducing the font to the minimum doesn't allow showing the full heading, it just cuts off what it can show.所以我写了我自己的小插件来减小字体大小以适应容器,假设你有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);

Try to use the fitText plugin, because Viewport sizes isn't the solution of this problem.尝试使用fitText插件,因为视口大小不是这个问题的解决方案。

Just add the library:只需添加库:

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

And change font-size for correct by settings the coefficient of text:并通过设置文本系数来更改字体大小:

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

You can set maximum and minimum values of text:您可以设置文本的最大值和最小值:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });

Always have your element with this attribute:始终让您的元素具有此属性:

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

or或者

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

When you go fullscreen, you should already have a scale variable calculated (scale > 1 or scale = 1).当你进入全屏时,你应该已经计算了一个比例变量(比例 > 1 或比例 = 1)。 Then, on fullscreen:然后,全屏:

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

It works nicely with little code.它适用于很少的代码。

Take look at my code.看看我的代码。 It makes the font size smaller to fit whatever there.它使font size smallerfit那里的任何内容。

But I think this doesn't lead to a good user experience但我认为这不会带来良好的用户体验

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

结果

For dynamic text, this plugin is quite useful:对于动态文本,这个插件非常有用:

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

Simply add CSS:只需添加 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;
}

And the script:和脚本:

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

This worked for me:这对我有用:

I try to approximate font-size based on a width/height got from setting `font-size: 10px`.我尝试根据设置“font-size: 10px”获得的宽度/高度来近似字体大小。 Basically, the idea is "if I have 20 pixels width and 11 pixels height with `font-size: 10px`, so what would it be the maximum font-size to math a container of 50 pixels width and 30 pixels height?"基本上,这个想法是“如果我有 20 像素宽和 11 像素高且 `font-size: 10px`,那么计算一个 50 像素宽和 30 像素高的容器的最大字体大小是多少?”

The answer is a double proportion system:答案是双比例系统:

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

Now X is a font-size that will match width, and Y is a font-size that will match height;现在 X 是一个与宽度匹配的字体大小,而 Y 是一个与高度匹配的字体大小; take the smallest value取最小值

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

NB: the argument of the function must be a span element or an element which is smaller than its parent, otherwise if children and parent have both the same width/height function will fail.注意:函数的参数必须是跨度元素或小于其父元素的元素,否则如果子元素和父元素具有相同的宽度/高度,则函数将失败。

HTML HTML

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

JavaScript code for maximizing font-size:最大化字体大小的 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`;

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

In case it's helpful to anyone, most of the solutions in this thread were wrapping text into multiple lines, form e.如果它对任何人都有帮助,这个线程中的大多数解决方案都是将文本包装成多行,形式 e。

But then I found this, and it worked:但后来我发现了这个,它起作用了:

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

Example usage:示例用法:

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

In order to make font-size fit its container, rather than the window, see the resizeFont() function I have shared in this question (a combination of other answers, most of which are already linked here).为了使字体大小适合其容器而不是窗口,请参阅我在此问题中共享的resizeFont()函数(其他答案的组合,其中大部分已在此处链接)。 It is triggered using window.addEventListener('resize', resizeFont);它是使用window.addEventListener('resize', resizeFont);触发的。 . .

Vanilla JavaScript: Resize font-awesome to fit container Vanilla JavaScript:调整字体大小以适应容器

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 + '%';
    }
  }
}

You could perhaps use vw/vh as a fallback, so you dynamically assign em or rem units using JavaScript, ensuring that the fonts do scale to the window if JavaScript is disabled.您也许可以使用 vw/vh 作为备用,因此您可以使用 JavaScript 动态分配emrem单位,确保在禁用 JavaScript 时字体确实缩放到窗口。

Apply the .resize class to all elements containing text you wish to be scaled..resize类应用于包含您希望缩放的文本的所有元素。

Trigger the function prior to adding the window resize event listener.在添加窗口调整大小事件侦听器之前触发该函数。 Then, any text which doesn't fit its container will be scaled down when the page loads, as well as when it is resized.然后,任何不适合其容器的文本将在页面加载时按比例缩小,以及在调整大小时。

NOTE: The default font-size must be set to either em , rem or % to achieve proper results.注意:默认font-size必须设置为emrem%以获得正确的结果。

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

Straight up media queries seems like a much simpler and more understandable solution to resizing font based on container sizes that may be dynamic.直截了当的媒体查询似乎是一种更简单、更容易理解的解决方案,可以根据可能是动态的容器大小调整字体大小。

The below resizes the font to the size of the container, whether the container is scaled to the size of the viewport, or if it's reached its max value.下面将字体大小调整为容器的大小,无论容器是否缩放到视口的大小,或者是否达到其最大值。 If you have non-100% wide containers, you could adjust the vw accordingly.如果你有非 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;
    }
}

It is possible to some degree with pure CSS.纯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>

Explanation解释

content rule sets the content of an element and it can be a URL of an image, including an SVG image. content规则设置元素的内容,它可以是图像的 URL,包括 SVG 图像。 SVG images can contain text so basically you have a background image with text which resizes based on the size of its parent. SVG 图像可以包含文本,所以基本上你有一个带有文本的背景图像,它会根据其父级的大小调整大小。 You may also use background-image property, but unlike content it does not contribute to layout of the element, so you will need to define the size of the parent.您也可以使用background-image属性,但与content不同,它不会影响元素的布局,因此您需要定义父元素的大小。

The problem with this method is, you need to define the color, size and positioning of the text inside the SVG.这种方法的问题是,您需要在 SVG 中定义文本的颜色、大小和位置。 They won't be inherited from parent.他们不会从父母那里继承。 But you can get clever with Sass and Less.但是你可以通过 Sass 和 Less 变得聪明。 There can also be accessibility issues with this solution.此解决方案也可能存在可访问性问题。

I don't recommend using this everywhere.我不建议在任何地方使用它。 But it should be fairly useful in certain situations.但它在某些情况下应该相当有用。

Here is a pure CSS solution with the understanding that you admit breakpoints are necessary but also want text scaling:这是一个纯 CSS 解决方案,您承认断点是必要的,但也需要文本缩放:

I'm aware I can add breakpoints, but I really want the text to scale as well as having extra breakpoints, otherwise....我知道我可以添加断点,但我真的希望文本可以缩放以及有额外的断点,否则......

Here is an approach using:这是一种使用方法:

  1. Custom properties自定义属性
  2. Media queries for breakpoints断点的媒体查询
  3. clamp() ( browser support in Feb 2022 is pretty good at 93%) clamp()2022 年 2 月的浏览器支持率相当不错,达到 93%)
  4. calc()

If one common scaling factor can be used to control ALL the text scaling within a container per screen max-width , all you need to do is scale a custom property per max-width , and apply this factor to 1 calculation .如果可以使用一个常见的缩放因子来控制容器内每个屏幕max-width所有文本缩放,那么您需要做的就是按max-width缩放自定义属性,并将此因子应用于 1计算

A basic setup starts like this:基本设置如下所示:

: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%); 
}

Then nest your media queries something like this (or whatever you need for your breakpoints):然后嵌套您的媒体查询,如下所示(或您的断点所需的任何内容):

@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() */
      }
    }
  }
}

This minimizes your media query markup.这可以最大限度地减少您的媒体查询标记。

Advantages优点

  1. One custom property controls ALL scaling ... no need to add multiple declarations per media breakpoint一个自定义属性控制所有缩放...无需为每个媒体断点添加多个声明
  2. The use of clamp() sets a lower-limit on what the font-size should be, so you ensure your text is never too small (here the floor is 60% of the parent's font-size ) clamp()的使用设置了font-size的下限,因此您确保您的文本永远不会太小(这里的下限是父font-size的 60%)

Please see this JSFiddle for a demo.请参阅此 JSFiddle以获取演示。 Resize the window until at the smallest widths, the paragraphs are all the same font-size .调整窗口大小,直到最小宽度,段落都是相同的font-size

If you want to fit it inside of a particular container, like a div, use:如果您想将其放入特定容器(如 div)中,请使用:

width: max-content;

Also tweaking font-size helps a lot, eg font-size: 75% .调整font-size也有很大帮助,例如font-size: 75%

You can interpolate the font size for the window width:您可以插入 window 宽度的字体大小:

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

I wanted to like the accepted answer, but fundamentally the ones that met my criteria all required used a library.我想喜欢接受的答案,但基本上符合我标准的答案都需要使用库。 Rather than acquaint myself with yet another library and then figure out how to use it and prepare to debug it if it didn't work, I decided to write a simple function that is working perfectly for me.我决定编写一个简单的 function 对我来说非常适合,而不是让自己熟悉另一个库,然后弄清楚如何使用它并准备调试它。

Theory:理论:

  • pass in the string that you need to fit传入你需要适合的字符串
  • pass in the parent that you will be inheriting text styles from传入您将从中继承文本 styles 的父级
  • optionally pass in custom attributes (eg, class/id you'll inherit font and other attributes from, or just custom inline styles)可选地传入自定义属性(例如,您将从中继承字体和其他属性的类/ID,或者只是自定义内联样式)
  • function will create a text element off screen with that text, that parent, and those attributes, with font size of 1px, and measure it function 将使用该文本、该父项和这些属性在屏幕外创建一个文本元素,字体大小为 1px,并测量它
  • then, on a loop, it will increase the font size pixel by pixel until it surpasses the width limit;然后,在一个循环中,它将逐个像素地增加字体大小,直到超过宽度限制; once it has done that, it will return the last one that did fit一旦完成,它将返回最后一个合适的
  • it then deletes the test element然后它删除测试元素
  • this all happens in the blink of an eye of course这一切当然发生在眨眼之间

Limitations:限制:

  • I don't care about dynamic screen resizing, as that's not relevant to my context.我不关心动态屏幕大小调整,因为这与我的上下文无关。 I only care about screen size at runtime when generating the text.生成文本时,我只关心运行时的屏幕大小。
  • I rely on one small helper function I also use elsewhere in my code, that basically exists as a one-function-version of mithril.js;我依赖一个小助手 function 我也在我的代码的其他地方使用,它基本上作为 mithril.js 的单功能版本存在; honestly, I use this little function in almost every project, and it's worth learning itself.老实说,我几乎在每个项目中都使用这个小 function,它本身就值得学习。
  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;`;  

Container Queries are a recent addition to the CSS feature set (late 2022) that make this straightforward. 容器查询是最近添加到 CSS 功能集(2022 年末)的功能,它使这一点变得简单明了。

They allow you to apply styles based on the size of the containing element, but also come with a new set of CSS units cqw / cqh for c ontainer q uery w idth/ h eight.它们允许您根据包含元素的大小应用 styles,而且还附带一组新的 CSS 单位cqw / cqh用于c ontainer q uery w idth / h八。 To use them you need to set the container-type property on the parent element whose size you want to use.要使用它们,您需要在要使用其大小的父元素上设置container-type属性。 Here's a minimal example:这是一个最小的例子:

 <div> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste odio modi deserunt dolores magnam, amet quidem repudiandae accusantium nobis, error iure vel? Debitis esse cum dolorum nihil, quo fugit vitae.</p> </div> <style> div { container-type: inline-size; } p { font-size: 5cqw; } </style>

The font size will increase smoothly as the parent container grows.字体大小会随着父容器的增长而平滑增加。 At 1000px container width, the p font size will be 1000px / 100 * 5 = 50px .在 1000px 容器宽度下, p字体大小将为1000px / 100 * 5 = 50px

container-type can be size or inline-size . container-type可以是sizeinline-size size tracks both height and width of the container, ie allows you to use both cqw and cqh . size跟踪容器的高度和宽度,即允许您同时使用cqwcqh Most of the time on the web, heights are calculated based on content and you only specify the width.大多数情况下,在 web 上,高度是根据内容计算的,您只需指定宽度。 To save the browser some work, you'll generally want to set container-type: inline-size;为了节省浏览器的一些工作,您通常需要设置container-type: inline-size; so the browser only tracks the inline dimension which is usually width.所以浏览器只跟踪通常是宽度的内联尺寸。

Browser support has grown rapidly in the 2nd half of 2022 and currently stands at 75% (2023-01-01).浏览器支持在 2022 年下半年迅速增长,目前为 75% (2023-01-01)。

If the issue is font getting too big on widescreen desktop, I think the easiest CSS method would be something like this (assuming wrapper maximum 1000 pixels wide)如果问题是宽屏桌面上的字体太大,我认为最简单的 CSS 方法是这样的(假设包装器最大 1000 像素宽)

.specialText{
    font-size: 2.4vw;
}

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

So it is auto sized for any screen smaller than the maximum width of your container, and fixed size when the screen is wider (like virtually all desktop and laptops).因此,对于小于容器最大宽度的任何屏幕,它都会自动调整大小,而当屏幕更宽时(几乎所有台式机和笔记本电脑),它会自动调整大小。

I just created a demo how to do it.我刚刚创建了一个演示如何做到这一点。 It uses transform:scale() to achieve that with some JS that watches element resizing.它使用transform:scale()来通过一些观察元素大小调整的 JS 来实现这一点。 Works nicely for my needs.很好地满足我的需求。

What about this?那这个呢?
Setting the parent's font size equal to its width, then use a percentage for text element font size.将父级的字体大小设置为等于其宽度,然后使用百分比作为文本元素字体大小。

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

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

I find this really easy specially when you are dealing with icons, but also works for text.当您处理图标时,我发现这非常容易,但也适用于文本。

 /* 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>

But what if the container is not the viewport (body)?但是如果容器不是视口(主体)呢?

The real answer is in the transform property allows you to visually manipulate an element by skewing, rotating, translating, or scaling:真正的答案在于transform 属性允许您通过倾斜、旋转、平移或缩放来直观地操作元素:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM