前言
网页布局是前端网页开发的第一步,是最最基础的部分,也是非常重要的部分。布局就是搭建网页的整体结构,好的布局不仅可以增加代码的可读性,提高开发效率,让人心中有丘壑,而且还可以提高代码的可复用性,且便于后期维护,是从事前端开发的小伙伴们需要重视的基本技能。本篇就着重介绍几种常用的页面布局方法。
居中布局
开头先说明一下,这里的居中方案都是可以适用于父容器和子容器都既不定宽也不定高的条件下的,所以自然也可以适用于定宽和定高的条件下。
一、水平居中布局
1. 水平居中:absolute + transform: translateX(-50%)
另外:
- 除了
transform: translateX(-50%)
这种方式以外,还可以采用给子容器设置负margin
值的方法实现居中(其绝对值必须为子容器宽度的一半),但前提是必须要知道子容器的宽度,也就是说子元素要定宽。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {position: relative; /* 如果不写这句,下面子元素的定位将不会是相对父级的绝对定位 */
}.child {position: absolute;left: 50%;transform: translateX(-50%); /* 相对自身偏移-50% */
}
2. 水平居中:flex + justify content: center
另外:
- 除了给父容器设置
justify-content:center
这种方式以外,还可以采用在子容器设置margin:0 auto
的方法实现居中,因为flex元素是支持margin: 0 auto
的。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {display: flex; /* flex布局 */justify-content: center;
}
3. 水平居中:inline-block + text-align: center
在使用inline-block
布局时需要注意的是:
vertical-align
属性会影响到inline-block
元素,你可能会想把它的值设置为top
;- 设置在父容器的
text-align:center
会继承到子容器,如果要改变子容器的text-align
属性,则需要重新设置进行覆盖; - 如果HTML源代码中元素之间有空格,那么列与列之间会产生空隙。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {text-align: center; /* text-align设置在块级元素的时候可以对里面的inline元素起作用 */
}.child {display: inline-block;
}
4. 水平居中:table + margin: 0 auto
给子元素设置display:table
属性,并且不设置宽度时,可以使其宽度由内容撑开,适合需要宽度自适应的水平居中布局。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.child {display: table; /* table在没有对它进行宽度100%的设置的时候,它的宽度就是和内容一样宽 */margin: 0 auto;
}
5. 水平居中:table-cell + text-align: center + inline-block
display:table-cell
属性指让标签元素以表格单元格的形式呈现,类似于td
标签。td
单元格有一些比较特别的属性,例如元素的垂直居中对齐,关联伸缩等,所以display:table-cell
还是有不少潜在的使用价值的。需要注意的是:
- 与其他一些display属性类似,
table-cell
同样会被其他一些CSS属性破坏,例如float
,position:absolute
,所以,在使用display:table-cell
时,与float:left
或是position:absolute
属性尽量要同时使用; - 设置了
display:table-cell
的元素对宽度高度敏感,对margin
值无反应,响应padding
属性,基本上就是活脱脱的一个td标签元素了。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {display: table-cell;text-align: center;
}.child {display: inline-block;
}
二、垂直居中布局
1. 垂直居中:absolute + transform: translateY(-50%)
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {position: relative; /* 如果不写这句,下面子元素的定位将不会是相对父级的绝对定位 */
}.child {position: absolute;top: 50%;transform: translateY(-50%); /* 相对自身偏移-50% */
}
2. 垂直居中:flex + align-items
注意:如果不设置align-items:center
,那么其默认值则是stretch
,这时子容器将撑满父容器的高度;
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {display: flex;align-items: center; /* 默认值是stretch, 即拉伸, 改为center即可居中 */
}
3. table-cell + vertical-align
display:table-cell
的属性上面的水平居中已经大致交代过了,这里再提醒一下需要注意:
- 与其他一些display属性类似,
table-cell
同样会被其他一些CSS属性破坏,例如float
,position:absolute
,所以,在使用display:table-cell
时,与float:left
或是position:absolute
属性尽量不要同时使用; - 设置了
display:table-cell
的元素对宽度高度敏感,对margin
值无反应,响应padding
属性,基本上就是活脱脱的一个td标签元素了。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {display: table-cell;vertical-align: middle;
}
三、水平方向和垂直方向同时居中布局
1. 同时居中:absolute + transform: translate(-50%, -50%)
另外:
- 除了
transform: translate(-50%, -50%)
这种方式以外,还可以采用给子容器设置负margin
值的方法实现居中(其绝对值必须为子容器宽度和高度的一半),但前提是必须要知道子容器的宽度和高度,也就是子元素要定宽定高。
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {position: relative; /* 如果不写这句,下面子元素的定位将不会是相对父级的绝对定位 */
}.child {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%); /* 相对自身偏移-50% */
}
2. 同时居中:inline-block + text-align: center + table-cell + vertical-align
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {text-align: center;display: table-cell;vertical-align: middle;
}.child {display: inline-block;
}
3. 同时居中:flex + justify-content + align-items
HTML:
<div class="parent"><div class="child">DEMO</div>
</div>
CSS:
.parent {display: flex;justify-content: center;align-items: center; /* 默认值是stretch, 即拉伸, 改为center即可居中 */
}
多列布局
一、定宽 + 自适应
left和center容器定宽,right容器自适应。
1. float + margin
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.left {float: left;width: 100px;
}.right {margin-left: 120px; /* 多出的20px作为left容器与right容器之间的边距 */
}
2. float + overflow
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="center"><p>center</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.left, .center {float: left;width: 100px;margin-right: 20px; /* 边距 */
}.right {overflow: hidden; /* BFC原理 */
}
3. table
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="center"><p>center</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {display: table;width: 100%; /* 如果不设置,宽度将由内容决定 */table-layout: fixed; /* 如果不设置,table内部子容器的宽度可能会被内容影响,即使设置了子容器的宽度也是如此 */
}.left, .center, .right {display: table-cell;
}.left, .center {width: 100px;padding-right: 20px; /* table-cell相当于td元素,是不能设置margin的,所以用padding代替 */
}
4. flex
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="center"><p>center</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {display: flex;
}.left, .center {width: 100px;margin-right: 20px; /* 边距 */
}.right {flex: 1; /* flex: 1 1 0%; */
}
二、不定宽 + 自适应
left和center容器不定宽(即宽度由内容撑开),right容器自适应。
1. float + overflow
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="center"><p>center</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.left, .center {float: left;margin-right: 20px; /* 边距 */
}.right {overflow: hidden;
}
2. table
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="center"><p>center</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {display: table;width: 100%; /* 如果不设置,宽度将由内容决定 *//* 这里不设置table-layout: fixed,因为我们需要table内部子容器的宽度由内容决定 */
}.left, .center, .right {display: table-cell;
}.left, .center {width: 0.1%; /* table-cell的特性,内容优先 */padding-right: 20px; /* table-cell相当于td元素,是不能设置margin的,所以用padding代替 */
}
3. flex
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="center"><p>center</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {display: flex;
}.left, .center {margin-right: 20px; /* 边距 */
}.right {flex: 1; /* flex: 1 1 0%; */
}
三、等宽
当父容器中有N个列时,它们的列宽相等,并且当父容器变宽(或变窄)时,这些列也要相应的变宽(或变窄)。
1. float
HTML:
<div class="parent"><div class="column"><p>1</p></div><div class="column"><p>2</p></div><div class="column"><p>3</p></div><div class="column"><p>4</p></div>
</div>
CSS:
.parent {margin-left: -20px; /* 将父容器撑开20px,但名义宽度不变,这20px是内部列与列之间的边距 */
}.column {float: left;width: 25%; /* 由列数决定 */padding-left: 20px; /* 列与列之间的边距 */box-sizing: border-box; /* 意味着padding-left值被包含在25%的宽度中 */
}
2. table
HTML:
<div class="parent-fix"><div class="parent"><div class="column"><p>1</p></div><div class="column"><p>2</p></div><div class="column"><p>3</p></div><div class="column"><p>4</p></div></div>
</div>
CSS:
.parent-fix {margin-left: -20px; /* 将父容器撑开20px,但名义宽度不变,这20px是内部列与列之间的边距,但是table不能设置margin值,所以在parent外面再加一个修正用的容器 */
}.parent {display: table;width: 100%;table-layout: fixed; /* 设置为fixed时,列宽会相等 */
}.column {display: table-cell;padding-left: 20px; /* 列与列之间的边距 */
}
3. flex
HTML:
<div class="parent"><div class="column"><p>1</p></div><div class="column"><p>2</p></div><div class="column"><p>3</p></div><div class="column"><p>4</p></div>
</div>
CSS:
.parent {display: flex;
}.column {flex: 1;
}.column + .column {margin-left: 20px;
}
四、等高
1. table
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {display: table;width: 100%;table-layout: fixed;
}.left, .right {display: table-cell;
}.left {width: 100px; /* 不设置也没关系 */border-right: 20px solid transparent; /* 通过border来设置间距 */background-clip: padding-box; /* 背景颜色默认会显示到border部分,也就是border-box,所以这里设置到padding-box */
}
2. flex
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {display: flex;
}.left {width: 100px;margin-right: 20px;
}.right {flex: 1;
}
3. float
伪等高方案,只是背景颜色一样高,不推荐。
HTML:
<div class="parent"><div class="left"><p>left</p></div><div class="right"><p>right</p><p>right</p></div>
</div>
CSS:
.parent {overflow: hidden; /* 必须 */
}.left {float: left;width: 100px;margin-right: 20px;
}.right {overflow: hidden;
}.left, .right {padding-bottom: 9999px;margin-bottom: -9999px;
} /* 一升一降 */