Flexbox 非常棒,并且肯定是未来布局的一部分。语法在过去几年中发生了很大变化,因此出现了 “旧”和“新” 语法。但是,如果我们将旧的、新的和介于两者之间的语法编织在一起,就可以获得不错的浏览器支持。特别是对于一个简单且可能是最常见的使用场景:顺序控制网格
HTML
一个语义上无意义的包装器围绕着三个主要区域,并将设置 flexbox 上下文。每个区域都用语义标记起来,并将被转换为列。
<div class="page-wrap">
<section class="main-content" role="main">
Main content: first in source order
</section>
<nav class="main-nav" role="navigation">
Links
</nav>
<aside class="main-sidebar" role="complementary">
Sidebar
</aside>
</div>
最终结果看起来像这样

Flexbox 上下文
我们需要将列的容器设置为 flexbox 显示上下文。仅通过这样做,此元素的所有直接子元素都会成为 flex 项目。无论它们之前是什么,现在都是 flex 项目。
我们马上需要将旧的、新的和过渡的语法编织在一起。顺序在这里很重要。由于 display 属性本身没有前缀,我们需要确保我们没有用旧的语法覆盖新的语法,以便仍然(可能永远会)支持这两种语法的浏览器。
.page-wrap {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
控制列宽
我们的目标是 20% / 60% / 20% 的网格。
第一步是将我们的主要内容设置为 60%。
第二步是将外部侧边栏设置为平均填充剩余空间。
我们再次需要将旧的、新的和过渡的语法编织在一起。
.main-content {
width: 60%;
}
.main-nav,
.main-sidebar {
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
width: 20%; /* For old syntax, otherwise collapses. */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
在新语法中,设置侧边栏的宽度不是必需的,因为它将平均填充剩余的 40%,使它们都成为 20%。但我发现没有设置它会导致旧语法出现一些宽度折叠。
列重新排序
我们希望主要内容在视觉上出现在中间,但在源代码顺序中排在第一位。在 flexbox 中很容易,但当然我们需要将新的、旧的和过渡的语法编织在一起。
.main-content {
-webkit-box-ordinal-group: 2; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-ordinal-group: 2; /* OLD - Firefox 19- */
-ms-flex-order: 2; /* TWEENER - IE 10 */
-webkit-order: 2; /* NEW - Chrome */
order: 2; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.main-nav {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
.main-sidebar {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
-ms-flex-order: 3;
-webkit-order: 3;
order: 3;
}
浏览器支持
如果您执行所有这些编织,您将获得
- Chrome 任何版本
- Firefox 任何版本
- Safari 任何版本
- Opera 12.1+
- IE 10+
- iOS 任何版本
- Android 任何版本
最大的限制因素当然是 IE,但除此之外,它非常好。如果您正在制作网站的移动特定版本,您的情况会更好。如果有人可以在 Windows Phone 上测试它,请告诉我。
Firefox 19- 有一些错误,您需要注意它。例如,在这个演示中,我无法找到一种方法来强制侧边栏实际上是 20%。它们只是折叠到内部内容的宽度,这有点随意,因为它是文本。我还需要在主要内容 (60%) 上使用 -moz-box-flex: 1;
,否则它会伸展到最宽段落的宽度,就像它具有 white-space: nowrap
一样,这对我来说简直不可思议。
演示
Check out this Pen!
Flexbox 绝对值得学习。感谢您提供这个清晰的教程,Chris。:)
很棒的信息,Chris,对我来说,我想知道(除了在视觉上重新排序内容之外)使用 Flex 相比传统代码(例如带有浮动的简单宽度)有什么好处?
这篇演讲的文字可能有助于解释背景:http://adactio.com/journal/6049/
不错的文章。Flexbox 的粉丝可能想看看 Flexy Boxes Flexbox 游乐场,它生成类似于这里编写的传统和现代 flexbox 语法。
感谢作者 Chris Coyier。使用 flexbox 有道理,特别是在我们使用现代浏览器(希望在不久的将来)时。
Pete B:您添加了指向 Flexy Boxes 的链接,这很有意义:一个帮助我们开始使用 flexbox 的 Web 应用程序——感谢。
太可惜了,没有低于 IE 10 的支持。那样就完美了。
html5please.com 建议现在避免使用它 http://html5please.com/#flexbox
这是一个 Flexbox 的 polyfill,我还没有测试过 https://github.com/doctyper/flexie
但是由于它甚至兼容 IE9,我不会将其用于桌面网站。
如果您正在考虑使用 polyfill,您也可以使用 Modernizr 在您的 CSS 中直接针对 .flexbox 和 .flexboxlegacy。我的意思是,除非您非常希望您的 flex 盒布局显示在 IE9 中。在处理这类事情时,我倾向于放弃旧的浏览器。如果它们没有 flex 盒,那么它们只会获得非 flex 盒布局。再说一次,我只在使用媒体查询针对的较大屏幕上使用 flex 盒,所以是的,我不建议将 flex 盒用作默认布局。
有人知道一个好的 polyfill 可以用这种语法为 IE8 或至少 IE9 提供支持吗?有人试过 Flexie 吗?
这不是一个完整的 polyfill,但以下是如何在 IE8 和 IE9 中执行类似操作:http://codepen.io/CalebKester/pen/eLDzm
注意,这很快就完成了,但向您展示了它仍然可以完成核心布局。您必须重新组织您的 html,但这并不算太糟糕。
FlexBox 的优势(回答 Andy Howells 的问题)不仅是排序,而且主要是自动填充空间和非常巧妙的定位
• 您可以在父元素中以更好的方式定位元素(居中、居中底部、右上角等),而无需使用
position: absolute;
• 您可以创建等高列和自动填充水平空间的列(如这里所示),并且这些列也可以按比例填充空间。
• 所有定位都变得更简单了(尽管它确实是一个几乎全新的语法要学习)。
在我谷歌搜索 flexbox polyfill 并偶然发现这个名为 Flexie 的很棒的库之前,我从未真正意识到 flexbox 的强大功能。
http://flexiejs.com/playground/?random
不幸的是,它只支持旧模型,但似乎运行得很好。如果没有其他,我链接的这个很棒的游乐场可以让你很好地了解 flexbox 的功能。我真的一无所知!
演示在 Windows Phone 8 上运行良好。
是的,运行良好 - 不过这并不奇怪,因为移动版 IE10 基本上运行在与桌面版相同的渲染引擎上。
提醒一下,flexie.js 使用的是旧语法,所以你最好在它更新之前避免使用它。开发者发布了它目前大约完成了 35%。
https://github.com/h5bp/html5please/pull/221
诺基亚 Lumia Windows Phone IE。如果你在 CodePen 的详细信息模式下旋转到横向,容器会占用一半宽度。纵向在编辑模式下看起来还可以,但在详细信息模式下不行。
CodePen 在纵向模式下也不会占用全部宽度。如果你需要的话,我可以发送截图。
在我看来,如果你想使用 flexbox,最好的方法是只使用最新的语法,并且简单地为不支持它的浏览器提供一个备用布局。
示例(一个位于 flexbox 容器内的元素)
当然,为同一个网站创建两个完全不同的布局。就好像我们本来就没有足够的工作要做似的。
非常棒的东西,Chris。想知道有没有人知道 BlackBerry 上的支持情况。我们公司超过 70% 的移动流量来自 BlackBerry 设备,这真的很令人沮丧。不幸的是,BrowserStack 目前不支持 BlackBerry 设备 (._. )
嘿,Chris!
在 IE9 移动版(诺基亚 Lumia 800)上测试,div 保持静止,就像你什么也没做一样。
以前从未听说过 Flexbox。感谢你写了一篇关于使用 Flexbox 的详细文章。我喜欢基于优先级对元素进行排序,非常酷。我认为你的代码还有很大的改进空间,但仍然非常有用。我在 IE10 上测试过,它运行良好。
很酷!以下是本文中的所有内容,以 Sass mixin 的形式:http://codepen.io/bensmithett/pen/neuyI
感谢你提供的 Sass mixin,Ben!我自作主张地将其转换为 SCSS,以便任何想使用该语法的用户都能使用它。
http://codepen.io/adamjohnson/pen/savzI
实际上,有一些东西无法在规范之间直接转换,因此你不能像那样将你的值直接放入带前缀的属性中。规范之间存在细微差异,例如“flex-start”与“start”或“space-between”与“justify”。“order”属性从 0 开始索引,而“box-ordinal-group”从 1 开始索引。
Compass 用户可以使用这些 mixin(我计划在确信它们很棒后将它们提交给 Compass 项目):https://gist.github.com/cimmanon/4461470
需要注意的是,没有一个遵循 2009 年规范的浏览器曾经实现过换行。尽管 Firefox 添加了对标准规范的支持,但他们会暂时排除对换行的支持。
我刚用 FF19 beta 测试了一下。必须在 about.config 中设置
layout.css.flexbox.enabled = true
,但这使得它即使在没有-moz-box-flex: 1;
的情况下也能工作。哦,
-moz
前缀很快就会被删除(参见这里)。看来 Dominic 是对的。将
layout.css.flexbox.enabled
更改为true
似乎解决了你在 Firefox 中遇到的问题。尽管如此,这篇文章仍然很棒,再次感谢你,Chris。我期待着在不久的将来能够在所有浏览器中可靠地使用 Flexbox。很高兴看到也使用了 ARIA 路标;)
我做了一个小实验,玩了一下 flex box,并创建了一种灵活的字体。
http://etienne.pouvreau.free.fr/#fantome
当然,只是为了好玩和测试;-)
你的帖子将帮助我更好地完成它……谢谢。
相当不错的方法,将来会被广泛使用。
如果 Compass 也有一个可以为我做所有这些事情的 mixin 就好了……
我在 flexbox 中发现的一个主要限制是它只对直接子元素有效。当你的内容元素是列占位符的一部分,而不是像本文中展示的那样单个主要父元素的一部分时,这是一个主要问题。关于这个问题的完整解释
http://stackoverflow.com/questions/14148162/does-the-css-flexbox-module-work-on-direct-child-elements-only
我唯一的主要担忧是缺乏 IE 支持(我认为是针对 < IE10 的)。在这个阶段,我无法证明在商业环境中使用 Flexbox 的合理性。
很高兴看到 Flexbox 有这么好的支持,但是如果你必须为几乎每个 IE 都想出一种替代方案,那它又有什么意义呢?
我是优雅降级的大力支持者,通常不太关心旧版 IE,但在 Flexbox 的情况下,它还没有准备好用于生产环境,直到旧版 IE 消失(这不会发生)或者出现一个 polyfill。如果你只需要关心 Webkit,即应用程序,那么 Flexbox 绝对是最佳选择,但对于一个普通的网站来说,在我看来,这实在太麻烦了。
顺便说一下,这里是我对新的 Flexbox 语法的简要概述:http://www.sitepoint.com/flexbox-css-flexible-box-layout/
Firefox 在(设置百分比宽度)[https://bugzilla.mozilla.org/show_bug.cgi?id=529761] 方面存在一个错误。
人们又
<
发明了表格>。
除了 flexbox 是语义化的和响应式的。
对的……
好文章 :)
它非常易于使用和实现。
Flexbox 让我重新对 CSS 感到兴奋。如果只有一种可靠的 polyfill,至少可以用于 IE9 就好了。
非常感谢你,Chris……我在 IE10 上测试过,运行良好!
很棒的信息。这篇文章展示了 Flexbox 的现状(2013 年 2 月 22 日):真是个灾难。
看起来很有趣,我绝对能看到它的好处,但是 IE10+ 的支持对我来说是致命的。
这种方法是否需要“跳到导航”链接,或者它是否足够快,可以跳过内容进行制表键操作?
@Peter,我不确定我是否误解了你的评论,但你可以使用 WAI-ARIA 路标角色,而不是使用“跳到导航”链接(我认为应该是“跳到主要内容”或“跳过导航”)。
根据 WAI-ARIA 最佳实践编辑草案:
地标是相对于 WAI-ARIA 之前使用的基本“跳过到主要内容”技术来说的巨大改进。如果可能,最好使用地标。
干杯。
不应该源代码/DOM 和视觉顺序匹配吗?
110% 同意。
不仅会造成可用性问题,而且还会造成严重的 SEO 影响。
您的源代码顺序应反映您的内容层次结构。
通常,移动版 IE 与其桌面版具有相同的特性。因此,带有 IE9 的 Windows Phone 7 不支持 Flexbox,但在带有 IE10 的 Windows Phone 8 上,它应该可以与您的“中间”解决方案一起使用。
我实际上已经创建了一个LESS Mixin 项目 来简化此操作。查看演示页面!
如何在 Flexbox 中根据元素的顺序对元素进行样式设置?nth-child(n)、first-child 等在标记中的位置有效
但是如何对 order:1 的元素进行样式设置。
这是否可行,因为这需要 CSS 与另一个样式的存在进行匹配???
这有点像 hack,但要解决 FF 百分比错误,可以使用 -moz-calc 和 vw 单位。从完整的视窗宽度中减去 body 边距(两次 8px)和填充(两次 2em),然后乘以小数而不是百分比(.2):
-moz-calc((100vw - 4em - 16px) * 0.2)
。对于除最基本公式之外的任何公式,这显然不是一个好方法。想知道为什么页面在提交时被刷新,而不是使用某种 jQuery 来更新页面!
抱歉,这些都是垃圾!我只是在测试。
随意删除我的帖子。
这真是太棒了!终于,CSS 有了可以让我们使用固定宽度侧边栏和灵活宽度内容列的东西!到目前为止,只有该死的旧表格才能做到这一点!
我做了一个小测试,将最小宽度和最大宽度与基于百分比的宽度一起设置到侧边栏,并让内容不设置宽度。它运行良好。如果我降低浏览器宽度,内容会变得非常窄,而侧边栏保持最小宽度。如果我在 3 个显示器中打开浏览器,内容会变得非常大,而侧边栏会保持最大宽度!如果我在内容中使用列 CSS 属性,我就能获得一个非常易读的网站,该网站针对大显示器进行了优化!
现在我必须找到一种方法来隐藏/移动到奇怪、丑陋、魔鬼出生的手机的底部侧边栏 :p
我写了一个测试用例。在 Chrome 中看起来还不错,但似乎在 iOS 中不起作用。
iOS 6.1 使用的是旧语法。
http://jsbin.com/aqunam/1372/edit/
这个概念很简单,我有一个包含三个项目的容器框。但是,宽度在容器中没有平均分配。
我做错了什么?
使用表格和 3d 变换
http://codepen.io/yukulele/pen/KLsnv
jQuery 代码,更短……。
$(document).ready(function(){
$( “.main-content” ).insertAfter( $( “.main-nav” ) );
});
是否可以使用侧边栏的固定宽度?