基于容器宽度的字体缩放

我很难让字体缩放。

我目前有这个网站的身体font-size为100%。 100%是什么? 这似乎计算出16px。

我的印象是,100%会以某种方式引用浏览器窗口的大小,但显然不是因为窗口大小调整为移动宽度或全宽屏桌面,总是16px。

我怎样才能使我的网站上的文字相对于其容器的规模? 我尝试使用em但这并不规模。

我的理由是,当你resize时,像我的菜单这样的事情会变.menuItem ,所以我需要减less.menuItem与其他元素的px font-size相关的容器的宽度。 (例如,在大型桌面上的菜单中,22px可以很好地工作,向下移动到平板宽度,16px更合适。)

我知道我可以添加断点,但是我真的希望文本可以扩展为具有额外的断点,否则最终每隔100px减less数百个断点来控制文本。

你正在寻找的是视口百分比长度 :

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

值是:

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

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

使用它看起来像这样:

 p { font-size: 4vw; } 

正如您所看到的,当视口宽度增加时,字体大小也会增加,而不需要使用媒体查询。

这些值是一个大小单位,就像pxem ,所以它们也可以用来确定其他元素的大小,例如宽度,边距或填充。

浏览器支持非常好,但你可能需要一个回退,如:

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

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

此外,检查出更广泛的看CSS的技巧: http : //css-tricks.com/viewport-sized-typography/

这里有一个很好的文章,关于设置最小/最大尺寸和行使更多的控制大小: http : //madebymike.com.au/writing/precise-control-responsive-typography/

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

此外,请查看这篇文章,其中使用了一种被称为“融化领先”的技术来调整行高。 https://css-tricks.com/molten-leading-css/

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

亚历克斯在接受的答案中提出了这个问题。

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

例1

然而,对于柔性宽度的容器来说,必须认识到,在某些方面,容器的尺寸仍然远离观察口 。 因此,调整vw设置是基于与视口不同的百分比大小差异,这意味着要考虑父包装的大小。 以这个例子

 div { width: 50%; border: 1px solid black; margin: 20px; font-size: 16px; /* 100 = view port width, as 1vw = 1/100th of that So if the container is 50% of view port (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 [ie 50%]) */ font-size: 2.5vw; } 

假设这里divbody一个孩子,它是100%宽度的50% ,这是这个基本情况下的视口大小。 基本上,你想要设置一个你会看起来很好的vw 。 正如你可以在上面的CSS中的评论中看到的那样,你可以通过math上的“思考”完整的视口大小,但是你不需要这么做。 文本将与容器一起“弯曲”,因为容器正在调整视口大小。 更新: 这是一个两个不同大小的容器的例子 。

例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 = view port width, as 1vw = 1/100th of that Here, the body is 200% of viewport, but the container is 50% of view port, 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 [ie 150%]) * .5 [ie 50%] */ font-size: 3.75vw; } 

尺寸仍然是基于视口,但基本上根据容器尺寸本身来设置。

如果容器大小dynamic变化…

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

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

一个挑战

在使用CSS3 calc()函数时,dynamic调整将变得困难,因为此时该函数不适用于font-size目的。 所以如果你的宽度在calc()上改变,你不能做纯粹的CSS3调整。 当然,对边距的宽度进行微小的调整可能不足以保证font-size任何改变,因此可能无关紧要。

这个问题有一个很大的哲学。 最简单的做法是给一个特定的字体大小的身体(我推荐10),然后所有其他元素将有他们的字体在REM或REM。 我会给你和例子来理解这些单位。 Em总是相对于他的父母

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

雷姆总是相对身体

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

而且你可以创build一个脚本来修改相对于你的容器宽度的字体大小。 但是这不是我想要的。 因为在一个900px的宽度的容器中,例如你会有一个12px字体大小的p元素。 并在您的ideea将成为在4px字体大小的300px宽度容器。 必须有一个下限。 另一种解决scheme是使用媒体查询,以便您可以设置不同宽度的字体。

但我会build议的解决scheme是使用一个JavaScript库,可以帮助你。 和我find的fittext.js到目前为止。

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

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

我知道这不能回答这个问题,但也许这可能是其他人的解决办法。

更新,因为我得到了一个投票。

这是function:

 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/

这可能不太实际,但是如果你希望字体是父类的直接函数,而没有任何监听/循环(间隔)的JS读取div /页面的大小,有一种方法可以做到这一点。 I帧。 iframe中的任何内容都会将iframe的大小视为视口的大小。 所以诀窍就是制作一个iframe,其宽度是您希望文本的最大宽度,其高度等于最大高度*特定文本的宽高比。

如果不考虑视口单元不能同时出现在父单元中的限制,那么视口单元确实提供了一个非常强大的工具:能够获取最小/最大尺寸。 你不能在其他地方做到这一点 – 你不能说…做这个div的高度是父母的宽度*的东西。

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

对于我的具体例子,你有

 .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规则。

我想不出没有骑自行车/听JS的另一种方式。 真正的解决scheme是为浏览器提供缩放文本的方法,作为父容器的function,并提供相同的vmin / vmaxtypes的function。

JS小提琴: https : //jsfiddle.net/0jr7rrgm/3/ (点击一次将红色方块locking到鼠标,再次点击释放)

