[翻译]使用VH和VW实现真正的流体排版

前言

不像响应式布局,经过media query,设置几个变化点来适配,流体排版经过调整大小,适配全部设备宽度。这个方法可使咱们开发的网页,在几乎全部屏幕尺寸上均可以使用。但出于一些缘由,它的使用率还远远没有响应式技术高。css

在印刷的历史上,排版是根深蒂固的。关于“流体”的概念,在传统思想里并不存在。这是由于,在印刷上,尺寸大小都是有固定的,不用考虑在页面上使用。我认为流体排版技术能够和网页很好的匹配。这是在不一样媒介上的一种解决方法。html

并不意味着咱们要推翻以前的全部关于排版的认识,只须要去学习如何用不一样方式,去运用掌握新的技术。只要注意细节,就能够制做出适配全部屏幕尺寸的完美的页面。css3

流体排版上手

视口(viewport)单位,使流体排版在页面上应用变为可能。视口单位是根据浏览器的视口尺寸的百分比来定义的。web

举个例子,1视口宽度(vw)等于视口宽度的1%,它不一样于百分比的地方是,它的宽度是依赖于视口的宽度的,而百分比是元素的祖先元素来决定的。chrome

视口单位,不一样于其它单位,它不依赖于基础字体的大小。这种差异很重要,使它变得有意义并且独特。npm

可使用的4种视口单位浏览器

  • vw:视口宽度(viewport width)
  • vh:视口高度(viewport height)
  • vmin:视口宽度或高度,选择小的那个
  • vmax:视口宽度或高度,选择大的那个

使用流体排版最简单的方法,是把html元素的font-size,设置为一个流体单位:sass

html{ font-size: 2vw; }ide

这个例子中,咱们把根元素的字体大小设置为2vw。这里咱们已经修改了根元素字体大小。由于直接或间接使用的em或rem单位,都是依赖于"root rem"的,因此也变成流体的了。例如模块化

h1{  font-size:2em; }

h1的font-size:2em,若是它依赖的是根节点的字体大小,那么 font-size:2*2vw=4vw。

只使用视口相关的单位也有一些不足。

  • 没法精确地控制放大比率。
  • 没有最大或最小字体大小。
  • 和使用font-size相比,用户更容易使用像素来声明大小。

控制视口单位来设置最小最大font-size

html设置为font-size:2vw的方法,看起来既是流体的,调用起来也很方便,但有些场景无法覆盖。视口单位不是万能的,它也须要使用一些其它的方法,来解决没法覆盖的场景。因为视口单位都是依赖于视口的,在很是小的屏幕上,会获得很小的字体大小,已致没法查看。(chrome的最小字体是12px,好像能够解决了。)

理想状况下,咱们能够经过设置最小字体来避免这种状况,但CSS中没有min-font-size这个属性。经过一些横向思惟,咱们能够获得实现这种效果的方法。

首先,咱们可使用calc()表达式。

html{ font-size: calc(1em + 1vw); }

这样就算咱们在一个0宽度的视口中,font-size的大小也会存在,并为1em。在大的屏幕上,1vw也会在最小字体1em的基础上增长。可是这种解决方法也不是最理想的。一般咱们只是想在一些小的屏幕上去设置最小字体。咱们可使用media query来解决:

@media screen and (min-width: 50em) {
  html {
    font-size: 2vw;
  }}

上面代码设置,是仅在当视口宽度大于50em的时候,使用流体。虽然这样能很好的工做,但也代表会在固定值和流体值之间跳动。为了解决这个问题,咱们能够计算出流体值和固定值之间的对应关系。

