CSS3 弹性盒布局说明(CSS3 Flexible Box Layout Explained)

来源:互联网 发布:理解信息与数据 编辑:程序博客网 时间:2024/06/06 00:07

弹性盒布局,或戏称为“flexbox”,是W3C工作草案(W3C Working Draft)很有趣的一部分。Flexbox规范依旧是个待变更的草案,所以你要时刻关注W3C的变化,等到大部分浏览器都支持它时,它将成为颠覆页面布局的新兴事物。

在此期间,我们可以用flexbox来试验,甚至将它运用在一些旧浏览器也能正确解析的网站上。直到它成为主流之前都将会是小范围的应用,例如bordr-radius,但是我们的工作时研究新技术,并在可能的地方使用它们。这就是说,当我们遇到页面布局的基本的东西,需要细心对待。

显示属性(The Display Property)


那么什么是flexbox,它的存在有什么意义?首先,让我们来看看目前页面布局的方式及其遇到的问题。

直到去年,我们中的大部分都还在使用表格(table)进行页面布局。好吧,或许不是去年!但是我怀疑正在读这篇文章的大部分人都曾因依赖表格而犯错。与是同时,这种布局方式的意义也十分重大,但它只能在一定程度上工作。然而,我们还是要面对table的语意含糊和结构的僵化。让我们穿过迷雾,看看未来:CSS 盒模式(CSS box model)。

CSS盒模式允许我们告诉浏览器如何显示一块内容,特别是如何让它作为一个box来显示。在我们仅仅复制粘贴clearfix到CSS文件中之前,我们左右摇摆,我们读了无数关于clearfix的文章,我们疲于理解什么是内联块(inline-block)。

基于IE6来测试网站,我们不得不为hasLayout及其后续带来的问题作一些调整:

* html #element {height: 1%;}

盒模式工作了,并且在多数情况下都运行良好。但是在网络初始的十几年里,这要求使用更多的复杂的方式来布局,而且多亏了Mr. Ethan Marcotte — 为浏览器及设备尺寸的解析做出巨大的贡献。

Percentage + Padding + Border = Trouble

关于当前的box模式有另一个问题:padding, marginborder的值都影响box的宽。看看下面的代码:

#element {width: 50%;border 1px solid #000;padding: 0 5px;}

这将不会得到一个相对于母元素(parent)50%的box,该box 宽度是parent的50%另加12 px(2px border + 10pxpadding)。你可以把padding设置为百分比(percentage),但是以percentage来设定 border 的宽度时会涉及到数学问题。

解决这个问题有两种方法。第一种是使用CSS3中的 box-sizing属性,其值设为 boder-box

#element {box-sizing: border-box;width: 50%;border 1px solid #000;padding: 0 5px;}

