CSS面试题
1、盒模型
盒子模型有两种:ie盒子模型和标准W3C盒子模型。
W3C盒子模型包括margin、border、padding、content,并且content部分不包含其他部分
ie盒子模型包括margin、border、padding、content,和w3c盒子模型不同的是:ie盒子模型的content部分包括了border和padding。
例如:一个盒子的margin为20px,border为1px,padding为10px,content的宽为200px,高为50px.w3c盒子模型解释,该盒子需要占据的位置为:宽:202+12+102+200=262px,高:202+12+102+50=112px,盒子实际大小为:宽:12+102+200=222px,高:12+102+50=72px;假如用ie盒子模型,那么这个盒子占据位置为:宽:202+200=240px,高:202+50=70px,盒子实际大小为:宽200px,高:50px
2、 box-sizing
box-sizing属性规定了一个元素用于计算元素宽度和高度的css盒子模型。是标准盒子和怪异盒子之间的切换。有两个属性值:content-box,border-box.
content-box:是默认值,他的计算方法是width/height=content。其内外边距不包含在width/height当中,而是在实际渲染时附加在原有基础上。(标准盒子)
div{
width:100px;
height:100px;
padding:20px;
margin:20px;
}
border-box:他的宽高计算方法是:width/height=content+padding+border。(与怪异盒模型是相同的)
当你希望通过百分比设定整体盒子的宽高,而不是内容宽高时,你希望子元素的整个盒子撑满父元素的内容区域。此时使用border-box,这样元素的宽高就变成了height/width=content+padding+border
在使用box-sizing时,我们要注意以下几点
1.absolute定位的元素,使用百分比设定其宽高时,它参考的是其第一个非static祖先节点的padding-box,即 content + padding
2.除去absolute的特例,其它情况下,使用百分比设定宽高时,参考的都是父级的content-box,即内容块宽高。
3、 Flex布局
布局的传统解决方案,基于盒模型,依赖display属性+position属性+float属性。它对于特殊布局非常不方便。W3C提出Flex布局,可以简便、完整、响应式地实现各种页面布局。
Flex译为“弹性布局”,任何一个容器都可以指定为Flex布局。
.box{
display: flex;
}
注意:设为Flex布局后,子元素的float、clear、和vertical-align属性将失效
基本概念
采用Flex布局的元素,称为Flex容器。它的所有子元素自动成为容器成员,称为Flex项目(flex item)
容器的属性
- flex-direction
决定主轴的方向(即项目的排列方向)
.box{
flex-direction:row(默认)|row-reverse|column|column-reverse;
}
属性 | 描述 |
---|---|
row | 主轴的水平方向,起点在左端 |
row-reverse | 主轴的水平方向,起点在右端 |
column | 主轴的垂直方向,起点在上端 |
column-reverse | 主轴的垂直方向,起点在下端 |
- flex-wrap
控制子元素溢出时的换行处理
.box{
flex-wrap:nowrap|wrap|wrap-reverse
}
- flex-flow
是flex-direction属性和flex-wrap属性的简写,默认值是row nowrap
- justify-content
定义了项目在主轴上的对齐方式
.box{
justify-content:flex-start|felx-end|center|space-between|space-around
}
属性 | 描述 |
---|---|
flex-start | 左对齐 |
felx-end | 右对齐 |
center | 居中 |
space-between | 两端对齐,项目之间间隔相等 |
space-around | 每个项目两侧的间距相等。所以,项目之间的间隔比项目与边框的间隔大一倍 |
space-evently | 元素间距离平均分配 |
- align-items
定义项目在交叉轴上如何对齐
.box{
align-item:flex-start|felx-end|center|baseline|strech;
}
属性 | 描述 |
---|---|
flex-start | 交叉轴的起点对齐 |
felx-end | 交叉轴的终点对齐 |
center | 交叉轴的中点对齐 |
baseline | 项目的第一行文字的基线对齐 |
strech | 如果项目未设置高度或设为auto,将占满整个容器的高度 |
- align-content
定义了多根轴线的对齐方式。如果项目只有一根轴线,改属性不起作用。
.box{
align-content:flex-start|flex-end|center|space-between|space-around|stretch;
}
属性 | 描述 |
---|---|
flex-start | 交叉轴的起点对齐 |
felx-end | 交叉轴的终点对齐 |
center | 交叉轴的中点对齐 |
space-between | 与交叉轴两端对齐,轴线之间间隔相等 |
space-around | 每根轴线两侧的间距相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍 |
strech | 轴线占满整个交叉轴 |
space-evently | 元素间距离平均分配 |
项目属性
- order
定义项目的排列顺序。数值越小,排列越靠前,默认为0.
.item{
order: <integer>;
}
- flex-grow
定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
.item{
flex-grow: <number>;
}
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍
- flex-shrink
定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
.item{
flex-shrink: <number>;
}
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
负值对该属性无效
- flex-basis
定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它默认值为auto,即项目的本来大小。
flex-basis 优先级比width 高
若flex-basis为auto,则width设置多少就是多少,若没有设置width,则根据内容撑开;
若flex-basis:200px;width:300px,那么子项自然为200px
- flex
该属性是flex-grow,flex-shrink,flex-basis的简写,默认值是0 1 auto(不放大会缩小)。后两个属性可选。
flex-basis是在flex-grow,flex-shrink之前看的。flex-basis设定好了再看另外两个,若空间还有空余,就flex-grow,若空间不够,就flex-shrink
flex缩写
flex = flex-grow flex-shrink flex-basis
flex:1 = > flex: 1 1 0
flex:2 => flex: 2 1 0
flex:auto => flex:1 1 auto (放大且缩小)
flex: none => flex: 0 0 auto(不放大也不缩小)
.item{
flex:none|[<'flex-grow'><'flex-shrink'>?||<'flex-basis'>]
}
- align-self
允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
4、隐藏元素的方法
- opacity:0;
设置一个元素的透明度,从视觉上隐藏了该元素,元素依然占据他原来的位置并对页面布局起作用,也将响应用户交互 - visibility:hidden
隐藏元素,占据原来位置,元素依然会对页面布局起作用,但不会响应用户交互。
如果一个元素的visibility被设置为hidden之后,却想要显示他的某个子孙元素,只要将那个子孙元素的visibility显示设置为visible即可 - display:none
真正的隐藏了元素。
不占据任何空间,不响应用户交互,子孙元素也会被隐藏。为这个属性添加过度动画是无效的。
通过DOM可以访问这个元素 - position:absolute
假设有一个元素你想要与他交互,但你又不想让他影响你的布局(opacity和visibility影响布局,display不影响布局但又无法直接交互)
这时,只能考虑将元素移出可视区域,这个办法既不会影响布局,有可能让元素保持可以操作。
通过position属性设置为absolute来实现
position:absolute;
top:-999px;
left:-999px;
- clip-path
通过裁剪实现,浏览器兼容比较差
clip-path:polygon{0px 0px, 0px 0px,0px 0px ,0px 0px}
5、清除浮动
浮动(float)是一种布局方式,浮动元素会漂浮在文档流的块框上。
浮动带来的问题:
1、父元素的高度无法被撑开,影响与父元素同级的元素
2、与浮动元素同级的非浮动元素(内联元素)会跟随其后
一个父亲是不能被浮动的儿子撑出高度
1. 给浮动元素的父级div加高度height
如果一个元素要浮动,那么他的祖先元素一定要有高度。有高度的盒子,才能关住浮动。在工作中很少用
2. clear:both
最后一个浮动元素后加空div标签并添加样式clear:both,不允许左侧和右侧有浮动对象。该方法有一个缺点:它所在标签,margin属性失效了。两个div之间,没有任何的间隙了。
3. 隔墙法和内墙法
隔墙法在两个浮动元素中间用一个新的div隔开,然后给这个div设置clear:both。这样虽然可以清处浮动不影响后面的盒子的布局,但是撑不起盒子的高度
<div>
<p></p>
<p></p>
<p></p>
</div>
<div class="cl h10"></div>
<div>
<p></p>
<p></p>
<p></p>
</div>
内墙法是在父盒子的里面的最后面增加一个div,然后设置其clear:both,这样可以清楚浮动并撑起高度
<div>
<p></p>
<p></p>
<p></p>
<div class="cl h10"></div>
</div>
<div>
<p></p>
<p></p>
<p></p>
</div>
4. 父元素添加overflow:hidden
通过触发BFC方式,实现清除浮动
.father{
width:400px;
border:1px solid white;
overflow:hidden;
}
5. 使用after伪元素清楚浮动
.clearfix:after{
content:"";
clear:both;
display:block;
}
.clearfix{
zoom:1;//为了兼容IE6,7,配合使用zoom
}
<div class="father clearfix">
<div></div>
</div>
6、BFC(块级格式化上下文)
BFC是一个独立的渲染区域,规定了内部的Block Box如何布局
定位方案:
- 内部的BOX会在垂直方向上一个接一个放置。
- Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻BOX的margin会发生重叠。
- 每个元素的margin box 的左边,与包含块border box的左边相接触。
- BFC的区域不会与float box重叠
- BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
- 计算BFC的高度时,浮动元素也会参与计算。
满足下列条件之一就可出发BFC
1、根元素,即HTML
2、float的值不为none(默认)
3、overflow的值不为visible(默认)
4、display的值为inline-block、table-cell、 table-caption
5、position的值为absolute或fixed
7、css选择器
id选择器(#id)、类选择器(.class)、标签选择器(div,p,h1)、相邻选择器(h1+p)、子选择器(ul>li)、后代选择器(li a)、通配符选择器(*)、属性选择器(a[rel=“exter”])、伪类选择器(a:hover,li:nth-child)
优先级:!important > id选择器 > 类选择器 = 伪类选择器 > 标签选择器
!important比内联优先级高
可继承的属性:font-size,font-family,color
不可继承的样式:border、padding、margin、width、height
8、css3新特性
- RGBA和透明度
- background-image、background-origin(content-box/padding-box/border-box)background-size、background-repeat
- word-wrap:break-word(对长的不可分割的单词换行)
- 文字阴影:text-shadow:5px 5px 5px #FF0000;(水平阴影,垂直阴影,模糊距离,阴影颜色)
- font-face属性:定义自己的字体
- 圆角(边框半径):border-radius
- 边框图片:border-image:url(border.png) 30 30 round
- 盒阴影:box-shadow:10px 10px 5px #0000
- 媒体查询:定义两套css,当浏览器的尺寸变化时会采用不同的属性
- css3新增伪类:
p:first-of-type 选择属于其父元素的首个元素
p:last-of-type 选择属于其父元素的最后元素
p:only-of-type 选择属于其父元素的唯一元素
p:only-child 选择属于其父元素的唯一子元素
p:nth-child(2) 选择属于其父元素的第二子元素
:enabled :disabled 表单控件的禁用状态
:checked 单选框或复选框被选中
9、水平垂直居中
行内元素(文字、图片)水平垂直居中
行内元素水平居中
:给父容器设置:text-align:center;
行内元素垂直居中
:让文字的行高等于盒子的高度,可以让单行文本垂直居中。
.father{
height:20px;
line-height:20px;
}
块级元素水平垂直居中
水平居中是比较容易的,直接设置元素的margin:0 auto就可以实现。但对垂直居中来说margin:auto行不通。
方式一:绝对定位+margin(需要指定子元素的宽高)
*{
margin:0;
padding:0;
}
.father{
position:relative;
min-height:500px;
background:pink;
}
.son{
position:absolute;
width:200px;
height:100px;//固定宽高
background:red;
top:50%;
left:50%;
margin-top:-50px;
margin-left:-100px;
}
<div class="father">
<div class="son">子元素的内容</div>
<div>
先让子元素的左上角居中,然后向上移动宽度的一般(50px),就达到了垂直居中的效果。
不足之处:要求指定子元素的宽高,才能写出margin-top和margin-left的属性。但通常情况下,对那些需要居中的元素来说,其宽高往往是由其内容决定的,不建议固定宽高。
方式二:绝对定位+translate(无需指定子元素的宽高,推荐)
*{
margin:0;
padding:0;
}
.father{
position:relative;
min-height:500px;
background:pink;
}
.son{
position:absolute;
background:red;
top:50%;
left:50%;
transform:translate(-50%,-50%);//动态计算宽高
}
<div class="father">
<div class="son">子元素的内容</div>
<div>
方式3:flex布局
将父容器设置为flex布局
*{
margin:0;
padding:0;
}
.father{
display:flex;
justify-content:center;
align-item:center;
min-height:100vh;
background:pink;
}
.son{
background:red;
}
<div class="father">
<div class="son">子元素的内容</div>
<div>
不足之处:给父容器设置justify-content:center和align-items:center之后,导致父容器里的所有子元素都垂直居中了,如果想要指定某个子元素居中,怎么办呢?
方式4:flex布局+margin:auto
先给父容器设置display:flex,再给指定的子元素设置margin:auto,即可让这个指定的子元素在剩余空间里水平垂直居中。
*{
margin:0;
padding:0;
}
.father{
display:flex;
min-height:100vh;
background:pink;
}
.son{
margin:auto;
background:red;
}
<div class="father">
<div class="son">子元素的内容</div>
<div>
10、两栏布局
一栏固定宽度,一栏自适应
浮动布局
<div id="left"></div>
<div id="right"></div>
div{
height:500px;
}
#left{
width:300px;
background-color:yellow;
float:left;
}
#right{
background-color:aqua;
margin-left:300px;
}
左侧栏固定宽度向左浮动,右侧主要内容则用margin-left留出左侧栏的宽度,默认宽度为auto,自动填满剩下的宽度。
浮动布局+overflow:hidden
<div id="left"></div>
<div id="right"></div>
div{
height:500px;
}
#left{
width:300px;
background-color:yellow;
float:left;
}
#right{
background-color:aqua;
overflow:hidden;
}
绝对定位
<div class="wrap">
<div id="left"></div>
<div id="right"></div>
</div>
div{
height:500px;
}
.wrap{
position:relative;
}
#left{
width:300px;
background-color:yellow;
}
#right{
background-color:aqua;
position:absolute;
top:0;
left:300px;
right:0;
}
弹性布局
<div class="wrap">
<div id="left"></div>
<div id="right"></div>
</div>
div{
height:500px;
}
.wrap{
display:flex;
}
#left{
width:300px;
background-color:yellow;
}
#right{
background-color:aqua;
flex:1;
}
11、三栏布局
两边栏固定中间自适应
方法一:绝对定位
左侧栏和右侧栏分别用绝对定位固定在左侧和右侧,中间栏则利用margin-left和margin-right空出左右栏位置来:
<div id="left">left</div>
<div id="right">right</div>
<div id="main">main</div>
*{
margin:0;
padding:0;
}
div{
height:100%;
}
#left{
width:200px;
background-color:yellow;
position:absolute;
top:0;
left:0;
}
#main{
background-color:aqua;
margin-left:200px;
margin-right:300px;
}
#right{
width:300px;
background-color:orange;
position:absolute;
top:0;
right:0;
}
方法二:浮动
<div id="left">left</div>
<div id="right">right</div>
<div id="main">main</div>
*{
margin:0;
padding:0;
}
div{
height:100%;
}
#left{
float:left;
width:200px;
background-color:yellow;
}
#right{
float:right;
width:300px;
background-color:orange;
}
#main{
margin-left:200px;
margin-right:300px;
background-color:aqua;
}
实现原理与前面的差不多
注意:
1、该方法里DOM节点中的left,right,main这三个块是不能换顺序的,也就是说这种方法的缺点:浏览器自上而下解析代码渲染DOM树,那么main内容区域不能被优先渲染出来。
2、为什么不能换顺序?因为我们要让他们在一行内显示,那么必须让左右这两个块漂浮起来不占原来的位置了,才能让main区域进来。
方法三:用BFC原理
BFC特性是触发了BFC的盒子不会和浮动的盒子重叠
<div id="left">left</div>
<div id="right">right</div>
<div id="main">main</div>
*{
margin:0;
padding:0;
}
div{
height:100%;
}
#left{
float:left;
width:200px;
background-color:yellow;
}
#right{
float:right;
width:300px;
background-color:orange;
}
#main{
overflow:hidden;//触发BFC
background-color:aqua;
}
此时main区域就是一个BFC区域,那么他不会被浮动的元素盖住,他的宽度是从不被left盖住的位置开始到被right盖住的区域之前这段宽度。缺点是:不能优先渲染main区域。
方法四:flex
利用flex布局中order属性
<div id="box">
<div id="main">main</div>
<div id="left">left</div>
<div id="right">right</div>
</div>
*{
margin:0;
padding:0;
}
div{
height:100%;
}
#box{
display:flex;
}
#left{
width:200px;
background-color:yellow;
order:0;
}
#main{
order:1;
width:100%;
background-color:aqua;
}
#right{
width:300px;
background-color:orange;
order:2;
}
方法五:圣杯布局
要求main区域优先渲染
原理:浮动+margin负值
<div class="main clearfix">
<div id="content">content</div>
<div id="left">left</div>
<div id="right">right</div>
</div>
.main{
padding: 0 200px 0 150px;
}
.content, .left, .right{
float:left;
position:relative;
height :400px;
line-height:400px;
}
.content{
width:100%;
background-color:#f5c531;
}
.left{
width:150px;
background-color:#a0c263;
margin-left:-100%;
left:-150px;
}
.right{
width:200px;
background:#a0c263;
margin-right:-200px;
/*margin-left:-200px;*/
/*right:-200px*/这两行也可以
}
1、首先给它们的父级元素main一个左padding值和右padding值,留出来给左右边栏的地方
2、给三个元素浮动起来,然后直接给content元素宽度100%,宽度全给了content,那么left和right是要掉下去的
结合浮动我们知道浮动起来的几个元素会排成一行内,而宽度不够才会掉下去,如果我给left块一个margin-left负值到一个界限,他就会回到上一行。margin-left:-100%,因为margin的百分比的值是父级盒子宽度的百分比,-100%自然向左走一个父级的宽度,
那么这个我位置不是我们想要的,再left:-150px
right只需margin-right:-200px.本来他在上面,但由于宽度不够别挤下来,现在给margin-right一个负值他就会上去。
注释两行也可以:先给margin-left:-200px(正好给200px的话就是正好贴在父级盒子的最右边。因为正好刚刚能上来,如果再多给点值还会再往左走,但这里不需要)被上面接纳,来到了他的父级盒子的贴着最右边:
然后再给一个right:-200px让他向右走200px
方法六:双飞翼布局
根据圣杯布局演化出来的一种布局。
<div class="main clearfix">
<div class="content-wrapper">
<div class="content">content</div>
</div>
<div id="left">left</div>
<div id="right">right</div>
</div>
.content-wrapper,.left, .right{
float:left;
height :400px;
line-height:400px;
}
.content-wrapper{
width:100%;
}
.content{
margin:0 200px 0 150px;
background-color:#f5c531;
height :400px;
line-height:400px;
}
.left{
width:150px;
background-color:#a0c263;
margin-left:-100%;
}
.right{
width:200px;
background:#a0c263;
margin-left:-200px;
}
1、这里left直接给margin-left:-100%就能想要的位置。因为left父级盒子是宽度100%的,不再是圣杯布局里的留出来左右padding值的父级自适应宽度的盒子,这里面使用content盒子的左右margin值留出来的定宽,所以直接就能把left盒子定到想要的位置
2、同理,right盒子也是因为这样,所以直接margin-left:-200px正好贴到父级盒子最右边,就能到想要的位置了。