若是默认字体大小是16像素,而且2vw是2%的视口宽度,那么能够知道在800像素的视口时两个值是相等的。(16/(2/100)=800

由于咱们想在media query中,使用em单位来匹配。如今来换算一下像素到em。800像素除以16:800/16=50。咱们也可使用这个公式来算1/(2/100)=50。和上面例子里使用的变化条件同样,2vw对应的是50em。最终,咱们获得了一个不会在固定和流体之间,产生跳动变化的值。

一样的能够用公式去算出最大字体。若是咱们想使用的最大字体是24像素,那么对应的视口宽度就是24/(2/100)=1200px。换算成字体,就是1.5/(2/100)=75em。若是视口宽度大于75em时,咱们就把字体大小设置成固定值。

@media screen and (min-width: 75em) {
  html {
    font-size: 1.5em;
  }}

这些计算都不是太难,下面作了一个表格,显示了各视口宽度,流体大小对应的字体大小。

Image

经过这个表格,你能够得到一些控制视口单位变化。使用单独的视口单位,能够只看对应的一列中的字体大小。

控制缩放比率

在不使用media query的状况下,咱们不可能解决,在400像素的屏幕上显示16像素的字体,在800像素显示24像素的问题。

还有,你可能会说,可使用设置最大最小字体的方式,来解决这个问题。但这里不是像那样来处理的。

咱们要怎么去解决这个问题呢?答案是使用calc()。使用calc和视口单位配合,咱们能够用高级的流体排版,能够精确地控制必定范围内的视口宽度使用特定大小的像素值。这里须要创建一个基本的数字函数:

Image(1)

这个函数能够能过一个范围内的一个值,能够计算出另外一个对应范围的值。若是你取1-100的中的50,用它获取1-200的值 ,你将获得100。(其实我获得的是(1+(200-1)*(50-1)/(100-1)=99.4949495))。这两个值都是各自范围的中间值。

这是一个求映射值的工具函数,在JS中处理数据时常用。当我认识到这只是一个纯粹的数学函数,我只须要一个变化的量,我使用calc()来运行这个函数。这里的变化关键值是视口大小:视口大小就是一个变量。100vw是一个变化的值,它是根据视口的尺寸变化的。有了最终的设想,花了一段时间来得到了能工做的函数表达式。calc()函数以其独特的方式来处理不一样的单位类型。若是你对这方面感兴趣,强烈推荐《 W3C对单位类型和值规范》,不为别的,就为了你在同事之间沟通时,能够吹牛B。

计算看上去很复杂,其实很简单。咱们选择最小和最大字体值,而且能够根据屏幕的尺寸来获取精确的字体大小。咱们可使用任何单位,包括em,rem,px。这里拿像素来举例,是由于能够解释起来更方便并更好理解,但正常工做中我是使用rem单位的。看你本身的喜爱啦,但有一点,方程式里全部的值必须是单位统一的,并且你也要像上面的例子中同样,去除一些单位。

若是你不想输入上面的代码,有一些工具能够帮助你实现。好比:SASS,LESS,PostCSS插件。这样你就能够轻松的工做了。

保持理想的阅读长度

在《The elements of typographic style》,Robert Bringhurst 提出一个合理的阅读长度 大约是45到75个字符的长度

Anything from 45 to 75 characters is widely regarded as a satisfactory length of line for a single-column page set in a serifed text face in a text size. The 66-character line (counting both letters and spaces) is widely regarded as ideal.

一样的规则能够直接运用到流体排版上,不少状况下,文件缩放实现一致的阅读长度是可能的。

在响应式方法里,咱们在media query里设置不一样的字体大小,调整容器的宽度,来保持正确的阅读长度。然而,使用流体排版,调整media query下的值方法已经行不通了。 只是设置容器的大小,使它的比率和字体相同。咱们可使用像上文提到的计算font-size的方法,使用 calc()来计算width属性的值。这能够保持阅读长度-并且样式表也更容易阅读和维护了。

在很是小的屏幕维护理想的阅读长度是不可能的。这种状况下,咱们选择把容器的宽度设置为智能移动设备的宽度。

实现模块化缩放

模块化缩放是指一组成比例的数值。看图能够更直观地看到效果:

Image(2)

每一个标题都是下面标题的1.2倍大小。

不用的屏幕尺寸显示不一样的绽开效果会更好。

Image(3)

在小屏幕的时候,标题大小显示得更统一。在大屏幕上有足够的空间能够显示更大的差异。咱们可使用排版技术来使在不一样的模板缩放变化时更平滑。简单地在不一样的屏幕上选择不的缩放比率,而后计算出每一个的标题级别,不一样的最小和最大的字体大小。

计算模块化的缩放,使用基础字体大小乘以一个指望的比率来获得一个大的值。获得小值是用除法。使用相同的方法去计算出每一个缩放对应的值。

大值:

  • 1em × 1.125em = 1.125em
  • 1.125em × 1.125em = 1.266em
  • 1.266em × 1.125em = 1.424em
  • 1.424em × 1.125em = 1.602em

小值:

  • 1em ÷ 1.125em = 0.889em
  • 0.889em ÷ 1.125em = 0.790em
  • 0.790em ÷ 1.125em = 0.702em
  • 0.702em ÷ 1.125em = 0.624em

咱们使用1.125作为咱们最小缩放比率,1.250作为咱们最大缩放比率。下面咱们把这个缩放比率应用到每一个级别的标题级别上。

  • 最小缩放比:1.125
  • 最大缩放比:1.250

Image(4)

让咱们在codepen上演示一下流体模块缩放标题。你能够从Tim Brown的《排版的意义》是去了解更多的模块绽开信息。

如何去选择一个合适的缩放比率,推荐 Jeremy Church的网站Type Scale,Tim brown、Scott Kellum的Modular Scale网站

保持垂直比例

纵向排版有必要保持页面元素之间的空白一致。这方面信息能够读Espen Brunborg的《CSS Baseline: The Good, the Bad and the Ugly》。

在咱们的层上保持纵向排版,须要设置一个元素之间的垂直空白的比例。找到一个在大屏幕和小屏幕上都适配的垂直排版,是颇有挑战性的。咱们一般但愿找出大屏和小屏的基本度量,或使用不一样的比例。

在流体排版中,基线也像字体大小同样是流体的。事实上,你给根元素设置一个流体的值,你可使用em或rem单位。你也可使用calc()来计算。

咱们设置baseline为1.5rem,而后把body的padding设置为一个单位的baseline。

body {
  padding: 1.5rem;
}

能够一样来设置line-height和margin

p {
  line-height: 1.5rem;
  margin-bottom: 1.5rem;
}

给标题元素设置不一样的line-height。我想让line-height加margin值等于baseline的增量。这里可使用calc()来计算。

h1 {
  font-size: 2rem;
  line-height: 2rem;
  margin-top: calc((1.5rem - 2rem) + 1.5rem);}

这个例子里,标题元素的height加上margin值等于3rem,正好是baseline值的两倍。

这里用sass变量建立一个例子,方便你们理解。

将来,使用自定义css属性,能够对这项技术进行更多的扩展。咱们能在calc()表达式中,使用css变量,计算出对应media query中的baseline基值。

约束条件

当你想在WordPress或Bootstrap,这些已经有预约义的布局中使用,或在已经存在布局的网站上使用,流体排版时。容器有可能不是流体的,或它们不是根据字体大小的比率来改变的。

最近,帮助澳大利亚政府的民众部,实现了流体排版。这是一个很大的网站,并且我必须根据已有的设计进行制做。在这种大流量的网站上实现流体布局,我有两个主要方面的问题。

第一问题,怎样阻止布局被破坏?在这个项目中,我预期导航容器里的内容,会由于字体大小和窗口的改变的比例不一样而溢出。但很神奇的是,并无出现这个问题。

实际状况,正好相反。以前须要单独设置来调整的地方,内容很天然的适配了它的容器。总之,样式表中须要尽可能少的media query,大多的组件须要更少的样式声明。

还有一个好处是,咱们能够不用单独为平板设备去制做一个单独的版本,由于这已经能够很好地在小屏幕上工做了。

下面是在过去须要去为每种不一样屏幕尺寸调整一个版本的导航组件。虽然在小屏幕下表现仍是不太完美,但能够不破坏它的总体性和功能性。

image

第二个问题,由于里面有不少的固定宽度,因此没法保持每行的字符都有理解的阅读长度。我在手机和平板电脑上,对字体大小进行了调整,使其保持在理想的阅读长度--移动设备阅读更重要。

主容器和文本的缩放比是不一样的,当浏览器改变大小时,一些文本会从新排列。由于我不想在设备改变方向时,致使阅读处置改变。这是没法避免的状况,咱们只能去测试一下主要设备的影响状况。还好,在移动设备上重排的影响并非太大。

最后,咱们对结果满意。毫无疑问,能够作更多关于排版的改进,咱们已经提升了网站的可读性。随着流体排版的经验愈来愈多,在下一个设计迭代中,主要的焦点会集中在排版和可读性上。

在现有网站上,使用流体排版技术的几点提示:

  1. 根据你的设计来,肯定最适合你的字体的最大最小值及缩放比。
  2. font-size使用em单位。若是你想在一个部分容器上(如导航),使用流体排版,给容器设置一个固定值。在这个容器中的em值,都是依赖于固定值的。
  3. 一样的,若是你只是把主体容器设置成流体排版。若是你把一个块容器的字体设置为流体的,那么全部这个容器中的em值都是流体的。
  4. 文本重排,若是只是在浏览器改变大小时,或设备改变方向时发生,不用过于在乎。
  5. 维护一个好的阅读长度是可能的。优先去考虑,手机或平板设备的理想阅读长度。

浏览器支持状况和BUGS

常常听到在Safari和特别是移动版的Safari,在同时使用视口单位和calc()表达式时,会出现明显的bug。但都没有提出什么具体的问题是什么,因此这里作了一些测试。

单独测试了calc()表达式和视口单位,以及同时使用它们来实现流体排版技术。在使用些技术时,没有发现什么问题。

在现代浏览器中,calc()和视口单位都能很好的工做。

在Safari 8如下和ie 11如下浏览器,当窗口中浏览器改变大小时,calc()表达式中的视口单位,不会从新计算。

能够经过media query来加以修正。

/* Older browsers */
  html { font-size: 16px; }
  
  /* Modern browsers only need this one */
  
  @media screen and (min-width: 25em){
    html { font-size: calc( 16px + (24 - 16) * (100vw - 400px) / (800 - 400) ); }
  }
  
  /* Safari <8 and IE <11 */
  @media screen and (min-width: 25em){
    html { font-size: calc( 16px + (24 - 16) * (100vw - 400px) / (800 - 400) ); }
  }
  @media screen and (min-width: 50em){
    html { font-size: calc( 16px + (24 - 16) * (100vw - 400px) / (800 - 400) ); }
  }

设置了Safary 8如下和ie 11如下,经过media query来从新计算字体大小。

老的浏览器则能过js来监听窗口的改变事件来从新计算字体大小。

能够在caniuse和查看支持状况

Image

image

使用流体排版

若是要使用流体排版,要先想清楚要使用哪一种解决方案。

若是整个设计都是流体的,能够考虑使用rem来定义流体,能够声明html字体大小为一个流体单位。可使用em和rem来定义全部设计部分。

当心选择你的最大最小字体。关于这点,你须要决定是否直接使用视口单位或对更加精确地缩放比率。若是是后者,使用Sass,LESS或PostCSS插件中的函数,能够更简单实现。

确保得到了正确的字体的最大最小值。这是问题的关键。一旦你选定了根元素的字体大小,其它的全部组件都是依赖这个值来计算的。项目中若是后面要调整这个值,那么整个项目都要调整。

不要忘记,在使用流体排版以前定义一个默认的字体大小。默认字体大小,用来在那些不支持流体字体大小的浏览器上使用的,这个值不须要和字体最小值 相同。

最后,考虑你的设计上的限制,如何去解决像标题级别和阅读长度的问题。能够参与文中的处理方法。若是你的标题组件,想和常规的文本,以不一样的比率进行缩放,在添加calc()表达式以前,先考虑可读性和样式代码的可维护性。

我但愿这能够给你启发,可让你思考在下个项目中那里能够用到流体排版。

基本阅读:

相关阅读:

扩展阅读:

原文:Truly Fluid Typography With vh And vw Units

原文连接:https://www.smashingmagazine.com/2016/05/fluid-typography/

相关文章
相关标签/搜索