盒模型
包括:外边距(margin)、边框(border)、内边距(padding)、实际内容(content)四个属性。
CSS盒模型:标准模型 + IE模型
标准盒子模型:宽度=内容的宽度(content)+ border + padding
低版本IE盒子模型:宽度=内容宽度(content+border+padding),如何设置成 IE 盒子模型:box-sizing: border-box;
position 属性值
static:默认定位,对象遵循正常文档流。top,right,bottom,left等属性不会被应用。
relative:对象遵循正常文档流,但将依据top,right,bottom,left等属性在正常文档流中偏移位置。而其层叠通过z-index属性定义。
absolute:对象脱离正常文档流,使用top,right,bottom,left等属性进行绝对定位。而其层叠通过z-index属性定义。
fixed:对象脱离正常文档流,使用top,right,bottom,left等属性以窗口为参考点进行定位,当出现滚动条时,对象不会随着滚动。而其层叠通过z-index属性定义。
sticky:具体是类似 relative 和 fixed,在 viewport 视口滚动到阈值之前应用 relative,滚动到阈值之后应用 fixed 布局,由 top 决定。
外边距合并
两个在普通文档流中的“相邻”元素外边距相遇的时候发生合并的情况。这个“相邻”可以是父子相邻,兄弟相邻,如果一个元素内部没有东西,自身的上下边距相遇时也会发生外边距合并。
合并的结果
两个外边距都是正数时,取两者之中的较大者;两个外边距都是负数时,取两者之间绝对值较大者;当一正一负时,取两者的和。
- 父元素和子元素:在正常的文档流当中,父元素没有边框或padding,那么父子之间会发生外边距合并。解决:给父元素加边框/设置父元素的padding
- 自身元素:加边框/加padding/设置overflow:hidden(它内部形成了一个空间,自身的margin被这个空间隔离开)。
不产生外边距合并
- 浮动元素不与任何元素产生外边距合并
- inline-block元素不合并
- 使用绝对定位的元素,不与任何元素发生外边距合并
- 子元素加了div包裹之后,利用overflow:hidden外边距不合并,可见创建BFC与子元素不发生合并。在外层形成了BFC真正把两者的外边距隔离开来。
总的来说,外边距合并不一定是两个相邻元素,不相邻的也可能会发生外边距合并。只要它们的外边距会融合到一起,没有分界线(可以是边框、padding,也可以是BFC形成的空间)隔开,就
有可能发生外边距合并。
去除inline-block内缝隙
两个相邻的inline-block 元素中间会有间隙
- html内标签不含空格
- 标签可以换行,但是要保证标签相接的地方没有空格
- 利用负margin(一般-4px左右)(margin-top和margin-left移动的是自己,margin-right和margin-bottom移动的是周围的元素。因为margin的意思是要让周围的元素有多少距离,比如说10px。根据文档流的顺序,当前的元素距离下一个元素要有10px的位置。因此,如果设置的是right和bottom,自然就是下一个元素移动。不然当前的元素和它前面的元素margin就会受到影响。)
- 利用浮动 (容器设置overflow:auto,容器内inline_block元素float:left)
- 父元素font-size,在容器里面的元素需要把字体大小重置回来。
BFC
浮动元素、绝对定位元素、非块级元素的块级容器(例如 inline-blocks, table-cells, 和 table-captions)以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的块级格式化上下文。简单的来说,BFC就是一个独立的空间,内部的元素不受外部元素影响。
主要有以下一些用处
清除浮动
防止外边距合并
设计布局
形成 BFC 的条件
五种:
• 浮动元素,float 除 none 以外的值
• 定位元素,position(absolute,fixed)
• display 为以下其中之一的值 inline-block,table-cell,table-caption
• overflow 除了 visible 以外的值(hidden,auto,scroll)
• HTML 就是一个 BFC
BFC 的特性:
• 内部的 Box 会在垂直方向上一个接一个的放置。
• 垂直方向上的距离由 margin 决定
• bfc 的区域不会与 float 的元素区域重叠。
• 计算 bfc 的高度时,浮动元素也参与计算
• bfc 就是页面上的一个独立容器,容器里面的子元素不会影响外面元素。
父容器使用overflow: auto| hidden撑开高度的原理
当元素设置浮动时,父元素感知不到元素的存在,造成高度塌陷。在父容器使用overflow属性时形成一个BFC,使其内部元素不受外界的影响。
BFC有三个特性:
BFC会阻止垂直外边距(margin-top、margin-bottom)折叠
BFC不会重叠浮动元素
BFC可以包含浮动
根据第三条特性就可以知道,父容器的高度可以被撑开。
清除浮动
.clearfix:after{ /* 在clearfix后面添加一个伪元素 /
content: ' '; / 伪元素的内容为空白字符 /
display: block; / 因为伪元素生成的默认为行内又元素,而clear对象一定是块级元素,所以这里设置一下display属性。 /
clear: both; / 不允许元素两边有浮动元素 /
}
.clearfix{
zoom: 1; / “”号是IE68的一个bug,IE68看到以“”开头的代码,会忽略星号,执行后面的代码。而zoom的原意是放大。它也会触发BFC,在IE里面其实不叫BFC,叫hasLayout 。/
}
zoom是IE的特有属性,可以设置对象的缩放比例。后面可以接数字或者百分数,也就是表示缩放的比例。经常用zoom: 1;来触发IE的hasLayout、清除浮动以及解决外边距合并的问题。因为伪元素在IE8是部分支持,IE8以下不支持,所以上述的代码在IE中也能达到清除浮动的效果。
BFC是形成一个内部的独立小空间,不受外部元素影响。而上述方法只是让父元素感知到浮动元素的存在,把内容撑开,不会形成独立的空间。
清除浮动方法及原理
清除浮动常用的四种方式:
- 父级
div
定义height
- 额外标签法: 在有浮动的父级元素的末尾插入了一个没有内容的块级元素div 并添加样式
clear:both
。 - 利用伪元素:父级div定义 伪类:after,我们可以写一个
.clearfix
工具样式,当需要清除浮动时,就为其加上这个类.clearfix:after { display: block; clear :both; content: '';}
。 - 父级添加
overflow
属性: 包含浮动元素的父标签添加样式overflow
为hidden
或auto
,通过触发BFC方式,实现清除浮动
清除浮动的四种方式及其原理理解
负边距 /position: relative
负margin和position: relative在让元素产生偏移时都没有脱离文档流。但是利用负margin让元素产生偏移时,元素原来的位置会被占据;而position: relative元素原来的位置不会被占据,仍然会被保留。
使用 相对定位 时,无论是否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框
负边距
margin-top和margin-left是移动自己(偏移后会对后面的元素有影响,比如设置margin-top:-10px,后面的元素也会跟着往下移),而margin-right和margin-bottom是让周围的元素移动。
position: relative 的元素发生偏离后不会影响到其他的元素的偏移
利用负margin来扩大面积:一个元素没有设置 width,只有左右的负margin,那么它就会变宽
margin 百分比
属性值为百分比时的边距是基于父元素的宽度来计算的。默认情况下writing-mode的值为 horizontal-tb,即水平书写方式。当把书写模式修改为纵向的时候,margin-top/bottom/left/right的百分比值都将会以包含元素(父元素)的高度为参照 https://blog.csdn.net/qq_40776187/article/details/87865123
两栏布局
- 左 float, + 右 margin-left(右边自适应)
- 右 float,margin-right
- BFC + float
.aside {
width: 300px;
float: left;
}
.main {
overflow: hidden;
} - float + 负 margin
.left {
width: 100%;
float: left;
background: #f00;
margin-right: -200px;
}
.right {
float: left;
width: 200px;
background: #0f0;
} - flex
flex: flex-grow, flex-shrink 和 flex-basis的简写
flex 的默认值是 0 1 auto。
.container {
display: flex;
}
.left {
flex: 0 0 200px;
}
.right {
flex: 1;
} - position + margin
.container {
position: relative;
}
.left {
position: absolute;
width: 200px;
}
.right {
width: 100%; /* 基于包含块的百分比/
margin-left: 200px; / 避免被前面的left 盖住*/
}
三栏布局
position + margin-left + margin-right
.wrap {
position: relative;
}
.left {
position: absolute;
left: 0;
top: 0;
width: 200px;
}
.right {
position: absolute;
right: 0;
top: 0;
width: 200px;
}
.middle {
margin-left: 200px;
margin-right: 200px;
}-
圣杯布局
代码:https://www.yuque.com/tuture/interview/htok5l?viewer=lake#TjkAS
left盒子负内边距-100%的解释(https://segmentfault.com/a/1190000014546205).container { padding: 0 300px 0 200px; border: 1px solid black; } .content { float: left; width: 100%; background: #f00; } .left { width: 200px; background: #0f0; float: left; margin-left: -100%; position: relative; left: -200px; } .right { width: 300px; background: #00f; float: left; margin-left: -300px; position: relative; right: -300px; }
中间内容
左侧区域
右侧区域
-
flex
.wrapper { display: flex; } .content { flex: 1 1; order: 2; background: #f00; } .left { flex: 0 0 200px; order: 1; background: #0f0; } .right { flex: 0 0 300px; order: 3; background: #00f; }
圣杯布局和双飞翼布局
- 共同点:三栏全部float浮动,但左右两栏加上负margin让其跟中间栏div并排,以形成三栏布局。负边距是这两种布局中的重中之重
- 不同点:解决“中间栏div内容不被遮挡”的思路不同
圣杯布局
- 1.三者都设置向左浮动
- 2.设置middle宽度为100%;
- 3.设置负边距, left设置负左边距为100%, right设置负左边距为负的自身宽度
- 4.设置content的padding值给左右两个子面板留出空间
- 5.设置两个子面板为相对定位,
left面板
的left值为负的left面板
宽度,right面板
的right值为负的right面板
的值
但是圣杯布局有个问题:当面板的middle部分比两边的子面板宽度小的时候,布局就会乱掉。因此也就有了双飞翼布局来克服这个问题。如果不增加任何标签,想实现更完美的布局非常困难,因此双飞翼布局在主面板上选择了加一个标签
双飞翼布局
- 1.三者都设置向左浮动。
- 2.设置middle宽度为100%。
- 3.设置 负边距,left设置负左边距为100%,right设置负左边距为负的自身宽度
- 4.设置middle-content的margin值给左右两个子面板留出空间。
对比两者可以发现,双飞翼布局与圣杯布局的主要差别在于:
- 1.双飞翼布局给主面板(中间元素)添加了一个父标签用来通过margin给子面板腾出空间
- 2.圣杯布局采用的是padding,而双飞翼布局采用的margin, 解决了圣杯布局的问题
- 3.双飞翼布局不用设置相对布局,以及对应的left和right值
详解查看 常见CSS布局的实现
https://www.jianshu.com/p/be0094ace1c9
bfc
W3c定义:
Formatting context(格式化上下文) 是 CSS2.1 规范中的一个概念。是页面中的一块渲染区域,并且有一套渲染规则,决定了子元素如何定位,以及和其他元素的关系和相互作用。
BFC是一种布局方式,在这种布局方式下,盒子们自所在的容器块顶部一个接一个垂直排列,水平方向上撑满整个宽度(普通流)。具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的BFC(块级格式上下文)。
两个相邻的BFC之间的距离由margin决定。在同一个BFC内部,两个垂直方向相邻的块级元素的margin会发生“塌陷”。
触发BFC:
float属性不为none
overflow不为visible(可以是hidden、scroll、auto)
position为absolute或fixed
display为inline-block、table-cell、flex
body根元素
应用:
- 同一个 BFC 下垂直相邻块元素外边距会发生折叠。要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
- 清除内部浮动。触发容器的 BFC,那么容器将会包裹着浮动元素overflow。
- 创建自适应两栏布局。BFC 可以阻止元素被浮动元素覆盖
容器等宽
table-cell
.left, .middle, .right{
display: table-cell;
width: 3000px;
}
flex
.wrap {
width: 100%;
flex-direction: row;
display: flex;
}
.div {
//取值为一个非负数字,为 flex-grow 值,flex-shrink :1,flex-basis :0%
flex-grow: 1;
}
百分比
水平、垂直均相对于父元素居中
行内元素水平居中
把行内元素包裹在父元素(
等)中,并且在父元素设置
container{
text-align:center;
}
适用于文字,链接,及其inline或者inline-block、inline-table和inline-flex。
块状元素的水平居中
设置左右margin为auto,元素设置:
center{
margin:0 auto;
}
多个块状元素水平居中
方法1: 将元素设置为display: inline-block,在父元素设置text-align: center。
方法2: 使用flexbox。
flex布局默认为块级元素,要设置元素为flex布局,只需在父元素上设置
display: flex;
justify-content: center;
若要设置行内元素,同理设置父元素:display: inline-flex
已知高度宽度元素的水平垂直居中
绝对定位+负margin
.container{
position: relative;
}
.item{
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
}
将填满整个父容器
.container{
position: relative;
}
.center{
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;
}
inline或者inline-block 元素垂直居中
设置父元素:
.container {
display: table-cell;
text-align: center;
vertical-align: middle;
}
css3的transform
translate是基于元素本身的宽高去计算百分比的,所以同样适用于宽度和高度都不固定的情况
.container{
position:relative;
}
.center{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
flex布局
.container{
display:flex;
justify-content:center;
align-items: center;
}
用js控制
父元素相对定位,子元素绝对定位;js动态设置top,left
childDom.style.top = (parent.offsetHeight - childDom.offsetHeight) / 2 + "px";
childDom.style.left = (parent.offsetWidth - childDom.offsetWidth) / 2 + "px";
CSS 权重和优先级
常用选择器权重优先级:!important > id > class > tag
!important可以提升样式优先级,但不建议使用。如果!important被用于一个简写的样式属性,那么这条简写的样式属性所代表的子属性都会被应用上!important。 例如:background: blue !important;
Flex 布局
● 弹性盒布局,CSS3 的新属性,用于方便布局,比如垂直居中
● flex属性是 flex-grow、flex-shrink 和 flex-basis 的简写
flex:1 非负数字,为 flex-grow 值,flex-shrink : 1,flex-basis :0%
flex:0 对应的三个值分别为 0 1 0%
flex :一个长度或百分比,则为 flex-basis 值,flex-grow : 1,flex-shrink : 1,(0% 是一个百分比)
(https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html)
画一个大小为父元素宽度一半的正方形
子元素设置:width: 50%; padding-bottom: 50%;
padding:% 规定基于父元素的宽度的百分比的内边距。
正方形
https://www.yuque.com/tuture/interview/htok5l#C5TDN
● width 设置百分比
● padding 撑高
● 如果只是要相对于 body 而言的话,还可以使用 vw 和 vh
● 伪元素设置 margin-top: 100%撑高
固定宽高比
在div的width固定的情况下,设置height为0,使内容自然溢出,再通过设置padding-bottom使元素有一定高度。
.element {
/* 16:9宽高比,则设padding-bottom:56.25% /
/ height: 0px, 防止矩形被里面的内容撑出多余的高度*/
width: 100vw;
height: 0px;
padding-bottom: 56.25%;
background: pink;
}
当margin/padding取形式为百分比的值时,无论是left/right,还是top/bottom,都是以父元素的width为参照物的!
伪类和伪元素
css引入伪类和伪元素概念是为了格式化文档树以外的信息。伪类和伪元素是用来修饰不在文档树中的部分。
伪类
伪类 用于当元素处于某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。比如说,用户悬停在指定的元素时,我们可以通:hover来描述这个元素的状态。虽然它和普通的css类类似,可以为已有的元素添加样式,但是它只有处于dom树无法描述的状态下才能为元素添加样式,所以将其称为伪类。
伪元素
伪元素 用于创建不在文档树中的元素,并为其添加样式,比如说,我们可以通过:before来在一个元素前添加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。
css 选择器
通用选择器(*)
标签选择器(div)
class选择器(.wrap)
id选择器(#wrap)
属性选择器(E[att], E[att=val], E[att~=val])
E[att]: 匹配所有具有att属性的E元素,不考虑它的值
E[att=val]:匹配所有att属性等于"val"的E元素
E[att~=val]:匹配所有att属性具有多个空格分隔的值、其中一个值等于"val"的E元素
相邻选择器(h1 + p)
子选择器(ul > li)
后代选择器(li a)
伪类选择器:
E:first-child:匹配父元素的第一个子元素
E:link 匹配所有未被点击的链接
E:focus 匹配获得当前焦点的E元素
E:not(s) 反选伪类,匹配不符合当前选择器的任何元素
css解析规则
CSS选择器是 从右向左解析 。
两种匹配规则的性能差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点),而从左向右的匹配规则的性能都浪费在了失败的查找上面。https://juejin.cn/post/6844904117819850765#heading-7
display: none和 visibility:hidden
是否占据空间
display: none 不占据空间
visibility:hidden 占据空间
是否渲染
display:none,会触发reflow(回流),进行渲染。
visibility:hidden,只会触发repaint(重绘),因为没有发现位置变化,不进行渲染。
是否是继承属性
display:none,display不是继承属性,元素及其子元素都会消失。
visibility:hidden,visibility是继承属性,若子元素使用了visibility:visible,则不继承,这个子孙元素又会显现出来。
opacity 会将元素设置为透明,但是其位置也在页面文档流中,不会被删除,所以会触发浏览器渲染引擎的重绘
em rem vh vw calc(), line-height 百分比
em
em: 相对父元素的font-size,具有继承的特点。如果字体大小是16px(浏览器的默认值),那么 1em = 16px
rem
rem:相对根节点html的字体大小来计算,不会像em那样,依赖于父元素的字体大小,而造成混乱
vw 和vh
vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%。
vh:viewpoint height,视窗高度,1vh等于视窗高度的1%。
vmin:取当前vw和Vh中较小的那一个值, vmax:取当前Vw和Vh中较大的那一个值
vw、vh 与 % 百分比的区别:
- % 是相对于父元素的大小设定的比率,vw、vh 是视窗大小决定的。
- vw、vh 优势在于能够直接获取高度,而用 % 在没有设置 body 高度的情况下,是无法正确获得可视区域的高度的,所以这是挺不错的优势。
calc()
calc(): CSS3中新增的一个函数, 用于动态计算宽/高,使用数学表达式来表示
- 使用“+”、“-”、“*” 和 “/”四则运算;
- 可以使用百分比、px、em、rem等单位;
- 可以混合使用各种单位进行计算;
- 表达式中有“+”和“-”时,其前后必须要有空格,如"width: calc(12%+5em)"这种没有空格的写法是错误的;
vertical-align
用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式。
可被用于两种环境:
- 使行内元素盒模型与其行内元素容器垂直对齐。
- 垂直对齐表格单元内容
line-height 百分比
可以直接查看MDN上的相关解释:
line-height 属性被指定为以下任何一个:
- 一个 <数字>: 该属性的应用值是这个无单位数字<数字>乘以该元素的字体大小
- 一个 <百分比>:与元素自身的字体大小有关。计算值是给定的百分比值乘以元素计算出的字体大小
- 一个 <长度> :必须px, em等,详细查看CSS长度
- 关键词 normal。
rem 布局
实际开发过程中,可以使用 lib-flexible库,但是如果每次写的时候都要手动去计算有点太过麻烦了,我们可以通过在webpack中配置 px2rem-loader, 或者 pxrem-loader,主要原理就是需要自己配置 px转rem的计算规则,在编辑的时候直接计算转成rem。所以在开发的时候直接按照设计稿的尺寸写px,编译后会直接转化成rem;
推荐:
- 移动端页面开发适配 rem布局原理
- Rem布局的原理解析
postcss
postcss可以理解为CSS的”babel“,可以让我们使用比较新的CSS语法
postcss 不是类似less的CSS预处理器, 而是一种允许用JS插件来转变样式的工具。 postcss提供了一个解析器,它能够将CSS解析成抽象语法树(AST)。
postcss的常用插件
- autoprefixer: autoprefixer插件会给根据CanIUse的兼容性去检查你的CSS代码,然后自动为你的CSS代码加上浏览器厂商的私有前缀
- precss
- postcss-cssnext
- PostCSS 是个什么鬼东西?
css modules
作用:
- 避免css相互覆盖的方法,CSS Modules 加入了局部作用域和模块依赖
实现原理:
- CSS的规则是全局的,任何一个组件的样式规则,对整个页面有效;
- 产生局部作用域的唯一方法,就是使用一个独一无二的class名字,不会与其他选择器重名,这就是CSS Modules的实现原理:将每个类名编译成独一无二的哈希值;
CSS Modules 用法教程
css 预处理器
CSS 预处理器是一个能让你通过预处理器自己独有的语法来生成CSS的程序。
绝大多数CSS预处理器会增加一些原生CSS不具备的特性,例如代码混合,嵌套选择器,继承选择器等
最流行的CSS预处理器:
less
sass
stylus
postcss
CSS 动画
https://juejin.cn/post/6844903615920898056#heading-2
animation(动画)
用于设置动画属性,是一个简写的属性,包含6个属性
transition(过渡)
用于设置元素的样式过度,和animation有着类似的效果,但细节上有很大的不同
transform(变形)
用于元素进行旋转、缩放、移动(translate)或倾斜
translate(移动)
translate只是transform的一个属性值,即移动。
transition 过渡
语法:transition: property duration timing-function delay;
transition-property
设置过渡效果的 CSS 属性的名称
transition-duration
完成过渡效果需要多少秒或毫秒
transition-timing-function
速度效果的速度曲线
transition-delay
定义过渡效果何时开始
.box {
height: 100px;
width: 100px;
background: green;
transition: transform 1s ease-in 1s;
}
.box:hover {
transform: rotate(180deg) scale(.5, .5);
}
transition产生动画的条件是transition设置的property发生变化,这种动画的特点是需要“一个驱动力去触发”,有着以下几个不足:
1.需要事件触发,所以没法在网页加载时自动发生
2.是一次性的,不能重复发生,除非一再触发
3.只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态
4.一条transition规则,只能定义一个属性的变化,不能涉及多个属性。
animation
这个属性是transition属性的扩展,弥补了transition的很多不足,我理解为animation是由多个transition的效果叠加,并且可操作性更强,能够做出复杂酷炫的效果
语法:animation: name duration timing-function delay iteration-count direction play-state fill-mode;
name
用来调用@keyframes定义好的动画,与@keyframes定义的动画名称一致
duration
指定元素播放动画所持续的时间
timing-function
规定速度效果的速度曲线,是针对每一个小动画所在时间范围的变换速率
delay
定义在浏览器开始执行动画之前等待的时间,值整个animation执行之前等待的时间
iteration-count
定义动画的播放次数,可选具体次数或者无限(infinite)
direction
设置动画播放方向:normal(按时间轴顺序),reverse(时间轴反方向运行),alternate(轮流,即来回往复进行),alternate-reverse(动画先反运行再正方向运行,并持续交替运行)
play-state
控制元素动画的播放状态,通过此来控制动画的暂停和继续,两个值:running(继续),paused(暂停)
fill-mode
控制动画结束后,元素的样式,有四个值:none(回到动画没开始时的状态),forwards(动画结束后动画停留在结束状态),backwords(动画回到第一帧的状态),both(根据animation-direction轮流应用forwards和backwards规则),注意与iteration-count不要冲突(动画执行无限次)