基于容器宽度的字体缩放

我很难让我的头周围的字体缩放。

我目前有一个网站,其主体font-size为100%。虽然是100%?这似乎以16像素计算。

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

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

我的理由是,当你调整大小时,像我的菜单这样的东西会被压扁,所以我需要减少.menuItem中的pxfont-size与容器宽度的关系。(例如,在大型桌面上的菜单中,22px效果很好。向下移动到平板电脑宽度,16px更合适。)

我知道我可以添加断点,但我真的希望文本缩放为好吧,因为有额外的断点,否则,我将为每减少100像素的宽度以控制文本而结束数百个断点。

1872387 次浏览

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

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

在你的CSS中,尝试在底部添加这个,改变320像素的宽度,无论你的设计开始破坏:

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

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

如果容器不是主体,CSS Tricks涵盖了将文本安装到容器中中的所有选项。

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

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

这些值是:

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

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

使用它看起来像这样:

p {font-size: 4vw;}

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

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

浏览器支持非常好,但您可能需要回退,例如:

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

查看支持统计数据:http://caniuse.com/#feat=viewport-units

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

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

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

另外,请查看这篇文章,它使用了一种被称为“熔融引线”的技术来调整线路高度。

但是如果容器不是视口(主体)怎么办?

这个问题在Alex在公认的答案下的评论中被问到。

这一事实并不意味着vw在某种程度上不能用于该容器的大小。现在要看到任何变化,必须假设容器在某种程度上是灵活的大小。无论是通过直接百分比width还是通过100%减去边距。如果容器总是设置为,比方说,200px宽度,那么设置一个适用于该宽度的font-size,这一点就变得“没有意义”了。

例1

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

