Flexbox布局介绍
Flexbox是什么意思呢?
flexible(形容词):能够伸缩或很容易变化,以适应外界条件的变化。
box(名词):通用的矩形容器。
弹性盒模型(The Flexible Box Module),又叫作Flexbox,它的出现具有非常重要的意义。它挖掘了CSS盒模型基本原理,给我们提供了功能更加强大、更有用的模块布局方式。它在CSS中的定义和标记非常简单,通过媒体查询的方式就可以适配和响应变化。不需要清除浮动,不需要使用额外的框架,也不需要使用大量冗余的代码来实现响应式栅格布局。Flexbox做了所有这些看起来略显烦琐的工作,所以我们使用起来非常简单————定义flex容器,在容器里面再定义所需的flex项目。
Flexbox布局究竟是什么
CSS3的Flexible Box(或者说Flexbox)是一种布局模式,这种布局模式适用于不同的屏幕尺寸和不同的显示设备,它给页面元素提供了适配这些情况的能力。
我们可以在一个flex容器中标记一些flex子元素,通过CSS来定义布局。Flexbox有很多属性用来定义布局 ,这些属性结合起来能够实现更多的效果。
flex-direction:通过这个属性,我们能够指定felx容器的子元素是按和地显示还是按列显示。我们也可以通过这个属性来定义元素按升序显示还是按降序显示。
justify-content:通过这个属性 ,可以声明浏览器如何分配元素之外的可用空间。比如有3个节点,它们组合起来一共占据了容器50%的空间,我们能够指定元素是集中在左边、右边还是中间,或者是均匀地从左往右分布,或者其他的一些方式。
flex-wrap:通过这个属性,我们能够指定当flex子元素的总宽度超出了容器的空间时,是否换行显示。
案例:
栅格系统
默认盒模型的行为导致在布局中通常会使用float和inline-block等hacks方式来实现,这些方式都有很多人在使用。Flexbox能让我们仅仅使用很少的几行CSS代码就轻松开出一套功能强大、可扩展的栅格系统。
在传统的栅格系统中,我们必须用某种方式说明在一行中包含有多少个内容节点,然后给每个内容节点设置相应的宽度。通过Flexbox,我们可以在一行中放任意数目的项目,而且这些项目的宽度可以根据容器宽度自动分配。换句话说,在 CSS中,我们可以通过一些标记来达到目的,而不用关心一行中放置多少个内容节点,代码如下。
<div class="grid"> <div class="grid_row"> <div class="grid_item">1</div> <div class="grid_item">2</div> </div> <div class="grid_row"> <div class="grid_item">1</div> <div class="grid_item">2</div> <div class="grid_item">3</div> </div> <div class="grid_row"> <div class="grid_item">1</div> <div class="grid_item">2</div> <div class="grid_item">3</div> <div class="grid_item">4</div> </div> </div>
.grid{border:1px solid #e7e7e7;} .grid_row{display: flex;} .grid_item{flex:1; padding:12px; border:1px solid #e7e7e7;}
这样就实现了一个栅格系统。.grid_row定义了一个flex容器,每一个.sub-item的节点作为felx容器中的子元素。在.sub-item中的flex:1使得所有的项目等宽分布在容器中。现在你可以建立很多的栅格行,每行中的项目数量不限。它们会在容器中等宽分布,你不需要增加任何其它的CSS样式了。
那么如果想要得到一个列布局该怎么做呢?如果你想让栅格容器中的项目按列来分布,只要简单地在.grid-row样式中声明flex-direction:column; 就可以实现。在这种情况下,我们只做了一点修改就创建了一个简单的快速响应布局,我们修改后的样式看起来像这样。
<div class="grid"> <div class="grid_row grid_row--sm"> <div class="grid_item">1</div> <div class="grid_item">2</div> <div class="grid_item">3</div> <div class="grid_item">4</div> </div> <div class="grid_row grid_row--md"> <div class="grid_item">1</div> <div class="grid_item">2</div> <div class="grid_item">3</div> <div class="grid_item">4</div> <div class="grid_item">5</div> <div class="grid_item">6</div> <div class="grid_item">7</div> </div> <div class="grid_row grid_row--lg"> <div class="grid_item">1</div> <div class="grid_item">2</div> <div class="grid_item">3</div> </div> </div>
.grid{border:1px solid #e7e7e7;} .grid_row{display: flex; flex-direction:column;} .grid_item{flex:1; padding:12px; border:1px solid #e7e7e7;} @media all and (min-width:480px) { .grid_row--sm{ flex-direction: row; } } @media all and (min-width:720px){ .grid_row--md{ flex-direction: row; } } @media all and (min-width:960px){ .grid_row--lg{ flex-direction: row; } }
一个简单的响应式栅格系统的CSS代码只有几行。这个系统的适应性非常强,你甚至可以嵌套栅格,而不必担心它的展现不够理想。
圣杯布局
圣杯布局在网页设计中非常著名,它在Web应用刚出现时就很出名,到今天圣杯布局依然扮演着重要角色,尤其是在内容丰富的网站中使用非常多。它利用float、margin负值和最小宽度(min-width)来确保布局不相冲突。这种方式如果要满足现有响应式布局的需求,就需要用到大量的运算、浮动清除等一些特殊的手 段。如果一个场景可能需要修改侧边栏的宽度,那你就不行不借助数学运算或者其他方式来实现。
Flexbox布局能够有效地缓解这些让人头疼的问题,我们可以指定列布局或者行布局,也可以明确指定元素的分布顺序,就算不按照它们在页面中出现的顺序也可以。下面是一个典型的圣杯布局。
<body class='holy-grail'> <header class="holy-grail_header">This is the header</header> <main class="holy-grail_body"> <div class="holy-grail_content"> <p>This is the main content</p> <p>This is the main contentThis is the main content</p> <p>This is the main contentThis is the main content</p> <p>This is the main contentThis is the main content</p> <p>This is the main contentThis is the main content</p> <p>This is the main contentThis is the main content</p> <p>This is the main contentThis is the main content</p> <p>This is the main contentThis is the main content</p> </div> <div class="holy-grail_sidebar holy-grail_sidebar--first">Sidebar1</div> <div class="holy-grail_sidebar holy-grail_sidebar--second">Sidebar2</div> </main> <footer class="holy-grail_footer">This is the footer</footer> </body>
.holy-grail{display: flex; flex-direction:column;} .holy-grail_header,.holy-grail_footer{flex:0 0 100%; background-color: #ccc; } .holy-grail_body{display: flex;} .holy-grail_sidebar{background-color: #999;} .holy-grail_sidebar--firse{order:1;} .holy-grail_sidebar--second{order:3;} .holy-grail_content{order:2; background-color: green;} @media all and (min-width:480px){ .holy-grail_body{ flex-direction:column;} } @media all and (min-width:720px){ .holy-grail_body{ flex-direction:row;} .holy-grail_sidebar{flex:0 0 180px;} .holy-grail_content{flex:1; } } @media all and (min-width:960px){ .holy-grail_sidebar{flex:0 0 240px;} }
垂直居中
在传统的CSS中,垂直对齐的实现非常糟糕。有时候给节点设置inline-block能够解决这个问题,也有人使用绝对定位的hack来实现,还有人在使用很过时的table布局(在标签语义化的今天,这是不符合要求的)。所有这些提到的方式在实现垂直对齐时其实都有些怪异,而且都需要很多额外的开销才能够运作起来。
Flexbox能够轻松地处理好这个问题。我们来看两个包含对齐问题的例子。
第一个例子,左侧是用户头像,右侧是用户的名字和一些信息。我们将使用Flexbox来使得用户头像在区域中垂直居中。
第二个例子,在一个宽度固定、高度可变的容器中 ,如何实现元素始终处于容器中心(水平和垂直方向都居中).
<div class="user"> <div class="user_avatar"></div> <div class="user_description"> <h2 class="user_username">John Doe</h2> <p class="user_excerpt">I'm John Doe....</p> </div> </div> <div class="user"> <div class="user_avatar"></div> <div class="user_description"> <h2 class="user_username">Harry Potter</h2> <p class="user_excerpt">I'm Harry Potter... with a really long description...</p> </div> </div>
.user{display: flex; align-items: center;} .user_avatar{flex:0 0 96px; width:96px; height: 96px; background-color: #e7e7e7;} .user_description{flex:1; margin-left: 24px; padding:12px; border:1px solid #e7e7e7;}
align-items能够让flex项目垂直于flex基准线方向上队列显示。如果flex基准线沿着水平方向,我们能够让每个项目基于这个水平线排列。在我们的例子中,我们想要让项目中心对齐,所以我们只要设置align-items:center就可以了。
第二个例子,在 所有的节点标记中最上面的是banner,这个banner中有一些标题文本。在小屏幕 中,banner的高度是180px,它将通过设置的两个断点将高度变化为480px。每次变化后,我们都希望标题文本仍处在banner的中心,无论是水平方向还是垂直方向。
<div class="banner"> <div class="banner_content"> <h2 class="banner_title">Symmetrical Perfection</h2> <span class="banner_sub">A beautiful sight,achieved with flexbox.</span> </div> </div>
.banner{display: flex; align-items: center; justify-content:space-around; height: 180px; background-color: #e7e7e7;} .banner_content{text-align: center;} .banner_title,.banner_sub{margin:0; padding:0; line-height: 1.5;} @media all and (min-width:480px){ .banner{height: 240px;} } @media all and (min-width:768px){ .banner{height: 360px;} } @media all and (min-width:960px){ .banner{height: 480px;} }
justify-content这个属性的作用是定义项目周围沿着flex基准线的空间如何显示。
无论banner的高度是多少,内容总是会保持在水平和垂直方向的中心位置,这就是Flexbox的力量了。