基础
样式优先原则
优先顺序
- 在属性后面使用 !important 会覆盖页面任意位置定义的元素样式
- 作为 style 属性写在元素内的样式(行内样式)
- id 选择器
- 类选择器 | 伪类选择器 | 属性选择器(后面样式覆盖前面样式)
- 标签选择器
- 通配符选择器
- 继承的样式
- 浏览器自定义样式(user agent stylesheet)
注意:优先级计算主要针对以上3-6的选择器,当优先级无法确定顺序时,后来者会覆盖之前的样式,注意,例如一个标签上有多个class,此时的先后顺序是指在css样式中出现的先后顺序,并不是在class属性中的先后顺序
优先级计算
首先有 A、B、C、D 四个值:
- 如果本样式是内联样式,那么 A = 1,否则 A = 0,例如
样式1:
h1 { color: red; }
样式2:
<h1 style="color: blue;">hello world</h1>
样式1不是内联样式,而样式2是内联样式,所以样式1的 A 值为 0,样式2 的 A 值为 1;
- B 的值等于 ID 选择器 出现的次数,例如
样式1:
#list #item { color: red; }
样式2:
#list {color: blue;}
样式1的 B 值为 2,样式 2 B 值为 1
- C 的值等于 类选择器 和 属性选择器 和 伪类 出现的总次数
- D 的值等于 标签选择器 和 伪元素 出现的总次数 。
这样就计算出了 A、B、C、D 四个值,然后将四个值组成一个四位的数字,就得到了这个样式的权重
案例
<!DOCTYPE html>
<html>
<head>
<style>
#parent .children {
color: red
}
.parent p {
color: blue;
}
.parent p.children {
color: yellow;
}
</style>
</head>
<body>
<div id="parent" class="parent">
<p class="children">
hello world
</p>
</div>
</body>
</html>
根据以上优先级的计算方式,对于同一个样式而言(此处指color),三个样式的得分分别为:0110、0011、0021,所以最终第一个样式胜利,文字颜色为红色;但是如果添加这个样式:
<p style="color:black" class="children">
hello world
</p>
这个内联样式的得分为:1000,所以它胜利,颜色为黑色
选择器
- id选择器(#myId)
- 类选择器(.myclassname)
- 标签选择器(div,h1)
- 相邻选择器(h1+p)
- 子选择器(ul > li)
- 后代选择器(li a)
- 通配符选择器(*)
- 属性选择器(a[rel="external"])
- 伪类选择器(a:hover,li:nth-child)
盒子模型
- box-sizing: content-box。标准盒子,默认值,设置元素的height/width属性指的是content部分的高/宽
- box-sizing: border-box。IE 盒子,设置元素的height/width属性指的是border+padding+content部分的高/宽
position定位
- static:默认位置。不需要特别声明,不常用。
- relative:不脱离文档流,参考默认位置通过top,bottom,left,right定位
- absolute:绝对定位,参考距其最近一个不为static的父级元素通过top, bottom, left, right定位
- fixed:固定定位,相对于整个浏览器窗口进行定位,无论页面怎么滚动
- sticky:黏性定位,屏幕范围内该元素位置不受影响,超出范围后,会变成 fixed,根据设置的left/top等属性成固定的效果
层叠上下文
从是否定位角度划分元素
- 定位元素,position 的值为 relative,absolute,fixed或sticky的元素
- 未定位元素,不是定位元素的都是未定位元素
浏览器元素渲染规则
- 浏览器渲染定位元素和非定位元素的时候,遵循以下规则
- 对于未定位元素,按照在元素在 HTML 文档中出现的顺序决定,越后面的元素越会覆盖在上面
- 先渲染未定位元素,再渲染定位元素
z-index的渲染规则
- z-index只对定位元素起作用,对非定位元素无效
- 当一个元素被显示设置z-index值,不管是正数、负数还是 0,所有这个元素和它的所有后代元素形成一个层叠上下文
- 层叠上下文的后代元素只参与和根元素的对比,不参与和根元素以外的元素对比,当根元素和子元素对比时,根元素被的 z-index 值被视为 0
总结-独立的层叠上下文中元素排列顺序
由下到上的层叠顺序(特别注意z-index为负数和未定位元素的先后顺序):
- 层叠上下文的根元素
- z-index为负值的已定位元素(包括它们的子元素)
- 未定位元素
- z-index为auto的已定位元素(包括它们的子元素)
- z-index为正值的已定位元素(包括它们的子元素)
样式继承
可继承的样式
- font-size
- font-family
- color
- text-align
不可继承的样式
- border
- padding
- margin
- width
- height
- display
设置元素隐藏的方法
- display: none:彻底消失,会导致浏览器回流和重绘,不能再触发点击事件
- visibility: hidden:元素隐藏,空间仍保留,会导致重绘,但是不能再触发点击事件
- opacity: 0:设置为透明,相当于它还在那里,但是你看不到,可以触发点击事件
居中布局
水平居中
- 行内元素: text-align:center(详细内容参照下文样式验证中的text-align部分)
- 块级元素: margin:0 auto
- 绝对定位和移动: absolute + transformx
- 绝对定位和负边距: absolute + margin
- flex弹性布局: flex + justify-content:center
垂直居中
- 子元素为单行文本: line-height:height
- 当不需要指定元素的高度时,可以直接给一个相同的padding-top和padding-bottom,让元素和padding一起撑起来容器
- dislpay设置为table显示(适用于需要指定容器高度,或者不能使用padding的时候): display:table-cell + vertical-align: middle
- flex弹性布局:flex + align-items:center,适用于不需要严格的兼容时
- 绝对定位和移动:absolute + transform,适用于不知道元素的高度时
- 利用position定位 + top + margin,适用于知道容器和元素的高度且其他方法不能用时
清除元素浮动的方法
- 使用clear属性的空元素
- 在浮动元素后使用一个空元素,如:<div ></div>
- 在css样式中使用.clear{clear:both;}
- 使用<br >或<hr >
- 使用css的overflow属性,给浮动元素添加overflow:hidden;或overflow:auto;
- 使用css的:after伪元素(注意这不是伪类,而是伪元素,代表一个元素子后最近的元素)
CSS单位
px
- px 是像素(pixel)的缩写,相对长度单位,是网页设计常用的基本基本单位,它是相对于显示器屏幕分辨率而言的。
em
- em 是相对长度单位
- 当用在font-size属性上时,相对的是父元素的font-size,如果当前父元素的字体元素未设置,则相对于浏览器的默认字体尺寸设置
- 当用在其他属性上时,相对的是元素本身的font-size大小
rem
- rem 是相对于 HTML 根元素的字体大小(font-size)来计算的长度单位。如果你没有设置 HTML 字体大小,那么以浏览器默认为主,一般为 16px。
vw/vh
- vw 和 vh 是相对于 viewport(视口)的宽度或者高度而定的。
一般来说:1vw = npx / 100,即浏览器宽度为 200px 的时候,1vw = 200px / 100,即 1vw = 2px。
CSS3 部分新特性
新增样式属性
- word-wrap:对长的不可分割单词换行,例如:
word-wrap:break-word
- text-shadow:文字阴影:
text-shadow: 5px 5px 5px #FF0000;
对应水平阴影,垂直阴影,模糊距离,阴影颜色 - font-face:定义自己的字体
- border-radius:圆角(边框半径),用于创建圆角
- border-image:边框图片:
border-image: url(border.png) 30 30 round
- box-shadow:盒阴影:
box-shadow: 10px 10px 5px #888888
- 媒体查询:定义两套 CSS,当浏览器的尺寸变化时会采用不同的属性
CSS3 新增伪类
- p:first-of-type:选择属于其父元素的首个元素
- p:last-of-type:选择属于其父元素的最后元素
- p:only-of-type:选择属于其父元素唯一的元素
- p:only-child:选择属于其父元素的唯一子元素
- p:nth-child(2):选择属于其父元素的第二个子元素
- :enabled:disabled表单控件的禁用状态
- :checked:单选框或复选框被选中
弹性布局
CSS 样式验证
text-align 的居中特性
- 父盒子设置
text-align: center;
后,盒子里面的文字内容、行内元素、行内块元素
都可以水平居中对齐,而块级元素则不可以,验证示例代码如下
<style type="text/css">
/*清除浏览器默认间距 */
* {
margin: 0;
padding: 0;
}
.text-center{
border:1px solid #24b3a3;
margin: 10px 0;
overflow: hidden;
text-align: center;
}
.d-inline-block {
/*行内块元素*/
display: inline-block;
width: 300px;
height: 100px;
background-color: green;
}
.b-color {
background-color: red;
}
.width-height {
width: 300px;
height: 100px;
background-color: pink;
}
.width-height-margin {
width: 300px;
height: 100px;
background-color: pink;
/*块元素居中*/
margin: 0 auto;
}
</style>
<body>
<!-- 1.文字内容 -->
<!-- 展示效果:居中 -->
<div class="text-center">
文本元素
</div>
<!-- 2.行内元素 -->
<!-- 展示效果:居中 -->
<div class="text-center">
<span>行内元素</span>
</div>
<!-- 3.行内块元素 -->
<!-- 3.1.行内块元素-图片 -->
<!-- 展示效果:居中 -->
<div class="text-center">
<img src="https://www.most-all.com/upload/2021/01/WechatIMG1-6b3f928200074980ae6ad1a568cb091d.png" />
</div>
<!-- 3.2.行内块元素-行内块 -->
<!-- 展示效果:居中 -->
<div class="text-center">
<span class="d-inline-block">被转成行内块元素的行内元素</span>
</div>
<!-- 4.块元素,没有设置宽高,可以水平居中,因为没有设置宽高,会继承父盒子的宽高;就这个示例来说,实际上就成了1的情况-->
<!-- 展示效果:居中,因为text-align的继承特性,实质上与1的效果相同 -->
<div class="text-center">
<div class="b-color">块元素,未设置宽高 + 父盒子设置text-align: center;</div>
</div>
<!-- 5.块元素的其他情形 -->
<!-- 5.1.块元素,设置了宽高+未设置margin:0 auto;的块级元素无法水平居中-->
<!-- 展示效果:居左 -->
<div class="text-center">
<div class="width-height">块元素,设置了宽高 + 未设置margin:0 auto;</div>
</div>
<!-- 5.2.块元素,设置了宽高+设置margin:0 auto;的块级元素可以水平居中-->
<!-- 以下示例中实际上使块居中的是margin属性,与text-align无关,此时的text-align实际只控制了div内部的文本的居中显示 -->
<!-- 展示效果:居中 -->
<div class="text-center">
<div class="width-height-margin">块元素,设置了宽高 + 设置margin:0 auto;</div>
</div>
</body>
移动端CSS
特殊的标签说明
<meta name="viewport" content="width=device-width, initial-scale=1">
这个标签用来控制 viewport。浏览器的 viewport 是指用户可以看到的 Web 内容的窗口区域
当页面在移动设备上显示时,窗口通常比屏幕要宽;如果直接显示的话,页面一定会乱掉,所以移动端浏览器会有相应的机制来防止这种情况发生。默认情况下,浏览器会采用虚拟视口来渲染页面,例如移动设备的宽度为 640px,则可能会用 980px 的虚拟视口渲染页面,然后缩小页面以适应 640px 的窗口大小
但是这种方案的体验并不好,由于页面被缩小所以页面看起来会不够清楚,用户需要用手势放大页面再移动来仔细查看页面;而且由于虚拟窗口用于都是固定大小(例如 980px),所以媒体查询不会起作用。这种方案通常只被用来渲染未针对窄屏幕做过优化的页面
其中 width=device-width 是指用来渲染页面的视口的宽度与移动设备屏幕的宽度保持一致,这样就不会出现浏览器永远都用 980px 的视口渲染页面的情况。
initial-scale=1 是指初始页面不放大也不缩小。所以,对于响应式页面来说,这个标签是不可缺少的
物理像素,逻辑像素和像素密度
以 iPhone XS 为例,当编写 CSS 代码时,针对于单位 px,其宽度为 414px & 896px,也就是说当赋予一个 div 414px,这个 div 就会填满手机的宽度
而有一把尺子来实际测量这部手机的物理像素,实际为 1242*2688 物理像素;经过计算可知,1242/414=3,也就是说,在单边上,一个逻辑像素=3个物理像素,我们就说这个屏幕的像素密度为 3,也就是常说的 3 倍屏
对于图片来说,为了保证其不失真,1 个图片像素至少要对应一个物理像素,假如原始图片是 500300 像素,那么在 3 倍屏上就要放一个 1500900 像素的图片才能保证 1 个物理像素至少对应一个图片像素,才能不失真
另外一个简单粗暴的适配方案,就是针对所有屏幕,都只提供最高清图片。虽然低密度屏幕用不到那么多图片像素,而且会因为下载多余的像素造成带宽浪费和下载延迟,但从结果上说能保证图片在所有屏幕上都不会失真
还可以使用 CSS 媒体查询来判断不同的像素密度,从而选择不同的图片
my-image { background: (low.png); }
@media only screen and (min-device-pixel-ratio: 1.5) {
#my-image { background: (high.png); }
}
移动端适配
移动端适配主要有两个维度:
-
适配不同像素密度。这一部分比较简单,针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真
-
适配不同屏幕大小。由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用 px 作为开发单位,会使得开发的页面在某一款手机上可以准确显示,但是在另一款手机上就会失真。为了适配不同屏幕的大小,应按照比例来还原设计稿的内容,为了能让页面的尺寸自适应,可以使用 rem,em,vw,vh 等相对单位
CSS 样式备忘
文字超出显示省略号
- 单行文本
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
- 多行文本
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
/* -webkit-line-clamp:把块容器中的内容限制为指定的行数 */
/* 它只有在display属性设置成-webkit-box或者-webkit-inline-box并且-webkit-box-orient(en-US)属性设置成vertical时才有效果 */
宽高等比自适应容器
- 通过vw视口单位实现(兼容性较差)
所谓视口单位(viewport units)是相对于视口(viewport)的尺寸而言,100vw等于视口宽度的100%,即1vw等于视口宽度的1%
<div class="box">
<img src="http://images.pingan8787.com/2019_07_12guild_page.png" />
</div>
// css
*{
margin:0;
padding:0
}
.box{
width:100%;
height:51.5vw
}
.box img{
width:100%;
}
// .box高度为51.5vw是因为图片原来的尺寸是884 * 455的宽高比例,即 455/884 = 51.5%。
// 这个方法无论图片是否加载成功,容器高度始终是计算完成,不会造成页面抖动,也不会造成页面重绘,从而提升性能
- 通过子元素padding实现(推荐)
通过设置子元素的padding属性来实现,是比较常用,也是效果比较好的一种,这里需要理解的是:子元素的padding属性百分比的值是相对父容器的宽度而言
<div class="box">
<div class="text">
<img src="http://images.pingan8787.com/2019_07_12guild_page.png" />
</div>
</div>
// css
.box{
width: 100%;
}
.text{
overflow: hidden;
height: 0; /* 高度设置为0,是避免增加额外的高度,同时由于高度为0,该元素的子元素会overflow溢出到padding所在的区域*/
padding-bottom: 51.5%;
}
.box .text img{
width: 100%;
}
扩展
link 和 @import 区别
CSS 的引入方式
- 内联:style 属性(style="color: red")
- 内嵌:style 标签()
- 外链:link 标签(
- 导入:@import(@import url('index.css') 或者 @import 'index.css')
link 和 @import 区别
- link 是 XHTML 标签,除了加载 CSS 外,还可以定义 RSS 等其他事务;@import 属于 CSS 范畴,只能加载 CSS。
- link 引用 CSS 时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载。
- link 是 XHTML 标签,无兼容问题;@import 是在 CSS2.1 提出的,低版本的浏览器不支持。
- link 支持使用 Javascript 控制 DOM 去改变样式;而 @import 不支持。
png,jpg,gif,webp
- png:便携式网络图片,一种无损数据压缩位图文件格式,优点是压缩比高,色彩好,大多数地方可用
- jpg:一种针对相片使用的失真压缩方法,在网络上被用来存储和传输照片的格式
- gif:一种位图文件格式,以8位色重现真色彩的图像,可以实现动画效果
- webp:压缩率位jpg的2/3,大小比png小45%,压缩时间久,兼容性不好
::before和::after中双冒号和单冒号的区别
- 通常情况下,:表示伪类,::表示伪元素(文档中不存在的元素),而对于before和after而言,:before/:after是Css2的写法::before/::after是Css3的写法
- :before/:after的兼容性要比::before/::after好,不过在H5开发中建议使用::before/::after比较好
- 这些伪元素 要配合content属性一起使用
- 这些伪元素不会出现在DOM中,所以不能通过js来操作,仅仅是在 CSS 渲染层加入
- 这些伪元素的特效通常要使用:hover伪类样式来激活
行内元素和块元素
行内元素
- 常用行内元素
- <a>, <span>, <b>, <em>, <i>, <cite>, <mark>, <code>
- 行内元素特性
- inline元素中只能包含内容或其他inline元素
- 默认情况下,多个inline元素之间不会换行
- 忽略margin-top,margin-bottom和padding-top,padding-bottom属性,margin-left,margin-right及padding-left,padding-right属性有效
- 忽略height与width属性
- 设置为inline-block时,inline元素将拥有block部分属性,如margin的所有属性均有效(同时还能避免margin的折叠),height与width也有效
- inline元素若设置float为left或right,则拥有所有block元素的特征
块元素
- 常用块元素
- <p>, <div>, <form>, <header>, <nav>, <ul>, <li>, <h1>
- 块元素特性
- block元素中可以包含block元素、inline元素等所有元素
- 默认情况下,block元素前后会另起一行(假设子元素没有设置float及position属性)
- margin和padding所有属性均有效
- block元素在未设置width属性时,默认占据父元素100%的width
- block元素在未设置height属性时,默认高度根据子元素自适应(假设子元素没有设置float及position属性)
行内块元素
- 常见行内块元素
- <img>、<input>、<td>
- 行内块元素特性
- 既具有块元素特性也具有行内元素的特性,可以设置其宽度和高度,默认大小由行内块元素的内容而定,不会占据整行。行内块元素只能容纳文本或则其他行内元素。(a标签除外,a标签内可以放块元素)
替换元素
替换元素的实际类型或者实际内容与元素属性有关,如img的实际内容由其"src"属性指定的图像替换,input的实际类型由其"type"属性决定
替换元素表现类似inline-block类型元素,其特性见行内块元素特性
<img>, <object>, <button>, <textarea>, <input>, <select>
CSS中的BFC模式
定义
BFC(Block Formatting Context)格式化上下文,是指页面上一个隔离的独立容器,容器内部的子元素不会影响到外面的元素,反之外面的元素也不会影响容器里面的元素
BFC 布局特性
- 在 BFC 中,盒子从顶端开始垂直地一个接一个地排列
- 盒子垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻盒子的 margin 会发生重叠
普通文档流布局规则
- 浮动的元素不会被父级计算高度
- 非浮动元素会覆盖浮动元素的位置
- margin会传递给父级元素
- 相邻元素的上下的margin会重叠
以下代码产生的页面中,它们的边距是 200px,需要通过 BFC 解决边距问题
<div style="width:100px; height:100px; margin-bottom:100px;"></div>
<div style="width:100px; height:100px; margin-top:200px;"></div>
BFC的布局规则
- 浮动元素会被父级计算高度(父级元素触发了 BFC)
- 非浮动元素不会覆盖浮动元素的位置(非浮动元素触发了 BFC)
- margin不会传递给父级(父级触发 BFC)
- 属于同一个BFC的两个相邻元素上下margin会重叠
BFC在开发中的应用
- 清除元素内部浮动,内部的Box会在垂直方向上一个接一个的放置
- 解决外边距合并问题,阻止margin重叠
- 阻止元素被浮动元素覆盖(BFC 的区域不会与float的元素区域重叠)
形成BFC的条件
- float: left/right
- position: absolute/fixed
- display: inline-block/table-cell/table-caption/flex/grid
- overflow: hidden/auto/scroll
脱离文档流
文档流
将窗体自上而下分成一行一行,并在每行中按从左至右一次排放元素,成为文档流
脱离文档流
脱离文档流的元素,将不再在文档流占据空间,而是漂浮在文档流上方
- float: left/right:元素会脱离并且具有block或者table的特性,即可以设置宽高,但是其他盒子会环绕该元素的周围
- position: absolute/fixed:absolute 为绝对定位,脱离文档流之后还是会相对于该元素的父类(做了 relative/absolute 定位的父类)进行偏移。而 fixed 就是完全脱离文档流,相对于 HTML (整个浏览器窗口)的形式展示
高度塌陷
当父元素没有设置高度时,其高度由子元素撑开,此时如果子元素脱离了文档流,则父元素的高度将发生塌陷,页面可能发生混乱
高度塌陷坚决方案
- 开启bfc模式(参考前文内容)
- 在父元素里的最末尾的位置添加一个div,然后对这个div设置清除浮动
clear:both;
,就解决了父元素高度塌陷。这个方法基本没有副作用(w3c推荐,全浏览器兼容) - 使用css中的after伪类,通过after伪类向父元素的末尾添加一个空白的块元素,然后对其清除浮动,使用它来解决父元素高度塌陷。和直接添加div原理一样,但不会添加多余的结构,非常推荐使用
/*以后这个clearfix类可以添加到任何高度塌陷的元素中解决问题*/
.clearfix:after{
/*添加一个空元素*/
content:"";
/*使其变为块元素*/
display:block;
/*清除两侧浮动*/
clear:both;
}
/*更加优秀的版本(即考虑了高度塌陷又考虑了父子元素垂直外边距重叠问题)*/
.clearfix:before,.clearfix:after{
/*添加一个空元素*/
content:"";
/*使其变为块元素*/
display:table;
/*清除两侧浮动*/
clear:both;
}
/*兼容ie6的额外样式*/
.clearfix{
zoom:1;
}
如何解决 a 标点击后 hover 事件失效的问题
- 改变 a 标签 CSS 属性的排列顺序
在 CSS 中,如果对于相同元素针对不同条件的定义,适宜将最一般的条件放在最上面,依次向下,保证最下面的是最特殊的条件(可以理解为样式覆盖),因此针对上述问题,应当使用如下的顺序进行样式边下:
link -> visited -> hover -> active
- a:link:简写 a,未访问的样式
- a:visited:已经访问的样式
- a:hover:鼠标移上去时的样式
- a:active:鼠标按下的样式