页面布局
# 页面布局
# 1. 常见的CSS布局单位
常用的布局单位包括像素(px),百分比(%),em,rem,vw/vh。
(1)像素(px)是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素:
CSS像素:为web开发者提供,在CSS中使用的一个抽象单位;
物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。
(2)百分比(%),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。
(3) em和rem相对于px更具灵活性,它们都是相对长度单位,它们之间的区别:em相对于父元素,rem相对于根元素。
em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认16px)。(相对父元素的字体大小倍数)。
rem: rem是CSS3新增的一个相对单位,相对于根元素(html元素)的font-size的倍数。作用:利用rem可以实现简单的响应式布局,可以利用html元素中字体的大小与屏幕间的比值来设置font-size的值,以此实现当屏幕分辨率变化时让元素也随之变化。
(4)vw/vh 是与视图窗口有关的单位,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。
vw:相对于视窗的宽度,视窗宽度是100vw;
vh:相对于视窗的高度,视窗高度是100vh;
vmin:vw和vh中的较小值;
vmax:vw和vh中的较大值;
vw/vh 和百分比很类似,两者的区别:
百分比(%):大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
vw/vm:相对于视窗的尺寸
# 2. px、em、rem的区别及使用场景
三者的区别:
px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
em和rem相对于px更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
em是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。
使用场景:
对于只需要适配少部分移动设备,且分辨率对页面影响不大的,使用px即可 。
对于需要适配各种移动设备,使用rem,例如需要适配iPhone和iPad等分辨率差别比较挺大的设备。
# 3. 两栏布局的实现
一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:
- 利用浮动,将左边元素宽度设置为200px,并且设置向左浮动。将右边元素的margin-left设置为200px,宽度设置为auto(默认为auto,撑满整个父元素)。
.outer{
height:100px;
}
.left{
float:200px;
width:200px;
}
.right{
margin-left:200px;
width:auto;
background:gold;
}
- 利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置overflow: hidden; 这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
.left{
float:200px;
width:200px;
background:red;
float;left;
}
.right{
margin-left:200px;
background:pink;
overflow:hidden;
}
- 利用flex布局,将左边元素设置为固定宽度200px,将右边的元素设置为flex:1。
.outer{
display:flex;
height:100px;
}
.left{
float:200px;
background:pink;
}
.right{
flex:1;
background:gold;
}
- 利用绝对定位,将父级元素设置为相对定位。左边元素设置为absolute定位,并且宽度设置为200px。将右边元素的margin-left的值设置为200px。
.outer{
position:relative;
height:100px;
}
.left{
position:absolute;
width:200px;
height:100px;
background:pink;
}
.right{
margin-left:200px;
background:gold;
}
- 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为200px,右边元素设置为绝对定位,左边定位为200px,其余方向定位为0。
.outer{
position:relative;
height:100px;
}
.left{
width:200px;
background:pink;
}
.right{
position:absolute;
top:0;
left:200px;
background:gold;
}
# 4. 三栏布局的实现
三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:
- 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。
.outer{
position:relative;
height:100px;
}
.left{
position:absolute;
width:100px;
height:100px;
background:pink;
}
.right{
position:absolute;
top:0;
left:200px;
height:100px;
background:gold;
}
.center{
margin-left:100px;
margin-right:200px;
height:100px;
background:red;
}
- 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1。
.outer{
display:flex;
height:100px;
}
.left{
width:100px;
background:pink;
}
.right{
height:100px;
background:gold;
}
.center{
flex:1;
background:red;
}
- 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式,中间一栏必须放到最后:
.outer{
height:100px;
}
.left{
float:left;
width:100px;
height:100px;
background:pink;
}
.right{
float:right;
left:200px;
height:100px;
background:gold;
}
.center{
margin-left:100px;
margin-right:200px;
height:100px;
background:red;
}
- 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
.outer{
height:100px;
padding-left:100px;
padding-right:200px;
}
.left{
position:relative;
left:-100px;
float:left;
margin-left:-100%;
width:100px;
height:100px;
background:gold;
}
.right{
position:relative;
left:-100px;
float:right;
margin-left:-200px;
width:200px;
height:100px;
background:gold;
}
.center{
float:left;
width:100%;
height:100px;
background:red;
}
- 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。
.outer {
height: 100px;
}
.left {
float: left;
margin-left: -100%;
width: 100px;
height: 100px;
background: tomato;
}
.right {
float: left;
margin-left: -200px;
width: 200px;
height: 100px;background: gold;
}
.wrapper {
float: left;
width: 100%;
height: 100px;
background: lightgreen;
}
.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
}
# 5. 水平垂直居中的实现
- 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心。该方法需要考虑浏览器兼容问题。
.parent{
position:relative;
}
.child{
position:absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%)
}
- 利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况:
.parent{
position:relative;
}
.child{
position:absolute;
left:0;
top:0;
margin:auto;
}
- 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况
.parent{
position:relative;
}
.child{
position:absolute;
left:50%;
top:50%;
margin-top:-50%;
margin-left:-50%;
}
- 使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。该方法要考虑兼容的问题,该方法在移动端用的较多:
.parent{
display:flex;
justify-content:center;
align-items:center;
}
# 6. 如何根据设计稿进行移动端适配?
移动端适配主要有两个维度:
适配不同像素密度,针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真;
适配不同屏幕大小,由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用 px 作为开发单位,会使得开发的页面在某一款手机上可以准确显示,但是在另一款手机上就会失真。为了适配不同屏幕的大小,应按照比例来还原设计稿的内容。
为了能让页面的尺寸自适应,可以使用 rem,em,vw,vh 等相对单位。
# 7. 对Flex布局的理解及其使用场景
Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。行内元素也可以使用Flex布局。注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。采用Flex布局的元素,称为Flex容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称"项目"。容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis),项目默认沿水平主轴排列。
以下6个属性设置在容器上:
flex-direction属性决定主轴的方向(即项目的排列方向)。
flex-wrap属性定义,如果一条轴线排不下,如何换行。
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
justify-content属性定义了项目在主轴上的对齐方式。
align-items属性定义项目在交叉轴上如何对齐。
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
以下6个属性设置在项目上:
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
简单来说:
flex布局是CSS3新增的一种布局方式,可以通过将一个元素的display属性值设置为flex从而使它成为一个flex容器,它的所有子元素都会成为它的项目。一个容器默认有两条轴:一个是水平的主轴,一个是与主轴垂直的交叉轴。可以使用flex-direction来指定主轴的方向。可以使用justify-content来指定元素在主轴上的排列方式,使用align-items来指定元素在交叉轴上的排列方式。还可以使用flex-wrap来规定当一行排列不下时的换行方式。对于容器中的项目,可以使用order属性来指定项目的排列顺序,还可以使用flex-grow来指定当排列空间有剩余的时候,项目的放大比例,还可以使用flex-shrink来指定当排列空间不足时,项目的缩小比例。
# 8. flex:1 表示什么
flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。flex:1 表示 flex: 1 1 0%:
第一个参数表示: flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大;
第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小;
第三个参数表示: flex-basis给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小。
# 9. 响应式设计的概念及基本原理
响应式网站设计(Responsive Web design)是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。
关于原理: 基本原理是通过媒体查询(@media)查询检测不同的设备屏幕尺寸做处理。 关于兼容: 页面头部必须有mate声明的viewport。
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimun-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
# 10. 实现“品” 字布局
品字布局就像下图这样:
(1)浮动实现 我们可以使用定位实现,对于上面的1,使用magin属性让他水平居中;下面的两个使用浮动即可实现,其HTML结构如下:
<div class='div1'>1</div>
<div class='div2'>2</div>
<div class='div3'>3</div>
CSS代码如下:
div {
width : 100px;
height : 100px;
font-size:40px;
line-height: 100px;
color : #fff;
text-align:center;
}
.div1 {
background :red;
margin:0 auto;
}
.div2 {
background: green;
float:left;
margin-left: 50%;
}
.div3 {
background: blue;float:left;
margin-left: -200px;
}
该方法是在在三个盒子的宽高都知道的情况下才能实现的。
(2)inline-block实现 HTML结构如下:
<div class='div1'>1</div>
<div class='div2'>2</div>
<div class='div3'>3</div>
这里将div设置为了inline-block,实际上和上面的float的作用是一眼的,就是让下面的两个块不换行。使用CSS样式如下:
div {
width: 100px;
height : 100px;
font-size:40px;
line-height : 100px;
color: #fff;
text-align:center;
}
.div1 {
background :red;
margin:0 auto;
}
.div2 {
background: green;
display: inline-block;
margin-left: 50%;
}
.div3 {
background: blue;
display: inline-block;
margin-left: -200px;
}
# 11. 实现九宫格布局
实现效果如下:
首先,定义好通用的HTML结构:
<div class="box">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
</div>
公共样式:
ul{
padding:0;
}
li{
list-style:none;
text-align:center;
border-radius:5px;
background:skyblue;
}
(1)flex实现
对于九宫格布局,我首先想到的就是flex布局,flex布局实现九宫格很简单,需要设置一个flex-wrap: wrap;使得盒子在该换行的时候进行换行。
由于我们给每个元素设置了下边距和右边距,所以最后同一列(3、6、9)的右边距和最后一行(7、8、9)的下边距撑大了ul,所以这里使用类型选择器来消除他们的影响。最终的实现代码如下:
ul{
display:flex;
flex-wrap: wrap;
width:100%;
height:100%;
}
li{
width:30%;
height:30%;
margin-right:5%;
margin-bottom:5%;
}
li:nth-of-type(3n){
margin-right:0;
}
li:nth-of-type(n+7){
margin-bottom:0;
}
(2)grid实现
grid布局相对于flex布局来说,实现九宫格就更加容易了,只需要设置几个属性即可:
ul{
width:100%;
height:100%;
display:grid;
grid-template-columns: 30% 30% 30%;
grid-template-rows: 30% 30% 30%;
grid-gap: 5%;
}
其中grid-template-columns属性用来设置每一行中单个元素的宽度,grid-template-rows属性用来设置每一列中单个元素的高度,grid-gap属性用来设置盒子之间的间距。
(3)float实现 这里首先需要给父元素的div设置一个宽度,宽度值为:盒子宽 * 3 + 间距 * 2;然后给每个盒子设置固定的宽高,为了让他换行,可以使用float来实现,由于子元素的浮动,形成了BFC,所以父元素ul使用overflow:hidden;来消除浮动带来的影响。最终的实现代码如下:
ul{
width:100%;
height:100%;
overflow:hidden;
}
li{
float:left;
width:30%;
height:30%;
margin-right:5%;
margin-bottom:5%;
}
li:nth-of-type(3n){
margin-right:0;
}
li:nth-of-type(n+7){
margin-bottom:0;
}
(4)inline-block实现 其实inline-block的作用和上面float的作用是一样的,都是用来让元素换行的,实现代码如下:
ul{
width:100%;
height:100%;
letter-spacing:-10px
}
li{
width:30%;
height:30%;
display:inline-block;
margin-right:5%;
margin-bottom:5%;
}
li:nth-of-type(3n){
margin-right:0;
}
li:nth-of-type(n+7){
margin-bottom:0;
}
需要注意的是,设置为inline-block的元素之间可能会出现间隙,就可能出现下面这种情况:
这里使用了letter-spacing属性来消除这种影响,该属性可以用来增加或减少字符间的空白(字符间距)。使用之后就正常了,出现了预期的效果。也可以给ul设置font-size: 0;来消除盒子之间的字符间距:
ul{
font-size:0;
}
(5)table实现 HTML结构:
<ul class="table">
<li>
<div>1</div>
<div>2</div>
<div>3</div>
</li>
<li>
<div>4</div>
<div>5</div>
<div>6</div>
</li>
<li>
<div>7</div>
<div>8</div>
<div>9</div>
</li>
</ul>
table布局也不算太难,首先给父元素设置为table布局,然后使用border-spacing设置单元格之间的间距,最后将li设置为表格行,将div设置为表格单元格,CSS样式如下:
.table{
width:100%;
height:100%;
display:table;
border-spacing:10px;
}
li{
display:table-row;
}
div{
width:30%;
height:30%;
text-align:center;
border-radius:5px;
background:skyblue;
}