告诉浏览器元素的的宽度与高度包括padding 和 border。(注:content-box 不包括paddingborder

第二种方法是使用 flexbox。

多个问题,多个解决方法

W3C提供了一些列的解决方案:弹性盒模式(flexible box model),列(columns),模板(templates),位置浮动(positioned floats)和grid。

这些显示属性不少于16个值:inline, block, list-item,inline-block, table, inline-table, table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, table-caption, none 和 inherit.

现在我们可以添加第17个:box

生活在一个盒子里(Living In A Box)


让我们看看flexbox, 它带来了一个新的显示属性值(box)和不少于8个新的属性。下面是W3C对它的定义:

In this new box model, the children of a box are laid out either horizontally or vertically, and unused space can be assigned to a particular child or distributed among the children by assignment of flex to the children that should expand. Nesting of these boxes (horizontal inside vertical, or vertical inside horizontal) can be used to build layouts in two dimensions.

听起来很精彩,W3C工作草案进行了补充:

Flexbox… lacks many of the more complex text or document-formatting properties that can be used in block layout, such as “float” and “columns,” but in return it gains more simple and powerful tools for aligning its contents in ways that Web apps and complex Web pages often need.

弹性盒模式决定了盒模式在那里结束,W3C并指出更好的布局模式是为了应对Web应用程序和复杂的网页。下面是新的flexbox属性:

  • box-orient,
  • box-pack,
  • box-align,
  • box-flex,
  • box-flex-group,
  • box-ordinal-group,
  • box-direction,
  • box-lines.

为了简便起见,我们只使用官方的属性和值,但是不要忘了加上供应方的前缀。

一切都将改变

如果你花点时间读甚至是浏览最新的工作草案(2011.3.22),你将会注意到很多红色标记的地方,而且都有很好的理由。这个规范依旧在变。

值得注意的是,本文中使用的语法,和目前所有的浏览器,是已过时。在工作草案中,弹性盒模式的语法已经发生了改变。例如:

display: box;

将会变成:

display: flexbox;

其他的变化包括一些属性的拆分,(blox-flex变成flex-growflex-shrink)

,还有一些属性将被合并(box-orientbox-direction变成flex-direction)。事实上,任何以box-开头的属性都将变成以flex-开头。所以要时刻关注规范和浏览器。

PaRappa the Wrapper

使用flexbox经常需要多加一个或两个div ,应为任何一个flexbox元素的母元素都需要 box属性。在此之前,你可以用下面的方式:

<div style="float: left; width: 250px;"> Content here </div><div style="float: right; width: 250px;"> Content here </div>

现在用flexbox,将会变成:

<div style="display: box">  <div style="width: 250px"> Content here </div>  <div style="width: 250px"> Content here </div></div>

或许你已经要放下这篇文章了,觉得这个额外的元素完全是浪费感情。这是可以理解的。但是当你掌握CSS后,就会发现这个小小的div的价值所在。事实上,你将常常已经有了这个包含元素(不一定是div)去添加 display: box

在更广泛的注意,有时你需要表象标志。这只是它的运作方式。我发现,特别是涉及到跨浏览器支持时,我们必须添加表象标记,例如说IE6。我并不是说一定要用“div-itis”,但由于我们都使用HTML5元素的标记,就会发现sections常常需要 div容器。

Box-flex
让我们先从box-flex属性着手。没有box-flex很多功能都无法实现。简而言之,在一个元素相对其父元素(parent)过大或过小时,box-flex能告诉浏览器如何来调整它.
假设有三个子元素(children)要放到一耳光容器(parent)中,而且要让他们一次排列好。换句话说就是让children向左浮动。由于 padding ,margin,和border的存在,children的总宽度可能比parent宽度大,那么就必须要指定宽度和百分比来控制宽度。
假设3个aside宽度为320px(包括padding margin 和order),放在了宽度为920px的parent中,这种情况下,内容便溢出了。但是如果给parent添加属性:display:box,给每个aside添加属性:box-flex:1。内容溢出的问题便被解决了。那么问题到底是怎么被解决的呢?
box-flex属性告诉浏览器如何来调整box(即parent)的宽度,原理是box载入后,分配其的未使用空间到每一个aside ,box-flex:1是比例因子。每个aside尺寸为320px+20px左右的padding,那么共有1080px ((320+20*2)*3),多出160px。由于现在每个aside是弹性的,将会相应的缩小。但是注意padding不变。计算如下:
160 pixels ÷ 3 asides = 53.333 pixels to be taken off each aside.320 pixels – 53.333 = 266.667 pixels
现在每个aside会被压缩到266.667px.  这个特性十分有用,它会让padding、margin和border保持不变。通过改变元素的尺寸来适应盒的大小。盒的大小如果改变它也会做出适应性的变化。
当然,你也可以给每个元素设置不同的属性值,这样就会有不同的显示比例。现假如有三个依次排列的元素,宽都为100px,padding都为20px,置于宽920px的盒中:
添加box-flex属性:
.box1 { box-flex: 2; }.box2 { box-flex: 1; }.box3 { box-flex: 1; }
每个aside宽度为140px(100px + 40px padding),共420px,就意味着左边有500px的待填补区域。由比例关系,它们分担空白的比例是2:1:1,这又以下计算:
.box1 = 350px (100px + 250px) + 40px padding.box2 = 225px (100px + 125px) + 40px padding.box3 = 225px (100px + 125px) + 40px padding
注意空白的分配只加在元素本身上,padding保持不变。其实关于数学计算的问题也不大用担心,浏览器会自动帮你搞定。


0 0
原创粉丝点击