div {width: 50%;border: 1px solid black;margin: 20px;font-size: 16px;/* 100 = viewport width, as 1vw = 1/100th of thatSo 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;}

假设这里的divbody的孩子,它是100%宽度的50%,这是这个基本情况下的视口大小。基本上,你想设置一个vw,这对你来说会很好。正如你在我的评论中看到的,在上面的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 thatHere, 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动态改变其百分比关系,那么无论基本“目标”是什么,都需要重新计算以保持文本大小的相同“关系”。

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

一个挑战

使用CSS3#0函数时,动态调整将变得困难,因为该函数此时不适用于font-size目的。因此,如果您的宽度在calc()上发生变化,则无法进行纯CSS 3调整。当然,对边距宽度的微小调整可能不足以保证font-size的任何更改,因此可能无关紧要。

尝试http://simplefocus.com/flowtype/。这是我在我的网站上使用的,它工作得很好。

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

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

我用过流量类型,效果很好(但它是JavaScript而不是纯CSS解决方案):

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

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

最简单的做法是为body指定一个特定的字体大小(我推荐10),然后所有其他元素的字体都在emrem中。我会给你一个例子来理解这些单位。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:

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

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

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

但是我推荐的解决方案是使用一个JavaScript库来帮助你做到这一点。到目前为止我找到了fittext.js

这里是函数:

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

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

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

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

http://jsfiddle.net/0tpvccjt/

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

它非常简单,但效果相当好,并且非常易于使用。您不必知道任何关于正在使用的字体,一切都由浏览器处理。

你可以用它玩http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

魔法就发生在这里:

var setMaxTextSize=function(jElement) {// Get and set the font size into data for reuse upon resizevar 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 quickFitSetClassfontSize -= 1;jElement.addClass(quickFitSetClass).css("font-size", "" + fontSize + "px");
return fontSize;};

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

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

抛开视口单元不能与文本的父单元一起出现的限制(例如,让%size的行为与其他所有人一样),视口单元确实提供了一个非常强大的工具:能够获得最小/最大尺寸。你不能在其他任何地方这样做-你不能说…让这个div的高度成为父*的宽度。

话虽如此,诀窍是使用vmin,并设置ifradsize,以便当高度是限制尺寸时,[分数]*总高度是一个很好的字体大小,当宽度是限制尺寸时,[分数]*总宽度。这就是为什么高度必须是宽度和长宽比的乘积。

对于我的例子,你有

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

这种方法的小烦恼是你必须手动设置ifram的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只是我自定义的点击拖动函数。

使用SVG的解决方案:

.resizeme {resize: both;margin: 0;padding: 0;height: 75px;width: 500px;background-color: lightblue;overflow: hidden;}
<div class="resizeme"><svgwidth="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"><textx="0"y="75"font-size="75"fill="black">█Resize This█</text></svg></div>

使用foreignObject进行SVG和文本包装的解决方案:

.resizeme {resize: both;margin: 0;padding: 0;height: 200px;width: 500px;background-color: lightblue;overflow: hidden;}
<div class="resizeme"><svgwidth="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>

我的问题与此类似,但与标题中的缩放文本有关。我尝试过Fit Font,但我需要切换压缩器才能获得任何结果,因为它解决的是一个稍微不同的问题,就像文本流一样。

所以我写了我自己的小插件,减少了字体大小以适应容器,假设你有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);

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

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

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

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

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

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

带有calc()、CSS单元和数学的纯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 - 6emr = 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意味着视口的全宽度,在滚动条下延伸(内容不能扩展!),所以全宽文本必须仔细边缘,最好在许多浏览器和设备上进行测试。

始终使用此属性的元素

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

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

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

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

它用很少的代码很好地工作。

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

你可以像这样使用它:

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

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

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

博客文章:全宽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

看看我的代码。它使font size smallerfit在那里。

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

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

结果

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

但后来我发现了这个,它奏效了:

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

示例用法:

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

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

只需添加库:

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

并通过设置文本系数更改font-size为正确:

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

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

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

使用vwem&co.肯定有效,但在我看来,它总是需要人类的触摸来进行微调。

这是我刚刚基于@ttnt-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(){varfs = 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>

它基本上将font-size减小到1em,然后开始递增0.1,直到达到最大宽度。

JSFiddle

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

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

为了使font-size适合它的容器,而不是窗口,请参阅我在这个问题中分享的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%才能获得正确的结果。

这对我有效:

我尝试根据设置'font-size: 10px'获得的宽度/高度来近似font-size。基本上,这个想法是“如果我有20像素的宽度和11像素的高度,'font-size: 10px',那么对50像素宽度和30像素高度的容器进行数学运算的最大font-size是多少?”

答案是双比例系统:

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

现在X是一个与宽度匹配的font-size,Y是一个与高度匹配的font-size;取最小的值

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

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

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

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

尝试使用以下解决方案…

超文本标记语言

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

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

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

下面将根据容器的大小调整字体的大小,无论容器是缩放到视口的大小,还是达到其最大值。如果你有非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;}}

使用CSS变量

还没有人提到CSS变量,这种方法最适合我,所以:

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

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

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

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

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

但是如果容器不是视口(主体)怎么办?

真正的答案是在变换性质中,它允许您通过倾斜、旋转、平移或缩放来直观地操作元素:

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

超文本标记语言

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

最大化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`;

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

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

让我们看看我们如何处理。

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")))作为参考,然后相应地计算后续行的字体大小。

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

我在尝试实现类似Fitty的紧密文本包装时非常沮丧,所以我最终使用了基于画布的方法,我尝试了其他方法但没有成功。我的目标是看起来像附件,结果证明非常困难(对我来说)。希望有一天我们将有一个简单的仅限CSS的方法来做到这一点。这种方法的缺点是文本被处理得更像图像,但对于一些用例来说这很好。

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

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

在此处输入图片描述

在某种程度上可以使用纯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>

补充说明

#0规则设置元素的内容,它可以是图像的URL,包括SVG图像。SVG图像可以包含文本,所以基本上你有一个背景图像,其中的文本根据其父级的大小调整大小。你也可以使用background-image属性,但与content不同,它不有助于元素的布局,所以你需要定义父级的大小。

这种方法的问题是,你需要定义SVG中文本的颜色、大小和位置。它们不会从父级继承。但是你可以使用Sass and less来变得聪明。这种解决方案也可能存在可访问性问题。

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

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

.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>

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

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

这是一种使用的方法:

  1. 自定义属性
  2. 断点的媒体查询
  3. #02022年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()设置了font-size应该是什么的下限,所以你确保你的文本是永远不会太小(这里的地板是父文本font-size的60%)

请参阅这个jsfiddle进行演示。调整窗口大小,直到最小宽度,段落都相同font-size

如果您想将其放入特定容器中,例如div,请使用:

width: max-content;

调整font-size也有很大帮助,例如font-size: 75%

您可以插入窗口宽度的字体大小:

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

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

理论:

  • 传入你需要适应的字符串
  • 传入您将从中继承文本样式的父级
  • 可选地传入自定义属性(例如,你将继承字体和其他属性的class/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/neededattributes.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;`;