前言:在这个月黑风高的夜晚,我来总结一下面试的时候非常爱问的CSS相关的问题,比如居中、布局、动画、清除浮动、定位以及BFC之类的。
话不多说,上正文。
CSS相关问题
1、css居中
分为水平居中和垂直居中,比如水平居中,文本级的标签就是text-align:center;容器级别的标签就是margin:auto;
垂直方向的居中比较麻烦,当然垂直方向的手段同时也适用于水平方向,比如定位和弹性盒子布局等等。
实现居中的方式主要有以下几种:
首先假设盒子宽高已知:
- 绝对定位+负margin:
<div class="outer">
<div class="inner"></div>
</div>
<style>
.outer{
position:relative;
background-color:lightblue;
width:500px;
height:500px;
}
.inner{
position:absolute;
background-color:pink;
width:200px;
height:200px;
top:50%;
left:50%;
margin:-100px 0 0 -100px;
}
</style>
- 绝对定位+margin:auto;
.outer{
position:relative;
background-color:lightblue;
width:500px;
height:500px;
}
.inner{
position:absolute;
background-color:pink;
width:200px;
height:200px;
top:0;
left:0;
bottom:0;
right:0;
margin:auto;
}
- 绝对定位+transform
.outer{
position:relative;
background-color:lightblue;
width:500px;
height:500px;
}
.inner{
position:absolute;
background-color:pink;
background-color:pink;
width:200px;
height:200px;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
- table-cell
.outer{
background-color:lightblue;
width:500px;
height:500px;
display:table-cell;
text-align:center;
vertical-align:middle;
}
.inner{
background-color:pink;
width:200px;
height:200px;
display:inline-block;
}
- flex布局
.outer{
background-color:lightblue;
width:500px;
height:500px;
display:flex;
justify-content:center;
align-items:center;
}
.inner{
background-color:pink;
width:200px;
height:200px;
display:inline-block;
}
如果盒子宽高未知的话,那么使用负margin的想当然就失效了。所以可以采用绝对定位+margin:auto以及transform。或者flex或者table-cell布局。
如果父盒子是根元素,也就是想让子盒子在整个页面居中,此时不适合用布局,因为父盒子之中的子元素都会受到布局的影响,则可以采用绝对定位+margin:auto以及transform等。
2、CSS布局
css布局中比较常问的布局就是三栏布局两侧定宽中间自适应,或者两栏等高一侧定宽一侧自适应。这几个布局都可以用flex来做,除了flex就是经典的两个圣杯布局和双飞翼布局(感觉挺麻烦的也不知道经典在哪里)
- flex布局
/*flex实现三栏等高布局,两栏定宽中间自适应*/
<div class="box">
<div class="left">left</div>
<div class="content">...很多内容</div>
<div class="right>right</div>
</div>
<style>
.box{
display:flex;
}
.left, .right{
width:100px;
backgound-color:pink
}
.content{
flex:1;
background-color:lightblue;
}
</style>
flex布局真心很方便,如果需要实现两列布局的话去掉.right就可以了。
- 采用浮动布局
三列布局的话很容易想到一列左浮动一列右浮动。
<div class="box">
<div class="left">left</div>
<div class="right>right</div>
<div class="content">...注意此时几个盒子的位置发生了改变</div>
</div>
<style>
.box{
overflow:hidden;
}
.left, .right{
width:200px;
height:200px;
background-color: red;
}
.left{
float:left;
}
.left{
float:right;
}
.content{
background-color:lightblue;
height:200px;
margin-left:200px;
margin-right:200px;
overflow:hidden;
}
</style>
如果是两栏布局一栏自适应的话,只需要去掉右浮动的元素和content中的margin-right即可。
- 圣杯布局
圣杯布局和前面所设置的浮动布局的不同之处就是改变的html代码。
然后css代码需要注意的几个点:
- 三栏全部左浮动
- 给中间的一栏宽度设为100%,旁边两栏定宽
- 左右两栏分别设置负margin
- 左右两栏设置相对定位,使其不压住中间盒子
假设html代码如下,而且不允许交换位置
<div class="box">
<div class="main">...注意此时几个盒子的位置发生了改变</div>
<div class="left">left</div>
<div class="right>right</div>
</div>
此时的css代码可以写为如下所示:
.box{
overflow:hidden;
padding: 0 300px 0 200px;
}
.right{
position:relative;
width:300px;
float:left;
margin-left:300px;
right:-300px;
background-color:red;
}
.left{
position:relative;
width:200px;
float:left;
margin-left:100%;
left:-200px;
background-color:red;
}
.main{
width:100%;
background-color:lightpink;
}
- 双飞翼布局
双飞翼布局的前提条件和圣杯布局是一样的,html中盒子位置的顺序不能改变。
圣杯布局和双飞翼布局解决问题的方案在前一半是相同的,也就是三栏全部float浮动,但左右两栏加上负margin让其跟中间栏div并排,以形成三栏布局。不同在于解决 “中间栏div内容不被遮挡”问题的思路不一样。
双飞翼布局多用了一个div来保证中间的盒子不被覆盖。
当然如果用flex布局设计,可以是left的order:-1;其他的保持不变就可以了。
<div class="box">
<div class="main">
<div class="content">注意此时外层盒子main包裹住了content</div>
</div>
<div class="left">left</div>
<div class="right>right</div>
</div>
.box{
overflow:hidden;
}
.right{
width:300px;
float:left;
margin-left:300px;
background-color:red;
}
.left{
width:200px;
float:left;
margin-left:100%;
background-color:red;
}
.main{
width:100%;
background-color:lightpink;
}
.content{
margin: 0 300px 0 200px;
}
3、CSS过渡和动画
css动画总是比较爱问,可是我是在是不想写,哎。再坚持一下吧。
在css3以前,我们实现动画的方式就是js或者flash,css3之后可以用纯css来写出过渡效果和动画。
首先明确一下过渡和动画的区别:
animation和transition的大部分操作的属性是相同的,主要区别在于transition的触发需要一个事件才可以改变属性,而animation的触发不需要任何事件;并且transition为两帧事件,而animation可以一帧一帧的。
而从效果上来看,过渡更像是一种黄油,可以是css的一些变化变得平滑,而动画则可以像flash一样,通过控制关键帧来控制每一补,实现更为复杂的动画效果。
3.1 transition
transition 属性是一个简写属性,用于设置四个过渡属性:
- transition-property:过渡效果的css属性的名称,all/none/propsName
- transition-duration:规定完成过渡效果所需要花费的时间,以秒或者毫秒为单位
- transition-timing-function:属性规定过渡效果的速度曲线。linear/ease/ease-in/ease-out,除此之外还有贝塞尔其曲线
- transition-delay:过渡效果的延迟时间,以秒或者毫秒来计
<style type="text/css">
div{
width: 100px;
height: 100px;
background-color: pink;
}
div:hover{
width: 300px;
background-color: lightblue;
transition: all 3s linear;
}
</style>
当将鼠标移动到div上的时候,元素过渡到设置的属性
3.2 animation
通过css3我们能够创建动画,animation也是一个简写属性:
- animation-name: 属性为@keyframes动画规定的名称
- animation-duration: 定义一个动画完成的时间,以秒或者毫秒计算
- animation-timing-function: animation-timing-function 规定动画的速度曲线。速度曲线定义动画从一套 CSS 样式变为另一套所用的时间。速度曲线用于使变化更为平滑。属性值和transition类似
- animation-delay:动画播放的延迟时间
- animation-iteration-count:动画播放的次数 n/infinate
- animation-direction:定义是否应该轮流反向播放动画.normal每个循环内动画向前循环,换言之,每个动画循环结束,动画重置到起点重新开始,这是默认属性。alternate动画交替反向运行,反向运行时,动画按步后退,同时,带时间功能的函数也反向,比如,ease-in 在反向时成为ease-out。reverse反向运行动画,每周期结束动画由尾到头运行。alternate-reverse反向交替, 反向开始交替动画,第一次运行时是反向的,然后下一次是正向,后面依次循环.
- animation-fill-mood:这个 CSS 属性用来指定在动画执行之前和之后如何给动画的目标应用样式. none动画执行前后不改变任何样式,forwards目标保持动画最后一帧的样式,backwards动画采用相应第一帧的样式,both动画将会执行 forwards 和 backwards 执行的动作。
动画的使用
1、当在 @keyframes 创建动画,把它绑定到一个选择器,否则动画不会有任何效果。
指定至少这两个CSS3的动画属性绑定向一个选择器:
• 规定动画的名称
• 规定动画的时长
div { animation :myAni 5s; -webkit-animation: myAni 5s; }
2、创建动画
@keyframes myAni{
from {background:red;}
to{background:yellow;}
}
4、CSS画形状
(1)画一个三角形
首先呢我们来画一个宽高均为0的盒子,四周的border均不相同;
<style type="text/css">
/*css代码*/
.triangle{
width: 0;
height: 0;
border:100px solid #000;
border-top-color:red;
border-bottom-color: yellow;
border-left-color: blue;
border-right-color: green;
}
</style>
<!-- HTML代码 -->
<div class="triangle">
</div>
可以得到如下效果
因此我们可以得到三角形的画法,如果想要画一个三角形就只留下其中的一块就可以;以一个朝上的三角形为例
.triangle{
width: 0;
height: 0;
border-bottom: 100px solid pink;
border-left:100px solid transparent;
border-right:100px solid transparent;
}
效果图如下:
如果想得到其他朝向的三角形,只需要在css中代码中加
transform:rotate(180deg);
或者根据情况将其他的边设为transparent即可。
.circle{
width: 0;
height: 0;
border-radius: 50%;
border-bottom: 100px solid lightblue;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
transform:rotate(45deg);
}
扩展:如何画一个带边框的三角形还是比较难的,我这里就不写了,贴上连接。
如何画一个带边框的三角形
(2)画一个圆形
使用border-radius
/*css代码*/
.circle{
width: 0;
height: 0;
border: 100px solid lightblue;
border-radius: 50%;
}
<!-- html代码 -->
<div class="circle"></div>
效果图如下图所示
如果想画一个半圆或者1/4的扇形,可以参照前面画三角形的做法
首先仍然可以将四个边角设置成不同的颜色来观察;
.circle{
width: 0;
height: 0;
border: 100px solid lightblue;
border-radius: 50%;
border-top-color: pink;
border-left-color: red;
border-right-color: yellow;
}
当然如果想得到一个水平的划分只需要将形状旋转45deg即可。
transform: rotate(45deg);
需要哪个半圆或者扇形就把其他的border设置为透明即可。
(3) 画一个0.5px的线
首先说一下画0.5px的线的原因,在pc端用1px的框线看起来还可以,但是在手机端看起来就比较难看。0.5px的就显得比较精致。用普通的写法,border:solid 0.5px red;iPhone可以正常显示,android下几乎所有的浏览器都会把0.5识别为0,即无边框状态.
一般UI为了美观都会采用0.5px而不是1px的细线。
① 使用scale
/*css代码*/
.bd-t{
position:relative;
width: 200px;
height: 200px;
background-color: lightblue;
}
.bd-t:after{
content: " ";
position: absolute;
left: 0;
bottom: -10px;
width: 100%;
height: 1px;
background-color: red;
/* 如果不用 background-color, 使用 border-top:1px solid red; */
-webkit-transform: scaleY(.5);
transform:scaleY(.5);
}
<!-- html代码 -->
<div class="bd-t"></div>
效果如下:
如果要实现四周都是细线
/*css代码*/
.bd-t{
position:relative;
width: 200px;
height: 200px;
background-color: lightblue;
}
.bd-t:after{
content: " ";
position: absolute;
left: 0;
top: 0;
width: 200%;
height: 200%;
border:1px solid red;
transform-origin: 0 0;
transform:scale(.5);
}
也可以修改成圆角的细线矩形来包裹:
.bd-t:after{
content: " ";
position: absolute;
left: 0;
top: 0;
width: 230%;
height: 230%;
border:1px solid red;
border-radius: 5%;
transform-origin: -30px -30px;
transform:scale(.5);
}
效果如下:
注意transform-oragin的使用。
② 使用border-image和css3的九宫格裁减
京东之前是这么做的,现在已经不被使用了。具体做法,请看下面demo结构:
├─demo/ ························ demo 目录
└─┬─ test.html ··············· test.html 文件
└─── pic.png ·················· png 图片文件
在text.html中有如下代码
.bd-t{
position: relative;
}
.bd-t::after {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 100%;
border-top: 1px solid transparent;
/* 下面用 stretch 和 round 都可以 */
border-image: url('pic.png') 2 1 1 1 stretch;
}
而 pic.png 的九宫格切法,如下图:
具体有关 border-image 的用法:
https://developer.mozilla.org/en-US/docs/Web/CSS/border-image
但是不推荐这种写法,毕竟图片质量比较大,能用代码解决的,不用图片.
③ weui的实现方式
这是一款微信团队开发的UI 组件 详情见: weui , (毕竟有现成的组件谁愿意重复造轮子呢,不过我也没看明白下面的实现比第一种简单到哪里去)。它的使用方式是这样的:
.weui-cell:before{
content:' ';
position:absolute;
left:0;
top:0;
height:1px;
border-top: 1px solid red;
color:red;
transform-origin:0 0;
transform:scaleY(.5);
}
5、CSS清除浮动的方式及原理
5.1 清除浮动的原因
父盒子高度塌陷,对后面的元素造成影响等
5.2 清除浮动的方法
(1)给需要清除浮动的元素加clear,比如可以消除后面的元素的浮动影响但是还是不能解决父盒子高度塌陷问题
(2)父元素的伪元素:after后面清除浮动,注意伪元素默认是内联元素,要加display:block
(3)父元素结束标签之间加一个没有内容的div设置clear:both
(4)父元素添加overflow:hidden
5.3 清除浮动原理
利用BFC(BlockingFormating Contexts)块格式化上下文,它规定了元素如何对其内容进行定位,以及与其他元素的关系。具有BFC特性的元素可以看做一个隔离的容器,里面的元素不会影响到外面的元素
形成bfc的条件:
body根元素;
浮动元素
绝对定位
display为in-block。table-cells和flex
overflow:hidden、auto。scroll
BFC常见的作用:
(1)阻止外边距折叠
问题案例:margin塌陷问题:在标准文档流中,块级标签之间竖直方向的margin会以大的为准,这就是margin的塌陷现象。可以用overflow:hidden产生bfc来解决。
如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中
(2)包含浮动元素
问题案列:高度塌陷问题,在通常情况下父元素的高度会被子元素撑开,而在这里因为其子元素为浮动元素所以父元素发生了高度坍塌,上下边界重合,这时就可以用BFC来清除浮动了
(3)阻止元素被浮动元素覆盖
问题案例:div浮动兄弟这该问题:由于左侧块级元素发生了浮动,所以和右侧未发生浮动的块级元素不在同一层内,所以会发生div遮挡问题。可以给右侧元素添加 overflow: hidden,触发BFC来解决遮挡问题。
6、CSS中的几个单位
css中的几个单位分为绝对长度和相对长度,下面介绍几个常用的单位。
(我只写几个常用的,其他的我就不写了,我脑阔疼)
(1)绝对长度单位
- px : 像素 (1px = 1/96th of 1in)
- pt : point,大约1/72英寸; (1pt = 1/72in)
- in : 英寸(1in = 96px = 2.54cm)
- cm/mm:厘米/毫米
(2)相对长度单位
- em : 它是描述相对于应用在当前元素的字体尺寸,所以它也是相对长度单位。一般浏览器字体大小默认为16px,则2em == 32px;
- rem : 根元素(html)的 font-size
- ch : 数字 0 的宽度
- ex : 依赖于英文字母小 x 的高度
<style type="text/css">
.p1{
font-size: 2em;
}
.p2{
font-size: 32px;
}
.p3{
font-size: 2rem;
}
.p4{
font-size: 32pt;
}
</style>
<p class="p2">哈哈哈</p>
<p class="p3">哈哈哈</p>
<p class="p4">哈哈哈</p>
结果显示:
7、css隐藏元素
通常隐藏元素的几种方式:
- display:none;
- visibility:hidden;
- opacity:0;
它们的区别如下:
(1)空间占据
display:none隐藏后不占据额外空间,会产生回流和重绘。
而visibility: hidden和opacity: 0;虽然隐藏了元素,但是仍然占据空间,他俩只会引起页面重绘
(2)子元素继承
display:none;不会被子元素继承,父元素都不存在,子元素自然也不会显示。父元素都不存在了,子元素自然也没有了。就算改变子元素的display也不会显示。
visibility:hidden;会被子元素继承,默认子元素也被隐藏,但是可以在子元素上设置visibility:visible来使子元素显示;
opacity: 0 也会被子元素继承,但是不能通过设置子元素opacity: 1使其重新显示;
(3)事件绑定
display:none上的元素已经不存在了,所以也无法触发绑定在它上面的事件;
visibility:hidden元素上绑定的事件也无法触发,
opacity:0上面绑定的事件是可以触发的。
(4)动画过渡
transition对于display是无效的
transition对于visibility也是无效的(亲测无效)
transition对于opacity是有效
参考文献
https://blog.csdn.net/Tyro_java/article/details/52013531
https://www.w3school.com.cn/cssref/pr_transform-origin.asp