大部分的小提琴中的JS只是我自定义的点击拖动function

纯粹的CSS解决scheme与calc() ,CSS单位和math

这不是OP所要求的,而是可能使某人的一天。 这个答案并不容易,在开发者方面需要一些研究。

我终于得到了一个纯CSS的解决scheme,使用不同的单位calc() 。 你将需要一些基本的公式math理解来calc()expression式。

当我解决这个问题的时候,我必须得到一个完整的页面宽度的响应头,在DOM中填充一些父母的填充。 我会在这里使用我的价值观,用自己的价值取代他们。

math

你会需要:

  • 在一些视口很好地调整的比例,我用320px,因此我得到了24px高和224px宽比例是9.333 …或28/3
  • 容器宽度,我有padding: 3em和全宽,所以这得到100wv - 2 * 3em

X是容器的宽度,所以用你自己的expression来replace它,或者调整这个值来得到整页文本。 R是你将拥有的比率。 您可以通过调整某些视口中的值,检查元素的宽度和高度并用您自己的值replace它们来获取它。 另外,它是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表示视口的全部宽度,我的目标是用一些填充来build立全宽头。

比例。 在一个视口中获取宽度和高度让我有一个比例可以玩,而且我知道在其他视口宽度中的高度应该是多less。 用手计算它们需要很多时间,至less需要很多带宽,所以这不是一个好的答案。

结论

我想知道为什么没有人知道这一点,有些人甚至告诉说,这是不可能的CSS修补。 我不喜欢使用Javascript来调整元素,所以我不接受JS或甚至没有挖掘更多的jQuery答案。 总而言之,这很好,这是网站devise中纯CSS实现的一个步骤。

我对我的文章中的任何不寻常的约定表示歉意,我不是母语为英语的人,而且对于写答案也是相当新颖的。

编辑 :它也应该指出,我们在一些浏览器中有邪恶的滚动条。 例如,当使用Firefox时,我注意到100vw意味着视口的全部宽度,在滚动条(内容不能扩展!)下面延伸,所以全宽文本必须小心谨慎,最好用许多浏览器和设备进行testing。

SVG解决scheme:

 <div style="width: 60px;"> <svg width="100%" height="100%" viewBox="0 -200 1000 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <text font-size="300" fill="black">Text</text> </svg> </div> 

https://jsfiddle.net/qc8ht5eb/

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

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

在你的CSS里面,在底部改变320px的宽度,在你的devise开始打破的地方,

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

然后按照你的意愿在“px”或“em”中input字体大小。

你有没有尝试http://simplefocus.com/flowtype/

这是我用于我的网站,并已完美运作。 希望它有帮助。

你在找这样的东西吗? =>
http://jsfiddle.net/sijav/dGsC9/4/
http://fiddle.jshell.net/sijav/dGsC9/4/show/
我已经使用stream式 ,它的工作很好(但它是JS和不是纯粹的CSS解决scheme)

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

我自己的解决scheme,基于jQuery,通过逐渐增加字体大小,直到容器的高度增加(意味着它有一个换行符)。 这很简单,但工作得很好,使用起来非常简单。 您不必了解所使用的字体,浏览器就会处理所有的事情。

你可以在http://jsfiddle.net/tubededentifrice/u5y15d0L/2/上玩;

魔术发生在这里:

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

我的问题是类似的,但与缩放标题内的文本有关。 我尝试了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); 

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

你可以像这样使用它:

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

我已经准备了使用css转换而不是字体大小的简单的缩放function。 你可以在任何容器中使用它,你不必设置媒体查询等:)

博客文章: https : //blog.polarbits.co/2017/03/07/full-width-css-js-scalable-header/

代码:

 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

使用vwem &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> 

如果问题是宽屏桌面上的字体变得太大,我认为最简单的css方法将是这样的(假设封装最大1000px宽)

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

所以它是自动resize的任何屏幕小于您的容器的最大宽度和固定的大小,当屏幕更宽(几乎所有的台式机/笔记本电脑)

总是让你的元素具有这个属性:

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

要么

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

当你进入全屏时,你应该已经有一个计算的比例variables(比例> 1或比例= 1)。 然后,在全屏上:

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

它很好用less量的代码。

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

看看我的代码,它使font size smallerfit任何地方

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

 var containerWidth = $("#ui-id-2").width(); var items = $(".quickSearchAutocomplete .ui-menu-item"); var fontSize = 16; items.each(function(){ //display value depend 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); } }); 

结果

希望这对你有所帮助

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

但后来我发现这个,它的工作:

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

用法示例:

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

尝试使用fitText插件,导致视口大小不是这个问题的解决scheme。 只需添加库

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

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

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

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

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

对于dynamic文本,这个插件是非常有用的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(); 

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

香草JS:调整字体真棒适合容器

JS:

 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作为后备,所以你dynamic地分配使用JavaScript的emrem单位,确保如果JavaScript被禁用,字体会缩放到窗口。

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

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

注:默认的font-size必须设置为emrem%以获得正确的结果…如果元素的样式过于复杂,那么浏览器可能会崩溃,如果你开始疯狂地调整窗口的大小。