CSS
BFC
-
定义:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关
从一个现象说起
一个盒子father没有设置height,其内容子元素son都为浮动的时候,无法撑起自身,即father的height一直为0,这个盒子没有形成BFC
-
如何创建BFC
- float的值不为none
- position的值不是static或者relative
- display的值是inline-block、flex或者inline-flex
- overflow:hidden(比较好的方式,不会影响到外部的布局)
-
BFC的其他作用
- 可以取消margin塌陷的问题
- 可以阻止元素被浮动元素覆盖
CSS盒模型
CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。
标准盒模型:一个块的总宽度=width+margin(左右)+padding(左右)+border(左右)
怪异盒模型:一个块的总宽度=width+margin(左右)(既width已经包含了padding和border值)
设置盒模型:box-sizing:border-box
CSS选择器优先级
样式的引用方式对css优先级的影响:
行内样式(写在标签的style属性中) > 内部样式表(写在头部的style标签中) > 外部样式表(通过link标签引用css文件)
但是有!important的样式除外
选择器对css样式优先级的影响:
!important > id选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 > 通配选择符 = 关系选择符
垂直居中的写法
1 flex
.parent{
width:400px;
height:400px;
display:flex;
align-items:center
}
.son{
width:200px;
height:200px;
}
2 margin自适应
.parent{
width:400px;
height:400px;
position:relative
}
.son{
width:200px;
height:200px;
position:absolute;
top:0;
bottom:0;
margin:auto
}
3 margin负值
.parent{
width:400px;
height:400px;
position:relative
}
.son{
width:200px;
height:200px;
position:absolute;
top:50%;
margin-top:-100px /*自身高度一半*/
}
4 父元素设置display:table-cell
.parent{
width:400px;
height:400px;
display:table-cell;
vertical-align:middle
}
.son{
width:200px;
height:200px;
}
5 absolute+transform
.parent{
width: 400px;
height: 400px;
background-color: cornflowerblue;
position: relative;
margin: 100px auto;
}
.child{
width: 100px;
height: 100px;
background-color: darkgreen;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
清除浮动
首先来看看浮动会产生哪些问题,当父容器未设置高度,且子元素设置为了浮动,那么子元素的高度可能会超过父元素,进而影响其他布局,来看个例子:左边是未清除浮动,子元素已经跑到父元素的兄弟元素上去了,后面是清除了浮动,父元素能够实现自适应高度,让子元素一直保持在父元素内部
清除浮动的方法
1.我们可以在浮动元素尾部加上一个标签,标签加上clear类,clear类设置为clear:both
.clear{
clear:both
}
2.可以在父元素上加上overflow:hidden/auto
.container{
overflow:hidden
}
当元素设置了overflow样式且值部位visible时,该元素就构建了一个BFC,BFC在计算高度时,内部浮动元素的高度也要计算在内,也就是说技术BFC区域内只有一个浮动元素,BFC的高度也不会发生塌缩,所以达到了清除浮动的目的,
3.兼容性最好的,after伪元素
为父元素添加一个clearfix类
.clearfix::after{
content:'';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
4.可以给容器parent添加浮动属性(不推荐,容易改变整体布局)
flex布局
flex-direction:决定主轴的方向(即子item的排列方法) .box { flex-direction: row | row-reverse | column | column-reverse; }
flex-wrap:决定换行规则 .box{ flex-wrap: nowrap | wrap | wrap-reverse; }
flex-flow: .box { flex-flow: || ; }
justify-content:对其方式,水平主轴对齐方式
align-items:对齐方式,竖直轴线方向
项目的属性(元素的属性):
order属性:定义项目的排列顺序,顺序越小,排列越靠前,默认为0
flex-grow属性:定义项目的放大比例,即使存在空间,也不会放大
flex-shrink属性:定义了项目的缩小比例,当空间不足的情况下会等比例的缩小,如果定义个item的flow-shrink为0,则为不缩小
flex-basis属性:定义了在分配多余的空间,项目占据的空间。
flex:是flex-grow和flex-shrink、flex-basis的简写,默认值为0 1 auto。
align-self:允许单个项目与其他项目不一样的对齐方式,可以覆盖align-items,默认属性为auto,表示继承父元素的align-items
三栏布局
两侧定宽,中间自适应
1.采用浮动加margin的方式,注意:这里html标签顺序有影响,必须先放left和right最后放middle
<div class="left"></div>
<div class="right"></div>
<div class="middle"></div>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.left{
width: 200px;
float: left;
height: 100vh;
background-color: lightblue;
}
.right{
width: 200px;
float: right;
height: 100vh;
background-color: lightblue;
}
.middle{
margin: 0 200px ;
height: 100vh;
background-color: lightgreen;
}
2.position
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.left,.middle,.right{
position: absolute;
height: 100vh;
}
.left,.right{
width: 200px;
background-color: lightskyblue;
}
.left{
left: 0;
}
.right{
right: 0;
}
.middle{
left: 200px;
right: 200px;
background-color: lightgreen;
}
3.flex
<div class="container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container{
width: 100%;
height: 100vh;
display: flex;
/* justify-content: space-between; */
}
.left,.right{
width: 200px;
background-color: lightblue;
}
.middle{
flex:1;
background-color: lightgreen;
}
vm和vh
1vh等于viewport高度1/100,100vh即当前视口大小高度,1vw表示视口宽度的1/100,100vw即等于当前视口宽度100%
em布局和rem布局
em是根据自身fontsize进行计算
rem是根据html根节点的fontsize来进行计算
冒泡与捕获
div1.addEventListener('click',function(){console.log('div1')})//true为捕获,false为冒泡,默认为冒泡
div2.addEventListener('click',function(){console.log('div2')})
div3.addEventListener('click',function(){console.log('div3')})
当我们点击div3的时候,会依次输出div3,div2,div1,默认为冒泡
我们将addEventListener的第三个参数换成true,改为捕获,会依次输出div1,div2,div3
如何阻止冒泡喃
div1.addEventListener('click',function(e){
e.stopPropagation()
console.log('div1')
})
div2.addEventListener('click',function(e){
e.stopPropagation()
console.log('div2')
})
div3.addEventListener('click',function(e){
e.stopPropagation()
console.log('div3')
})
这样就能阻止冒泡了,但是如果此时我们将参数设置为true,那么我们点击什么都是打印的div1
事件委托
所谓事件委托,就是不把事件绑定在元素本身,而是绑定在其父元素上,通过冒泡获取元素,比如一个ul里面有很多li,我们想实现点击一个li,打印一下这个 li的内容,传统做法是给每一个li绑定一个事件,这样太过于繁琐,而且会有很多函数驻留在内存中,占用内存,事件委托方法。同时也适合动态添加元素,比如我们在ul中又动态添加了li,我们就不需要再给其添加和之前一样类似的函数了,通过事件委托,被创建之后就具有点击事件了
var ul = document.querySelector('ul')
ul.addEventListener('click',function(e){
console.log(e.target.innerHTML)
})
e.target就是通过冒泡返回的点击源,点击li则e.target为li
js如何获取盒模型的宽和高
假设已经获取了DOM
//只能获取使用内联样式的元素的宽和高
dom.style.width/height
//这种方法获取的是浏览器渲染以后的元素的宽和高,这种写法兼容性更好一些。
window.getComputedStyle(dom).width/height
//这种方法获取的是浏览器渲染以后的元素的宽和高,无论是用何种方式引入的css样式都可以,但只有IE浏览器支持这种写法。
dom.currentStyle.width/height
//这种方式获得到的宽度是内容content+padding+border
//此 api 的作用是:获取一个元素的绝对位置。绝对位置是视窗 viewport 左上角的绝对位置。
//此 api 可以拿到六个属性:left、top、right、bottom、width、height。
dom.getBoundingClientRect().width/height
画一条0.5px的线
-
采用meta viewport的方式(viewport只针对移动端,只在移动端上才能看到效果)
<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/> -
采用transform: scale()的方式
.line1{ width: 300px; height: 1px; margin-top: 100px; background-color: cornflowerblue; transform:scaleY(0.5); }
link标签和import标签的区别
link标签属于HTML标签,而@import是css提供的
页面被加载的时候,link会同时被加载,而@import引用的css会等到页面加载结束之后才会加载
link是html标签,因此没有兼容性,而@import只有IE5以上才会识别
link方式样式的权重高于@import的
@import url('路径')
原生JS实现拖拽功能
html
<div>点击拖拽</div>
css,注意:一定要将定位设置为absolute
div{
width: 50px;
height: 50px;
background-color: lightseagreen;
position: absolute;
}
js
var div = document.querySelector('div')
var isDrag=false
div.addEventListener('mousedown',function(){
isDrag=true
})
div.addEventListener('mouseup',function(){
isDrag=false
})
window.addEventListener('mousemove',function(e){
if(isDrag){
console.log(e.clientX)
div.style.left=(e.clientX-div.clientWidth/2)+'px'
div.style.top=(e.clientY-div.clientHeight/2)+'px'
}
})
CSS3新增内容
- CSS3边框:border-radius、box-shadow、border-image
- CSS3背景:background-size、background-origin(规定背景图片定位区域)
- CSS3文字效果:text-shadow、word-wrap(对长单词进行拆分并换行)
- CSS3 2D转换:transform: translate()、rotate()、scale()
- CSS3 3D转换:transform: rotateX()、rotateY()
- CSS3 过渡:transition
- CSS3 动画:animation
- CSS3用户界面:resize(是否可由用户调整元素尺寸)、box-sizing(定义盒模型)
calc属性
calc用户动态计算长度值,任何长度值都可以使用calc()函数计算,需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);
css动画如何实现
创建动画序列,需要使用animation属性或其子属性,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 @keyframes规则实现。
transition也可实现动画。transition强调过渡,元素的一个或多个属性发生变化时产生的过渡效果。
transition和animation的区别
1、transition 是过渡,是样式值的变化的过程,只有开始和结束;animation 其实也叫关键帧,通过和 keyframe 结合可以设置中间帧的一个状态;
2、animation 配合 @keyframe 可以不触发时间就触发这个过程,而 transition 需要通过 hover 或者 js 事件来配合触发;
3、animation 可以设置很多的属性,比如循环次数,动画结束的状态等等,transition 只能触发一次;
4、animation 可以结合 keyframe 设置每一帧,但是 transition 只有两帧;
5、在性能方面:浏览器有一个主线程和排版线程;主线程一般是对 js 运行的、页面布局、生成位图等等,然后把生成好的位图传递给排版线程,而排版线程会通过 GPU 将位图绘制到页面上,也会向主线程请求位图等等;我们在用使用 aniamtion 的时候这样就可以改变很多属性,像我们改变了 width、height、postion 等等这些改变文档流的属性的时候就会引起,页面的回流和重绘,对性能影响就比较大,但是我们用 transition 的时候一般会结合 tansfrom 来进行旋转和缩放等不会生成新的位图,当然也就不会引起页面的重排了;
关于js动画和css3动画的差异性
功能涵盖面,js比css大,复杂;js在主线程中运行,容易丢帧;js灵活,兼容性好;
实现/重构难度不一,CSS3比js更加简单, 性能跳优方向固定
对帧速表现不好的低版本浏览器,css3可以做到自然降级
css动画有天然事件支持;浏览器可以对css动画进行优化
css有兼容性问题,笨重,代码冗长;强制gpu加速
css比js动画流畅的原理是因为在复合线程中进行动画处理,所以节省了昂贵的主线程资源
隐藏页面中某个元素的方法
opacity=0;visibility=hidden;display:none;position移到外部;z-index图层遮盖
visibility=hidden,opacity=0,display:none区别
- opacity=0,元素透明度为0,被隐藏,但是不改变页面布局,点击这个元素相应部分,绑定在这个元素上面的事件仍然能够触发
- visibility=hideen,隐藏元素,不会改变布局,仍然存在于原来非透明的时候那个位置,但是绑定的事件不会触发
- display=none,元素不显示,且会改变布局,可以理解为暂时将元素从页面中删除了
子元素继承
display:none不会被子元素继承,但是父元素都不在了,子元素自然也就不会显示了,皮之不存,毛之安附~~
visibility:hidden 会被子元素继承,可以通过设置子元素visibility:visible 使子元素显示出来(显示出来之后子元素dom事件可用)
opacity: 0 也会被子元素继承,但是不能通过设置子元素opacity: 1使其重新显示
inline-block、inline和block的区别
- block:块级元素,前后都有换行符,可设置width和height,padding margin垂直水平方向均有效
- inline:内联元素,前后无换行符,无法设置宽高,垂直方向的padding和margin无效
- inline-block:内联块级元素(行内块元素),前后无换行符,可以设置宽高,水平垂直方向的padding和margin均有效
为什么img是inline还可以设置宽高
img属于替换元素,替换元素一般有内在尺寸和宽高比,所以具有width和height,所以可以设置宽高
HTML中替换元素:input img textarea select
双边距重叠问题(外边距折叠)
多个相邻(兄弟或者父子关系)普通流的块元素垂直方向marigin会重叠
折叠的结果为:
两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。 两个外边距一正一负时,折叠结果是两者的相加的和。
css画三角形
.triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
CSS+JS写时钟
核心是transform:rotate()和定时器
旋转中心设置:transform-origin:left
表盘刻度可以通过背景图来实现
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container{
width: 400px;
height: 400px;
margin: 100px auto;
background-color: lightskyblue;
border-radius: 200px;
position: relative;
}
.hour{
height: 2px;
width: 100px;
background-color: red;
position: absolute;
top: 50%;
margin-top: -1px;
left: 50%;
transform-origin: left;
}
.minute{
height: 2px;
width: 120px;
background-color: green;
position: absolute;
top: 50%;
margin-top: -1px;
left: 50%;
transform-origin: left;
}
.second{
height: 2px;
width: 160px;
background-color: beige;
position: absolute;
top: 50%;
margin-top: -1px;
left: 50%;
transform-origin: left;
}
</style>
</head>
<body>
<div class="container">
<div class="hour"></div>
<div class="minute"></div>
<div class="second"></div>
</div>
<script>
var hour = document.querySelector('.hour')
var minute = document.querySelector('.minute')
var second = document.querySelector('.second')
let h=0
let m=0
let s=0
setInterval(() => {
s=s+6
second.style.transform=`rotate(${s}deg)`
if(s%360==0){
m=m+6
minute.style.transform=`rotate(${m}deg)`
}
if(m%360==0&&m!=0){
h=h+6
hour.style.transform=`rotate(${h}deg)`
}
}, 1000);
CSS+animation实现硬币动画
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.coin{
width: 100px;
height: 100px;
border-radius: 50%;
background-color: cornflowerblue;
margin: 100px auto;
animation: rotate 5s linear infinite;
}
.coin:hover{
animation-play-state: paused;
}
@keyframes rotate {
0%{
transform:rotateY(0deg)
}
100%{
transform:rotateY(360deg)
}
}
</style>
<div class="coin"></div>
CSS预处理
scss
定义变量
//定义颜色
$colors:(
"primary":#db9e3f,
"info":#4b67af,
'blue-2':#00ADFF,
"white":#fff,//当命名与内置属性冲突的时候用引号将其包裹
"light":#f9f9f9,
);
//字体大小
$base-font-size:1rem;
$font-sizes:(
xxs:0.6154,//8px
xs:0.7692,//10px
sm:0.9231,//12px
md:1,//13px
lg:1.0769,//14px
xl:1.2308,//16px
);
//布局
$flex-jc:(
start:flex-start,
end:flex-end,
center:center,
between:space-between,
around:space-around,
);
$flex-ai:(
start:flex-start,
end:flex-end,
center:center,
// between:space-between,
// around:space-around,
stretch:stretch,
);
生成工具类
@each $colorKey,$color in $colors{
.text-#{$colorKey}{
color:$color
}
.bg-#{$colorKey}{
background-color:$color;
}
}
//text
@each $var in (left,center,right){
.text-#{$var}{
text-align: $var !important;
}
}
@each $key,$value in $flex-jc{
.jc-#{$key}{
justify-content: $value;
}
}