Flexbox布局介绍

本文由清尘发表于2016-11-25 17:51最后修改于2016-12-30属于HTML/CSS分类

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的力量了。