前言
前几天听过学长的大厂面试经历后,我深感自己的基础知识的不足(我是fw,呜呜…),今天就借此讲一个有关CSS的一连串面试知识,希望大家能有所收获。
盒模型
CSS 盒子模型(Box Model)
所有HTML元素可以看作盒子,在CSS中,”box model”这一术语是用来设计和布局时使用。CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。
下面的图片说明了盒子模型(Box Model):
不同部分的说明:
- Margin(外边距) – 清除边框外的区域,外边距是透明的。
- Border(边框) – 围绕在内边距和内容外的边框。
- Padding(内边距) – 清除内容周围的区域,内边距是透明的。
- Content(内容) – 盒子的内容,显示文本和图像
重要:为了正确设置元素在所有浏览器中的宽度和高度,要了解,当你指定一个 CSS 元素的宽度和高度属性时,你只是设置内容区域的宽度和高度,而完整大小的元素,你还必须添加内边距,边框和外边距。
布局的传统解决方案,基于盒状模型,依赖 display
属性 + position
属性 + float
属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现,由此延伸提出了新的布局方案。
Grid布局
网格布局(Grid)是最强大的 CSS 布局方案。
它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。
如下图就是grid布局的拿手好戏:
Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。
Flex 布局是轴线布局,只能指定”项目”针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成”行”和”列”,产生单元格,然后指定”项目所在”的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。
相关属性
Grid Container
- 设置了
display: gird
的元素。 这是所有 grid item 的直接父项。
Grid Item
- Grid 容器的孩子(直接子元素)。
Grid Line
- 这个分界线组成网格结构。 它们既可以是垂直的(“column grid lines”),也可以是水平的(“row grid lines”),并位于行或列的任一侧。
Grid Track
- 两个相邻网格线之间的空间。 可以把它们想象成网格的列或行。
Grid Cell
- 两个相邻的行和两个相邻的列网格线之间的空间。它是网格的一个“单元”。
Grid Area
- 四个网格线包围的总空间。 网格区域可以由任意数量的网格单元组成。
还有一些其他属性我就不一一列举了。
虽然Grid布局能力十分强大,可以同时处理完行和列,但是不够成熟,grid的布局只支持高版本的浏览器,对于版本较低的浏览器就不是很兼容了。
Flex布局
Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。
Flex 是 Flexible Box 的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
- 任何一个容器都可以指定为 Flex 布局,
- 行内元素也可以使用 Flex 布局,
- Webkit 内核的浏览器,必须加上
-webkit
前缀。
注意,设为 Flex 布局以后,子元素的float
、clear
和vertical-align
属性将失效。
基本概念
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称”项目”。容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start
,结束位置叫做main end
;交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size
,占据的交叉轴空间叫做cross size
。
示意图:
容器的属性
以下6个属性设置在容器上:
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
flex三属性:flex:flex-grow flex-shrink flex-basis
第一个属性:flex-basis
该属性用来设置元素的宽度,其实,width也可以设置宽度。如果元素上同时设置了width和flex-basis,那么width 的值就会被优先度更高的flex-basis覆盖掉。
<html>
<head>
<style>
.box{
display: flex;
margin:100px auto;
width:400px;
height:200px;
}
.inner{
width:200px;
height:100px;
flex-basis:300px;
background:blue;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">
</div>
</div>
</body>
</html>
复制代码
如图width设置的200px宽度被flex-basis的300px宽度给覆盖了:
第二个属性:flex-grow
该属性用来设置当父元素的宽度大于所有子元素的宽度的和时(即父元素会有剩余空间),子元素如何分配父元素的剩余空间。 flex-grow的默认值为0,意思是该元素不索取父元素的剩余空间,如果值大于0,表示索取。值越大,索取的越厉害。
举个例子: 父元素宽400px,有两个子元素:A和B。A宽为100px,B宽为200px。 则空余空间为 400-(100+200)= 100px。 如果A,B都不索取剩余空间,则有100px的空余空间。
<html>
<head>
<style>
.box{
display: flex;
flex-direction: row;
margin:100px auto;
width:400px;
height:200px;
border:1px solid red;
}
.inner{
flex-basis:100px;
height:100px;
background:pink;
}
.inner1{
flex-basis:200px;
height:100px;
background:blue;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">A</div>
<div class="inner1">B</div>
</div>
</body>
</html>
复制代码
如图:
如果A索取剩余空间:设置flex-grow为1,B不索取。则最终A的大小为 自身宽度(100px)+ 剩余空间的宽度(100px)= 200px 。
<html>
<head>
<style>
.box{
display: flex;
flex-direction: row;
margin:100px auto;
width:400px;
height:200px;
border:1px solid red;
}
.inner{
flex-basis:100px;
height:100px;
background:pink;
flex-grow:1;
}
.inner1{
flex-basis:200px;
height:100px;
background:blue;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">A</div>
<div class="inner1">B</div>
</div>
</body>
</html>
复制代码
如图:
如果A,B都设索取剩余空间,A设置flex-grow为1,B设置flex-grow为2。则最终A的大小为 自身宽度(100px)+ A获得的剩余空间的宽度(100px (1/(1+2))),最终B的大小为 自身宽度(200px)+ B获得的剩余空间的宽度(100px (2/(1+2))。
<html>
<head>
<style>
.box{
display: flex;
flex-direction: row;
margin:100px auto;
idth:400px;
height:200px;
border:1px solid red;
}
.inner{
flex-basis:100px;
height:100px;
background:pink;
flex-grow:1;
}
.inner1{
flex-basis:200px;
height:100px;
background:blue;
flex-grow:2;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">A</div>
<div class="inner1">B</div>
</div>
</body></html>
复制代码
如图:
第三个属性:flex-shrink
该属性用来设置,当父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度的。 flex-shrink的默认值为1,当父元素的宽度小于所有子元素的宽度的和时,子元素的宽度会减小。值越大,减小的越厉害。如果值为0,表示不减小。
举个例子: 父元素宽400px,有两子元素:A和B。A宽为200px,B宽为300px。 则A,B总共超出父元素的宽度为(200+300)- 400 = 100px。 如果A,B都不减小宽度,即都设置flex-shrink为0,则会有100px的宽度超出父元素。
<html>
<head>
<style>
.box{
display: flex;
flex-direction: row;
margin:100px auto;
width:400px;
height:200px;
border:1px solid red;
}
.inner{
flex-basis:200px;
height:100px;
background:yellow;
flex-shrink:0;
}
.inner1{
flex-basis:300px;
height:100px;
background:blue;
flex-shrink:1;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">A</div>
<div class="inner1">B</div>
</div>
</body>
</html>
复制代码
如图:
如果A,B都减小宽度,A设置flex-shirk为3,B设置flex-shirk为2。则最终A的大小为 自身宽度(200px)- A减小的宽度(100px * (200px * 3/(200 * 3 + 300 * 2))) = 150px,最终B的大小为 自身宽度(300px)- B减小的宽度(100px * (300px * 2/(200 * 3 + 300 * 2))) = 250px 。
<html>
<head>
<style>
.box{
display: flex;
flex-direction: row;
margin:100px auto;
width:400px;
height:200px;
border:1px solid red;
}
.inner{
flex-basis:200px;
height:100px;
background:yellow;
flex-shrink:3;
}
.inner1{
flex-basis:300px;
height:100px;
background:blue;
flex-shrink:2;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">A</div>
<div class="inner1">B</div>
</div>
</body>
</html>
复制代码
如图:
这里出一个综合的面试问题:flex:7 1 100px 是指什么?详解
这里明确一点,flex是flex-grow,flex-shrink, flex-basis 的缩写形式,大家可以记一下下面的缩写规则:
如:flex 取值为 none,则计算值为 0 0 auto,如下是等同的:
.item {flex: none;}
.item { flex-grow: 0; flex-shrink: 0; flex-basis: auto;}
复制代码
当 flex取值为 auto,则计算值为 1 1 auto,如下是等同的:
.item {flex: auto;}
.item { flex-grow: 1; flex-shrink: 1; flex-basis: auto;}
复制代码
当 flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,如下是等同的:
.item {flex: 1;}
.item {flex-grow: 1; flex-shrink: 1; flex-basis: 0%;}
复制代码
当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink取 1,有如下等同情况(注意 0% 是一个百分比而不是一个非负数字):
.item-1 {flex: 0%;}
.item-1 { flex-grow: 1; flex-shrink: 1; flex-basis: 0%;}
.item-2 {flex: 24px;} .item-2 { flex-grow: 1; flex-shrink: 1; flex-basis: 24px;}
复制代码
当 flex取值为两个非负数字,则分别视为 flex-grow和 flex-shrink的值,flex-basis取 0%,如下是等同的:
.item {flex: 2 3;}
.item { flex-grow: 2; flex-shrink: 3; flex-basis: 0%;}
复制代码
当 flex取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow和 flex-basis的值,flex-shrink取 1,如下是等同的:
.item {flex: 2333 3222px;}
.item { flex-grow: 2333; flex-shrink: 1; flex-basis: 3222px;}
复制代码
水平垂直居中的实现方式
实现水平垂直居中效果的方法:
-
用absolute + 负margin
father{
position: relative;//父元素设置绝对定位
}
.son{
position: absolute;
width:100px;
height:100px;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -50px;
} -
absolute + margin auto
.father{
position: relative;//父元素设置绝对定位
}
.son{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
} -
absolute + transform
.father{
position: relative;//父元素设置绝对定位
}
.son{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
} -
absolute + calc,
.father{
position: relative;//父元素设置绝对定位
}
.son{
position: absolute;
width:100px;
height:100px;
top: calc(50%-50px);
left: calc(50%-50px);
} -
flex布局
.father{
display: flex;
justify-content: center; /显示在主轴的中间/
align-items: center; /子项在侧轴中间位置/
} -
grid布局
.father{
display:grid;
align-items:center;
justify-items:center;
} -
css新增的table属性
.father {
display: table-cell;
text-align: center;
vertical-align: middle;
}
.son {
display: inline-block;
} -
text-align和line-height
.father{
text-align: center;
width: 100px;
height: 100px;
background: indianred;
line-height: 100px;
}
如果需要更详细的介绍,可以去看看这一篇相关的文章。
总结
CSS面试题考察的东西虽说不算太难,但是内容大多会是面试官透你的项目对我们进行提问,所以学习CSS可以从我们做的项目着手,这样或许更有效率。