分享

使用 CSS 弹性框

 培强ren 2016-06-18

CSS3 弹性框(Flexible BoxFlexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当排布行为的布局方式对很多应用程序来说,由于不使用浮动,且弹性容器的外边距也不会与其内容的外边距合并,弹性框模型比起方框模型要好一些。

许多设计师会发现弹性框模型易于使用。弹性框中的子元素可以在各个方向上进行布局,并且能以弹性尺寸来适应显示空间。由于元素的显示顺序与它们在源代码中的顺序无关,定位子元素变得更容易,并且能够用更简单清晰的代码来完成复杂的布局。这种无关性是特意限制于视觉呈现上的,语音顺序以及基于源代码顺序的导航均不受影响。

注意: 虽然 CSS 弹性框布局规范 还处于最终征求意见稿 (Last Call Working Draft)阶段(参见最新编辑草案),并非所有浏览器都实现了弹性框的所有功能。但,这么说吧,现在全线产品对弹性框都有良好支持。最新的兼容性状况可以查看每个具体属性的兼容性表格获取。

弹性框概念

弹性布局在定义方面是指调整其内项目宽高从而在任何显示设备上实现对可用显示空间最佳填充的能力。弹性容器扩展其内项目来填充可用空间,或将其收缩来避免溢出。

弹性框布局算法是方向无关的,与此相对的,块级布局侧重于垂直方向、行内布局侧重于水平方向。虽然块级布局用于页面行之有效,但其仍缺乏足够的定义来支持那些必须随用户代理(user agent)不同或设备方向从水平转为垂直等各种变化而变换方向、调整大小、拉伸、收缩的应用程序组件。 弹性框布局主要适用于应用程序的组件及小规模的布局,而(新兴的)网格布局则针对大规模的布局。这二者都是 CSS 工作组为在不同用户代理、不同书写模式和其他灵活性要求下的网页应用程序有更好的互操作性而做出的更广泛的努力的一部分。

弹性框相关词汇表

关于弹性框的讨论已经从诸如水平/行内轴和垂直/块级轴这些术语中解放出来,与此同时,需要有一套新的术语来正确描述此模型。在学习下面的词汇项目时请对照下图。图中是一个 flex-direction 属性为 row的弹性容器,意味着其内的弹性项目将根据既定书写模式沿主轴水平排列,其方向为元素的文本流方向,在这个例子里,为从左到右。

弹性布局相关名词

弹性容器(Flex container)
包含着弹性项目的父元素。通过设置 display 属性的值为 flexinline-flex 来定义弹性容器。
弹性项目(Flex item)

弹性容器的每个子元素都成为弹性项目。弹性容器直接包含的文本将包覆成匿名弹性项目。

轴(Axis)

每个弹性框布局包含两个轴。弹性项目沿其依次排列的那根轴称为主轴(main axis)。垂直于主轴的那根轴称为侧轴(cross axis)

  • flex-direction 属性确立主轴。
  • justify-content 属性定义了在当前行上弹性项目沿主轴如何排布。
  • align-items 属性定义了在当前行上弹性项目沿侧轴默认如何排布。
  • align-self 属性定义了单个弹性项目在侧轴上应当如何对齐,这个定义覆盖由 align-items 所确立的默认值。
方位(Direction)

弹性容器的各个边(主轴起点(main start)/主轴终点(main end)侧轴起点(cross start)/侧轴终点(cross end))描述了弹性条目流的起点与终点。它们具体取决于弹性容器的主轴与侧轴以及由 writing-mode 确立的方向(从左到右、从右到左,等等)。

行(Line)

根据 flex-wrap 属性,弹性项目可以排布在单个行或者多个行中。此属性控制侧轴的方向和新行排列的方向。

尺寸(Dimension)

根据弹性容器的主轴与侧轴,弹性项目的宽和高相应称为主轴尺寸(main size)侧轴尺寸(cross size)

指派弹性框

为要使用此样式的元素指派 CSS,需按以下方式设置 display 属性:

display : flex

或者

display : inline-flex

这样做将元素定义为弹性容器,其子元素则成为弹性项目。值 flex 使弹性容器成为块级元素。值 inline-flex 使弹性容器成为单个不可分的行内级元素。

注意:厂商前缀标记应当附加给 display 属性值,而不是加给 display 属性本身。例如:display : -webkit-flex

弹性项目须知

弹性容器直接包含的文本将自动包覆成匿名弹性项目。不过,只包含空白的弹性项目不会被渲染,就如同对其指派 display: none

对于弹性容器的绝对定位子元素来说,其静态位置参照弹性容器的内容框的主起始角确定,而后依此完成此元素的定位。

相邻的弹性元素其外边距不会互相合并。使用 auto 外边距可以吸收掉水平或垂直方向上的额外空间,这可以用于对齐或分隔相邻的弹性项目。更多细节请参考 W3C 弹性框布局模型规范中的 Aligning with 'auto' margins

为了确保弹性项目有合理的默认最小尺寸,使用 min-width:automin-height:auto。对于弹性项目,属性值 auto 使项目的最小宽/高在计算中不会小于其内容的实际宽/高,这样可以保证项目渲染得足够大以容纳其内容。更多细节请参考 min-widthmin-height

不像 CSS 中的其他对齐方法,弹性框的对齐属性将进行“真正的”居中对齐。这意味着即使弹性条目溢出了弹性容器,它依然保持居中。不过这在某些时候可能会有问题。如果溢出超过了页面的上边缘或左边缘(在从左到右的语言中,比如英语;在诸如阿拉伯语这样从右到左的语言中这个问题出现在右边缘),则虽然那些地方确实有内容,却无法滚动到那些位置。在未来的发布版本里,对齐属性将会有所扩展,使其包含有“安全”选项。目前,如果操心这点,可以改用外边距来达成居中效果,因为外边距会用比较“安全”的方式来响应变化,出现溢出时将停止居中。对需要居中的弹性项目应用自动外边距来替代 align- 属性的使用。对弹性容器中第一个和最后一个弹性项目的外侧边缘应用自动外边距来替代 justify- 属性。自动外边距会自动伸缩来占满剩余空间,当有剩余空间存在时弹性项目将会居中,如果没有则切换至常规对齐方式。不过,如果尝试在多行的弹性框中用基于外边距的居中方法来替代 justify-content,很不幸,必须对每一行的第一个和最后一个弹性项目应用外边距。除非能够事先预测每一行都结束于哪个元素,否则无法放心地在主轴方向上用基于外边距的居中方法来替代 justify-content 属性。

重新提一下,元素的显示顺序与它们在源代码中的顺序无关,这种无关性只影响视觉呈现,语音顺序以及基于源代码顺序的导航均不受影响。order 属性并不影响语音和导航的次序。因此开发者们必须小心,合理地安排元素在源代码中的顺序,以免破坏文档的可访问性。

弹性框相关属性

不影响弹性框的属性

由于弹性框使用了不同的布局算法,某些属性用在弹性容器上没有意义:

示例

基本的弹性布局示例

这个基本的示例展示了如何对元素应用弹性布局,以及在弹性布局状态下相邻元素的行为方式。

html lang='en'> head> style> .flex { /* 基本样式 */ width: 350px; height: 200px; border: 1px solid #555; font: 14px Arial; /* 建立弹性框 */ display: -webkit-flex; -webkit-flex-direction: row; display: flex; flex-direction: row; } .flex > div { -webkit-flex: 1 1 auto; flex: 1 1 auto; width: 30px; /* 让过渡表现良好。(从/到'width:auto'的过渡 至少在 Gecko 和 Webkit 上是有 bug 的。 更多信息参见 http:///731886 ) */ -webkit-transition: width 0.7s ease-out; transition: width 0.7s ease-out; } /* colors */ .flex > div:nth-child(1){ background : #009246; } .flex > div:nth-child(2){ background : #F1F2F1; } .flex > div:nth-child(3){ background : #CE2B37; } .flex > div:hover { width: 200px; } style> head> body> p>Flexbox nuovop> div class='flex'> div>unodiv> div>duediv> div>trediv> div> body>html>

圣杯布局示例

此示例展示了弹性框根据不同屏幕分辨率动态改变布局的能力。下图说明了这种转换。

HolyGrailLayout.png

这里展示的正是针对浏览器窗口的页面布局必须为智能手机窗口优化的场景。不仅元素的尺寸需要缩减,其呈现顺序也需要改变。弹性框让这变得很简单。

html lang='en'> head> style> body { font: 24px Helvetica; background: #999999; } #main { min-height: 800px; margin: 0px; padding: 0px; display: -webkit-flex; display: flex; -webkit-flex-flow: row; flex-flow: row; } #main > article { margin: 4px; padding: 5px; border: 1px solid #cccc33; border-radius: 7pt; background: #dddd88; -webkit-flex: 3 1 60%; flex: 3 1 60%; -webkit-order: 2; order: 2; } #main > nav { margin: 4px; padding: 5px; border: 1px solid #8888bb; border-radius: 7pt; background: #ccccff; -webkit-flex: 1 6 20%; flex: 1 6 20%; -webkit-order: 1; order: 1; } #main > aside { margin: 4px; padding: 5px; border: 1px solid #8888bb; border-radius: 7pt; background: #ccccff; -webkit-flex: 1 6 20%; flex: 1 6 20%; -webkit-order: 3; order: 3; } header, footer { display: block; margin: 4px; padding: 5px; min-height: 100px; border: 1px solid #eebb55; border-radius: 7pt; background: #ffeebb; } /* 窄到已不足以支持三栏 */ @media all and (max-width: 640px) { #main, #page { -webkit-flex-flow: column; flex-direction: column; } #main > article, #main > nav, #main > aside { /* 恢复到文档内的自然顺序 */ -webkit-order: 0; order: 0; } #main > nav, #main > aside, header, footer { min-height: 50px; max-height: 50px; } } style> head> body> header>headerheader> div id='main'> article>articlearticle> nav>navnav> aside>asideaside> div> footer>footerfooter> body>html>

试验场

有几个在线弹性框试验场可以进行各种实验:

务必牢记

描述弹性项目如何排布的算法有时会极其棘手。在使用弹性框进行设计时,请考虑以下几点,以免碰到不好的意料外状况。

弹性框的排布与书写模式是一致的,这意味着排布的主轴起点主轴终点根据的是开始结束的位置。

侧轴起点侧轴终点依赖于开始前面的位置定义,而后者依赖于 direction 的值。

只要 break- 属性的设置值允许,在弹性框布局中是可以存在分页的。CSS3 中的 break-afterbreak-beforebreak-inside,以及 CSS 2.1 中的 page-break-beforepage-break-afterpage-break-inside 属性在弹性容器上、弹性项目上和弹性项目内均可以使用。

浏览器兼容性

特性 Firefox (Gecko) Chrome Internet Explorer Opera Safari
基础支持(单行弹性框) 18.0 (18.0)[6]-moz[2]
22.0 (22.0)
21.0-webkit
29.0
11[3] 12.10-webkit[5] 6.1-webkit[1]
多行弹性框 28.0 (28.0) 21.0-webkit
29.0
11[3] 12.10[5]
15 -webkit
6.1-webkit[1]
特性 Firefox Mobile (Gecko) Firefox OS Android IE Phone Opera Mobile Safari Mobile
基础支持(单行弹性框) 18.0 (18.0)-moz[2]
22.0 (22.0)

1.0-moz[2]
1.1

2.1-webkit[4]
4.4
11 12.10[5]
15-webkit
7-webkit[1]
多行弹性框 28.0 (28.0) 1.3 2.1-webkit[4]
4.4
11 12.10[5]
15-webkit
7-webkit[1]

[1] Safari 在版本 6.0 (iOS.1)以前支持的是规范的一个与现有版本不兼容的旧版草案。Safari 6.1(以及 iOS 7 上的 Safari)已更新为支持最终版本。

[2] 直到 Firefox 22 位置,用户必须修改 about:config 设置,将 layout.css.flexbox.enabled 改为 true 才能激活对弹性框的支持。从 Firefox 22 到 Firefox 27,此设置项默认为 true,而 Firefox 28 中取消了此设置项。

[3] Internet Explorer 10 支持的是规范的一个与现有版本不兼容的旧版草案;Internet Explorer 11 已更新为 支持最终版本。

[4] Android 浏览器直到 4.3 为止支持的是规范的一个与现有版本不兼容的旧版草案。Android 4.4 已更新为支持最终版本。

[5] 在 Opera 12.10 的弹性框初始实现中是没有前缀的,但 Opera 版本 15 到 16 和 Opera Mobile 的 15 到 19 需要 -webkit. 在 Opera 17 及 Opera Mobile 24 中再次取消了前缀。

[6] 直到 Firefox 29 为止,在弹性项目上指定 visibility: collapse 将使其被视为 display: none 处理,而预期的行为是被视为 visibility: hidden。建议的处理方式是在弹性项目上使用 visibility:hidden,这样其行为应当与指派了 visibility:collapse 一致。更多信息,参考 bug 783470.

参见

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多