CSS 网格布局引入了二维网格布局系统,可用于布局页面主要的区域布局或小型组件。不同于flex布局,flex布局是一维的,适合单行或单列的布局,而css grid(网格)是在一个二维的平面上布局元素,类似于table,不同于table的是它的子元素不受限制可以自由定位。
Grid 和 flexbox 区别
CSS网格布局和弹性盒布局的主要区别在于弹性盒布局是为一维布局服务的(沿横向或纵向的),而网格布局是为二维布局服务的(同时沿着横向和纵向)。这两个规格有一些相同的特性。如果你已经掌握如何使用弹性盒布局的话,你可能会想知道这些相似之处怎样在能帮助你掌握网格布局。
网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以将网格元素放置在与这些行和列相关的位置上。它使网页设计变得更加容易,而无需使用浮动和定位等其它技术。
css Grid 是一个强大的规范,当与 CSS 的其他部分(如flexbox)结合使用时,可以帮助您创建以前不可能在 CSS 中构建的布局。这一切都是通过在网格容器上创建一个网格来开始的。
我们可以使用 display:grid 或 display:inline-grid 来创建一个网格容器。如下示例:
html:
<div class="grid-container">
<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>
块级网格容器:
.grid-container {
display: grid;
background-color: #2196F3;
padding: 10px;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 30px;
text-align: center;
}
显示效果:
图1
行内块级网格容器:
.grid-container {
display: inline-grid;
background-color: #2196F3;
padding: 10px;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 30px;
text-align: center;
}
效果显示:
图2
网格容器的所有直接子元素自动成为网格项,注意grid和inline-grid的区别。在浏览器中,元素转为网格前看不出什么差异,因为网格给这些元素创建了一个单列网格。
你可以打开开发者工具,使用选择工具选择网格容器元素,此时会在元素节点旁看到一个grid的图标,点击后会看到页面显示网格布局。如下图:
图3
通过 grid-template-columns 和 grid-template-rows 属性来定义网格中的行和列,一个网格轨道就是网格中任意两条线之间的空间。
网格列轨道:
display: grid;
grid-template-columns: 200px 200px 200px;
显示效果:
图4
网格行轨道:
display: grid;
grid-template-rows: 200px 200px 200px;
图5
比如图5中,行一到行2之间的区域就是我们定义的行轨道。列1到列3之间的区域就是列轨道。从这里可以看出轨道不是指网格行或网格列,它们是有区别的,网格行和网格列是指网格项的水平线或垂直线,如下图:
网格列
网格行
网格轨道的大小,可以使用固定单位,如px、cm、pt等,还可以使用百分比、auto、关键字(min-content、max-content)、函数(max()、min()、minmax())等。此外还专门为网格指定一个 fr单位用来设置轨道大小,本节简单介绍下fr单位,后面会单独讲述,这方面内容太多。
fr单位代表网格容器中可用空间的一等份。下一个网格定义将创建三个相等宽度的轨道,这些轨道会随着可用空间增长和收缩。fr 类似于 flex布局中的flex-grow。
如下示例:
display: grid;
grid-template-columns: 1fr 1fr 1fr;
图6
如图6中,每列等宽,平分网格容器可用的空间。当将其中一列设置不同的值,如下图:
display: grid;
grid-template-columns: 1fr 2fr 1fr;
图7
图7中,一个3列的网格,其中列2的宽度是其它列的2倍。
应该注意的是,当我们定义网格时,我们定义的是网格轨道,而不是网格线。Grid 会为我们创建带编号的网格线来让我们来定位每一个网格元素。如下示例:
图8
列之间的线称为列线,行之间的线称为行线。可用使用grid-column-start (en-US), grid-column-end (en-US), grid-row-start (en-US) 和 grid-row-end (en-US) 属性,按照网格线编号进行定位,具体内容会在以后详细介绍。
网格线的编号顺序取决于文章的书写模式。在从左至右书写的语言中,编号为 1 的网格线位于最左边。在从右至左书写的语言中,编号为 1 的网格线位于最右边。 网格线也可以被命名,我们将在稍后的教程中看到如何完成这一操作。
一个网格单元是在一个网格元素中最小的单位, 从概念上来讲其实它和表格里的一个单元格很像。现在再看回我们前面的一个例子,一旦一个网格元素被定义在一个父级元素当中,那么他的子级元素将会排列在每个事先定义好的网格单元中。在下面的图中,我会将第一个网格单元作高亮处理。
网格元素可以向行或列的方向扩展一个或多个单元,并且会创建一个网格区域。网格区域的形状应该是一个矩形 - 也就是说你不可能创建出一个类似于“L”形的网格区域。下图高亮的网格区域扩展了 2 列以及 2 行。
图10
每列/行之间的空间称为网格间距。可使用 grid-column-gap (en-US) 和 grid-row-gap (en-US) 属性来创建,或者直接使用两个合并的缩写形式 grid-gap (en-US)。在下面的例子中,我会创建一个横向间距为 10px、纵向间距为 1em 的网格元素。
css:
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 10px;
grid-row-gap: 1em;
}
html:
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
效果显示:
图11
间距使用的空间会在使用弹性长度 fr 的轨道的空间计算前就被留出来,间距的尺寸定义行为和普通轨道一致,但不同的是你不能向其中插入任何内容。从以基线定位的角度来说,间距就像一条很宽的基线。
一个网格元素可以也成为一个网格容器。在接下来的例子中我事先有了一个 3 列的网格元素,并有两个跨轨道的网格。在这个例子中,第一个网格元素含有几个子级元素。当这些元素不是网格容器的直接子级元素时,它们不会参与到网格布局中,并显示为正常的文档流。
如下示例:
html:
<div class="wrapper">
<div class="box box1">
<div class="nested">a</div>
<div class="nested">b</div>
<div class="nested">c</div>
</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
css:
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 10px;
grid-row-gap: 1em;
background:#000;
}
.wrapper > div {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 30px;
text-align: center;
}
.nested{
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
}
图12
当我们给box1设置display: grid;如下图显示:
box1 {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 10px;
grid-row-gap: 1em;
}
图13
图13中box1它也会变成一个网格元素,它的子级元素也会排列在这个新网格元素中。
在这个例子中,嵌套网格和他的父级并没有关系。就像你在例子中所看见的一样,它并没有从它的父级继承 grid-gap (en-US) 属性,并且嵌套网格里面的网格线没有与父级的网格线对齐。
多个网格项目可以占用同一个网格单位。如下图示例:
html:
<div class="wrapper">
<div class="box box1">One</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
css:
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
column-gap: 10px;
row-gap: 10px;
}
.box{
background: #fff;
border:1px solid #000;
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
background:red;
}
.box2 {
grid-column-start: 1;
grid-row-start: 2;
grid-row-end: 4;
background:orange;
}
效果显示:
图14
网格 box2 现在覆盖于 box1 之上,其覆盖顺序遵循文档流的原始顺序(后来居上)。
我们可以使用 z-index 属性控制重叠的顺序。如果我们给 box2 设定一个低于 box1 的 z-index 值的话,box2将会显示在 box1 的下方。如下示例:
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
column-gap: 10px;
row-gap: 10px;
}
.box{
background: #fff;
border:1px solid #000;
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
background:red;
z-index:2;
}
.box2 {
grid-column-start: 1;
grid-row-start: 2;
grid-row-end: 4;
background:orange;
z-index:1;
}
显示效果:
图15
在本文章中我们快速对网格布局的概念有了个基本的了解。后面会详细介绍网格的布局及相关属性的具体内容。
站开发入门指南:如何划分网格?
除了能设定这些常见的尺寸的设定的值之外,其实还有它自己特别的一些值的设定。在开始介绍这几个特别的值得设定之前,先来看到开发者工具显示的网格效果。
先给大家介绍一个非常重要的信息,这个信息就是网格(中单元格)的尺寸。网格(中的单元格)的尺寸是由两个数据组成的,一个是左边的,一个右边,它是通过一个点分开的。这里乍一看其实没有什么特别奇怪的地方,因为这里前后都是一样的,包括行高也是前后都是一样的。
这里其实前面这个值就是在CS5里面写的这样的值,后面这个值其实是跟DPR相关的,也就是之前在讲屏幕像素的时候提到过的高倍屏,它有一个比较高的屏幕像素密度值的东西。
这里录制的显示器因为它是普通倍率的屏幕,不是高倍屏的屏幕,所以前后两个值都是一样的。但是如果网页在高倍屏上打开,比如这里,在高倍屏上去打开之后给大家截个图看一下。大家可以看到这里截出来的图,它的值前面是后面的两倍。
这个东西大家做一个基本的了解就可以了,只要知道它是跟屏幕倍率有关,因为像主屏幕就是刚才去截的屏幕,OPR是2,所以这两者的关系其实就是前面CS5设置的值除以DPR的值,然后就得出了后面这样的数据了。所以如果在不同的倍率的屏幕上可能看到的效果是不一样的,这个东西知道就好了。
像自己平时其实没有什么大的影响,因为主要还是看CS5,这部分设置的值就可以了。
接下来是先来介绍一下rep,这个东西准确的来讲其实是一个单位,因为它用起来是这样用的1fr.2fr这样子。这个东西的英文全称叫做fraction,fraction是有这种部分的意思,它的作用其实就是把整个容器内剩余的空间做一个均分,然后进行分配。
所以它的使用特点跟这种Flex布局中的repeale.xegrow其实是有点像的。利用这样的一个单位就能实现把整个的容器区域充分的利用起来,就是形成的整个网格就能刚刚好的占用满整个容器的区域。
这里通过这个代码来看一下,比如这里去做一个简化,先让它变成一行一列,这样的结果是整个网格就这么大。然后在列这里加一个1fr,会发现这里就神出来第二列,第二列完全占据了剩下的横向的空间。
也可以看到这样一个格子,第二列这里形成的格子的尺寸是这样子,左边是在CSS里面定义的值,右边是通过DPR相关的一些计算得出的具体的像素值。这样在横向空间内是不是完全占据了这样一个容器的宽度?
大家注意,像这种网格生成的格子也可以称为叫一个单元格,不管它的尺寸大小,只要是网格形成的其中的一个格子都可以称作叫单元格。这里给这个行这里也加一个1fr,会发现这里出现了第二行,第二行这里也是1fr,500px,这说明第二行也是1fr设置产生的了。
1fr这里就把整个容器的纵向的高度,给充分的利用起来了。
其实看到这里也能感觉到它的用法跟flexgrow真的是很像的,就是这里1fr其实就是把剩余的空间就分成1份,这一列占据1份。假如这里来个2fr,剩余的横向空间总共就分为3份,第三列占两份,第二列占1份。
假如这里再来一个,比如5fr,它也是一模一样的逻辑,就是剩余的空间进行均分,总共设置了几个fr,比如横向设置了列这里总共设置了8个fr,就除以8,然后占一份,占两份,占5份。
剩余空间不一定是第一个之后的,比如这里中间也可以穿插其他的单位的设置,比如在这里再来一个200px,横向的宽度剩余的空间是什么?就是元素的总宽度减去已经固定的这些值,不就是剩余的空间了吗?剩余的空间再进行总的fr份数的平分,各自去占几份,是这样的效果。
像这里,比如这里来一个3fr,最后来一个200px,也是一样类似的逻辑,都是这样的划分方式。其实也可以利用fr的方式快速的实现纯行纯列的布局,比如这里来这样一个1fr、1fr、1fr三列,是不是就三个这样的列的单元格了?
如果是行也可以这样,1fr、1fr、1fr,其实这就是有三行了,但是如果把元素放进去,其实就能看得到了,比如放几个元素进去111,其他就变成三行的效果了。
再更复杂一点,要做完全的平分的,比如9宫格,把列宽这样一个设置打开,就会发现它就是一个9宫格了,再来多几格,它是不是就变成16宫格了?所以很多时候fr这个单位,是在很多场景都会用得到的。因为用它就是能够去把整个的容器内部的空间给利用起来。所以想实现把容器空间内部完整利用起来的效果,进行一些剩余空间的分配、平均分配这样的一些需求,就可以大胆的去用fr这样一个单位。
们前端开发过程中,写css(包括sass, less, stylus这样的预处理器)进行设计稿的样式还原是一项重要的工作,而其中,关于页面布局的部分,又是书写样式代码时候的重点和难点,这篇文章就尽可能的去总结常见的一些页面布局实现方案(并不是全部,布局实现方法太多了),希望能够对大家有所帮助。
在开始正题之前,有一点要说明:css布局中遇到的一个绕不开的问题就是浏览器兼容性,下面方案会遇到类似transform, flex等的兼容性问题,且由于grid布局兼容性问题,暂不涉及grid布局内容,在不同场景,大家选择合适的布局实现方案即可。
1.1 水平居中布局
效果图如下:
分析:display设置为inline-block的元素,具有文本元素的性质,其父元素可以通过设置文本对齐属性text-align来控制其在行内的对齐方式,text-align: center即为水平对齐
注意:text-align属性是具有继承性的,会导致自己元素内部的文本也是居中显示的,需要自身设置text-align覆盖
<style>
.wrap {
width: 100%;
height: 200px;
background-color: aqua;
text-align: center;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
display: inline-block;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:父元素开启定位(relative,absolute,fixed都可以)后,子元素设置绝对定位absolute后,left设置为50%,再使用transform: translateX(-50%)将子元素往反方向移动自身宽度的50%,便完成水平居中。
注意:父级元素是否脱离文档流,不影响子元素水平居中效果,但是transform是css3属性,存在浏览器兼容问题
<style>
.wrap {
position: relative;
width: 100%;
height: 200px;
background-color: aqua;
}
.content {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:这个方法只需要对子元素进行设置就可以实现水平居中,margin设置auto表示浏览器会自动分配,实现来外边距等分效果。
注意:这里子元素设置display为block或者table都是可以的,如果子元素脱离文档流(浮动,定位),会导致margin属性的值无效。
<style>
.wrap {
width: 100%;
height: 200px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
display: table;
margin: 0 auto;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
效果图如下:
这种方案和之前水平居中布局的方案二是同样的原理,不在赘述
<style>
.wrap {
position: relative;
width: 200px;
height: 600px;
background-color: aqua;
}
.content {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:设置display: table-cell的元素具有td元素的行为,它的子元素布局方式类似文本元素,可以在父元素使用vertical-align: middle;实现子元素的垂直居中。
注意:vertical-align属性具有继承性,导致父元素内文本也是垂直居中显示的。
<style>
.wrap {
display: table-cell;
vertical-align: middle;
width: 200px;
height: 600px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
效果图如下:
前面分别总结了一些水平居中和垂直居中的布局方式,那么进行水平垂直居中的布局,也就没什么特别要说的了,直接上代码:
方案一.定位 + transform
<style>
.wrap {
position: relative;
width: 1200px;
height: 800px;
background-color: aqua;
}
.content {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
方案二. 结合水平布局方案三,垂直布局方案二
<style>
.wrap {
display: table-cell;
vertical-align: middle;
width: 1200px;
height: 800px;
background-color: aqua;
}
.content {
margin: 0 auto;
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:使用flex,水平垂直居中会变得非常容易,默认情况下,align-items: center垂直居中(交叉轴排列方式),justify-content: center水平居中(主轴排列方式) 注意:需要考虑浏览器兼容性问题。
<style>
.wrap {
display: flex;
align-items: center;
justify-content: center;
width: 1200px;
height: 800px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
2.1 两列布局
这里的两列布局指的是,其中一列是定宽元素,另一列元素宽度自适应。比如,我们实现左列定宽,右列自适应的布局。
效果图如下:
分析:一个最简单的做法,左边元素设置浮动,定宽,右边元素的margin-left设置为左边元素宽度大小,可以实现效果。
注意:我们左边元素使用了浮动,但是右边元素没有浮动
<style>
.l, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.r {
background-color: blueviolet;
margin-left: 400px;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">自适应</div>
</body>
分析:右边元素由于设置overflow:hidden开启BFC,与外界隔离,所以能实现效果
注意:overflow:hidden的设置也使得右边元素内容超出隐藏。这里如果不设置overflow:hidden,右边元素的宽度是100%,有一部分被左边浮动元素盖住,不是我们要的结果,虽然看起来没什么区别。
<style>
.l, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.r {
background-color: blueviolet;
overflow: hidden;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">自适应</div>
</body>
分析:这里主要是基于表格元素,在没有设置宽度时,会自动分配宽度来实现布局的。
注意:设置为表格后,在某些浏览器可能会受到表格本身特有行为的影响,比如表格边框等等。
<style>
.w {
display: table;
table-layout: fixed;
width: 100%;
}
.l, .r {
display: table-cell;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.r {
background-color: blueviolet;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="r">自适应</div>
</div>
</body>
分析:父容器采用flex布局,左边元素定宽之后,右边元素,因为只有一个,所以flex属性设置为不是0的正值(也就是设置flex-grow),都会占满剩余空间。
注意:依然是,注意兼容性问题。
2.2 三列布局
这里的三列布局,主要分三种情况介绍,第一种是普通三列布局,还有两种是比较有名的圣杯布局和双飞翼布局(两者都是实现一个两侧宽度固定,中间宽度自适应的三列布局,区别在于双飞翼布局比起圣杯布局,中间元素会多一个子元素,而左右元素需要定位relative)
2.2.1. 普通三列布局
我们这里实现的是,左中两列定宽,右边一列自适应的布局,这个实际上和前面的两列布局是类似的。
效果图如下:<style>
.p {
display: flex;
height: 600px;
}
.l {
background-color: aqua;
width: 400px;
}
.r {
flex: 1;
background-color: blueviolet;
}
</style>
<body>
<div class="p">
<div class="l">定宽</div>
<div class="r">自适应</div>
</div>
</body>
这里的三列布局,主要分三种情况介绍,第一种是普通三列布局,还有两种是比较有名的圣杯布局和双飞翼布局(两者都是实现一个两侧宽度固定,中间宽度自适应的三列布局,区别在于双飞翼布局比起圣杯布局,中间元素会多一个子元素,而左右元素需要定位relative)
我们这里实现的是,左中两列定宽,右边一列自适应的布局,这个实际上和前面的两列布局是类似的。
效果图如下:
分析:这个方案和两列布局方案二是相同的。
<style>
.l, .c, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.c {
width: 400px;
background-color: blueviolet;
float: left;
}
.r {
background-color: brown;
overflow: hidden;
}
</style>
<body>
<div class="l">定宽</div>
<div class="c">定宽</div>
<div class="r">自适应</div>
</body>
分析:这里布局原理和两列布局中flex布局方式是相同的。
<style>
.w {
display: flex;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.c {
width: 400px;
background-color: blueviolet;
}
.r {
flex: 1;
background-color: brown;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="c">定宽</div>
<div class="r">自适应</div>
</div>
</body>
两侧宽度固定,中间宽度自适应的三列布局(中间元素不需要嵌套子元素)
效果图如下:
分析:这种方法就是左右两边浮动,给定宽度,中间元素使用margin空出左右两边元素的位置,实现比较简单。
注意:这种方式,需要在书写html结构时,将右侧元素写在中间元素的前面,因为如果右侧元素在中间元素后面,由于浮动元素位置上不能高于(或平级)前面的非浮动元素,导致右侧元素会下沉。但是,中间元素一般都是页面的核心部分,放在比较后面的位置,不利于SEO。
<style>
.l, .c, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.c {
background-color: blueviolet;
margin-left: 400px;
margin-right: 400px;
}
.r {
width: 400px;
background-color: brown;
float: right;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">定宽</div>
<div class="c">自适应</div>
</body>
分析:这种方法将中间元素c放置在最前面,有利于SEO。
注意:实现细节在参考下面代码中的注释。
<style>
.w {
/* margin-left对应左边元素l的宽度,margin-right对应右边元素r的宽度 */
margin-left: 400px;
margin-right: 400px;
}
.l, .c, .r {
height: 600px;
float: left;
}
.l {
width: 400px;
background-color: aqua;
position: relative;
/* 为了让l元素从当前行移动到第一行同一位置*/
margin-left: -100%;
/* 移动到中间元素左侧正确位置 */
left: -400px;
}
.c {
width: 100%;
background-color: blueviolet;
}
.r {
width: 400px;
background-color: brown;
position: relative;
/* 为了让l元素从当前行移动到上一行*/
margin-left: -400px;
right: -400px;
}
</style>
<body>
<div class="w">
<div class="c">自适应</div>
<div class="l">定宽</div>
<div class="r">定宽</div>
</div>
</body>
两侧宽度固定,中间宽度自适应的三列布局(中间元素内部增加子元素用于放置内容)
效果图如下:
分析:这种方法为中间元素增加子元素作为内容区域,通过子元素设置margin完成。
注意:和圣杯布局对照,有相似处,也有不同,实现的结果是一样的。
<style>
.l, .c, .r {
height: 600px;
float: left;
}
.l {
width: 400px;
background-color: aqua;
/* 为了让l元素从当前行移动到第一行同一位置*/
margin-left: -100%;
}
.c {
width: 100%;
background-color: blue;
}
.i {
height: 600px;
background-color: blueviolet;
margin-left: 400px;
margin-right: 400px;
}
.r {
width: 400px;
background-color: brown;
/* 为了让r元素移动到第一行*/
margin-left: -400px;
}
</style>
<body>
<div class="c">
<div class="i">自适应</div>
</div>
<div class="l">定宽</div>
<div class="r">定宽</div>
</body>
分析:flex实现就很简单了,可以参照普通三列布局flex实现。
注意:还是要注意浏览器兼容性问题。
<style>
.w {
display: flex;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.c {
flex: 1;
background-color: blueviolet;
}
.r {
width: 400px;
background-color: brown;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="c">自适应</div>
<div class="r">定宽</div>
</div>
</body>
所谓多列等分布局,就是若干列在容器中自适应等分宽度,我们以五列等分布局为例。
效果图如下:
分析:这种方案就是每一列浮动,之后按照百分比平分宽度,实现简单。
<style>
.col {
float: left;
width: 20%;
height: 300px;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
分析:父容器指定display: table,设置布局行为table-layout: fixed,指定每个表格等宽。
注意:table-layout: fixed是需要设置的,默认情况下,列宽度由单元格内容设定,设置之后,列宽由表格宽度和列宽度设定。
<style>
.w {
display: table;
/* 列宽由表格宽度和列宽度设定 */
table-layout: fixed;
width: 100%;
}
.col {
display: table-cell;
height: 300px;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
分析:使用column布局,指定内容区域需要分为5列即可。
注意:浏览器兼容性问题。
<style>
.w {
/* 指定列数 */
column-count: 5;
/* 指定列与列之间的间隙,默认1em */
column-gap: 0;
}
.col {
height: 300px;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
分析:使用flex布局十分简单,指定每一列所占空间相同即可
<style>
.w {
display: flex;
}
.col {
height: 300px;
flex: 1;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
</html>
所谓多列等高布局,就是多类内容可能不一样,但是保证每一列的高度是相同的,这个高度应该由内容最多的那一列决定。
效果图如下:
分析:父元素设置display: table,子元素设置display: table-cell,这样布局就是按照表格行为布局,表格单元格默认等高。
<style>
.w {
display: table;
}
.col {
display: table-cell;
width: 20%;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1">啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col2">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col3">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col4"></div>
<div class="col col5">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
</div>
</body>
分析:默认情况下,display: flex的元素align-items属性值为stretch,如果项目未设置高度或设为auto,将占满整个容器的高度。
<style>
.w {
display: flex;
}
.col {
flex: 1;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1">啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col2">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col3">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col4"></div>
<div class="col col5">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
</div>
</body>
所谓全屏布局,就是实现经典的头部,内容区,底部三大区域占满全屏的布局,这种布局很常见。
实现效果如下:
分析:这里采用的方案是,头部底部使用fixed定位,中间使用之前讲到的两列布局技术。
注意:头部底部可以使用header, footer标签,内容区域结构与布局都是多种多样的。
<style>
html, body {
margin: 0;
overflow: hidden;
}
.header {
position: fixed;
left: 0;
top: 0;
right: 0;
height: 100px;
background-color: salmon;
}
.w {
position: fixed;
left: 0;
right: 0;
top: 100px;
bottom: 100px;
overflow: auto;
background-color: palevioletred;
}
.w .l {
width: 400px;
/* height: 100%; */
position: fixed;
left: 0;
top: 100px;
bottom: 100px;
background-color: greenyellow;
}
.w .r {
position: fixed;
left: 400px;
right: 0;
top: 100px;
bottom: 100px;
background-color: blueviolet;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 100px;
background-color: goldenrod;
}
</style>
<body>
<div class="header"></div>
<div class="w">
<div class="l"></div>
<div class="r"></div>
</div>
<div class="footer"></div>
</body>
本篇文章总结了一些常见布局的实现方案,css布局的实现方案很多,需要我们平时多去积累,选择合适的方案。
最后,希望随着时间的推移,兼容性不再成为我们技术实现的障碍,愿世界越来越美好。
最后送福利了,自己是从事了五年的前端工程师,整理了一份最全面前端学习资料,只要私信:“前端"等3秒后即可获取地址,
里面概括应用网站开发,css,html,JavaScript,jQuery,Ajax,node,angular等。等多个知识点高级进阶干货的相关视频资料,等你来拿
*请认真填写需求信息,我们会在24小时内与您取得联系。