CSS 知识总结

484 阅读8分钟

CSS入门

先来看一组快问快答:

CSS是什么?

Cascading Style Sheets,即层叠样式表。功能如其名,既能给HTML文档添加样式,又带有可层叠的特性。

层叠指什么?

样式层叠、选择器层叠、文件层叠等,这些特性使得CSS书写非常灵活

CSS是谁发明的?

万维网的Lee爵士的挪威同事Lie先生首先提出的CSS

哪个CSS版本最主流或流行?

CSS 1和CSS 2是比较老的版本不提,CSS 2.1是目前使用最广泛兼容性最好的版本,CSS 3开始分模块进行升级,还在逐步扩展浏览器的兼容性。

CSS的版本详情

CSS版本时间重要性
CSS 11996年过时
CSS 21998年过时
CSS 2.12004~2011年使用最广泛的版本(IE支持)
CSS 31999年开始起草现代版本,分模块升级(IE 8部分支持)
CSS 4 ?未来版本分模块升级

查看浏览器的CSS特性支持性

各个浏览器兼容性非常繁琐复杂,建议使用caniuse.com网站,全网数据一网打尽

CSS的语法

掌握两大类即可

样式语法

选择器 {
属性名: 属性值;
}

注意区分大小写!!

@语法

@charset "UTF-8";
@import url(.css);
@media (min-width: 100px) and (max-width: 150px)

注意事项

  • charset字符编码设置必须在第一行
  • 没有{}就必须以;结尾
  • media媒体查询是非常关键的功能,做自适应或自响应页面

CSS的调试方法

跟JS中的经典log调试法类似,CSS也有其灵魂调试法,border调试法

遇事不决,给元素添加border

注意border有时候会影响尺寸,导致父元素容纳子元素的空间出现问题。

Tips: 这时候可用outline法代替border,outline不占用文档空间

CSS重要概念

Normal Flow

国内翻译文档流,其实直译应该是正常流或常规流,就是HTML文档的一个正常排布流动的方向。

页面的左上角作为起点,横向排布流是从左到右,纵向排布流是自上而下。

block, inline, inline-block元素

  • block元素自上而下,每一个另起一行
  • inline元素从左到右,到达一行末端会换行
  • inline-box元素也从左到右

盒模型

CSS 盒模型有两种,一种是默认的content-box模型,一种是border-box模型。两者的主要区别就在,context-box你规定的元素宽度只有content宽度,不包括padding,border。而border-box模型下,你定义的元素宽度会包括content,padding,border的总和。如果定义了padding,border宽度,content宽度会自动减法计算得到。

border-box模型非常符合人类思维,普适于平时工作场景,推荐优先使用。

脱离Normal Flow

对元素使用以下CSS样式:

  • float
  • position: absolute / fixed 等

CSS大坑

说了CSS那么多特性和优点,实际工作中会发现CSS也有缺点,有很多奇葩的大坑。

最经典的,margin合并问题

在较新的主流内核的浏览器上,如chrome和firefox,CSS会出现block元素的垂直方向margin合并,也称为margin塌缩现象。父与首尾两个子元素或者相邻同级子元素在垂直方向的margin如果同时存在,他们两个的margi会取其中最大的值。

而在比较老的浏览器比如ie8上,这个margin合并功能就不会实现。这就会出现,所谓的双倍margin问题。因为我们通常CSS编程,是根据目前最通用的chrome内核浏览器编写的;而在ie内核下,将相邻子元素赋予垂直方向margin会导致不自动合并而是呈现双倍效果。虽然有办法解决,但这是CSS一个令人头疼的典型问题。

CSS3的重要新功能——动画

CSS3提供了很强的动画功能,主要分为两种方法,transition以及animation。通过这两种动画功能,进行包装和配合,就能实现一些很酷眩的动画效果,摆脱以往需要复杂Js脚本实现的繁琐操作。在继续探讨这两种动画功能之前,需要先稍微了解一些前置的知识点,如浏览器是如何渲染html页面的。

浏览器渲染原理

关于浏览器的渲染原理,其实各家浏览器会有各自的做法和微妙的区别。由于最主流的浏览器都是在用chrome内核,所以我们优先探讨一下chrome浏览器的渲染机制。关于chrome渲染,最权威的说明还是谷歌官方提供的文档。文档很长,很专业,涉及专业术语很多难啃,就在这里简单总结一下。

浏览器渲染大概步骤

  1. 根据HTML构建HTML树,也就是DOM树
  2. 根据CSS构建CSS树(CSSOM)
  3. 将两颗树合并成一颗渲染树(render tree)
  4. Layout布局(包括文档流,盒模型,计算大小和位置)
  5. Paint绘制(把边框颜色、文字颜色、阴影等绘出)
  6. Compose合成(根据层叠关系展示画面)

如何更新样式

通常使用JS脚本来更新样式

  • 比如改背景 div.style.background = 'color'
  • 比如改元素显示/隐藏 div.style.display = 'none'
  • 更改元素的样式更常用改类名的方法 div.classList.add('blue')
  • 移除节点 div.remove()

这些不同的脚本和方法,会产生不同的页面样式更新方式,这跟浏览器的种类版本也有关系。涉及浏览器的渲染过程。

三种更新方式

  1. JS -> style -> layout -> paint -> composite
  2. JS -> style -> paint -> composite
  3. JS -> style -> composite

第一种方式是全走一遍,比如div.remote会让元素消失,其他元素发生重新布局relayout。

第二种方式会跳过layout步骤,因为不涉及元素的重排,比如改元素背景色。

第三种方式会跳过layout和paint步骤,直接进行composite步骤。比如,非常重要的改变元素外观效果的一个功能,transform。

优化CSS的动画效果,就需要研究浏览器渲染过程,就需要优化不同属性下触发的流程,触发的CSS更新流程越简单,响应越快,用户体验越好。

注意不同的属性会触发不同的渲染过程,这就需要使用不同浏览器调试功能来试验。

好在有CSS Triggers这个网站,已经总结了绝大多数常用的CSS属性触发,在不同浏览器上的表现。

transform方法简介

四个常用功能:

  • 位移 translate
  • 缩放 scale
  • 旋转 rotate
  • 倾斜 skew

使用transform变换页面元素的外观,一般都需要配合transition来过渡。

特别需要注意一点,inline元素不支持transform,需要先display: block;

这些方法的具体语句写法,在MDN里都有详细的描述,最快掌握语句的方法就是去查看MDN的语法示例。

例子:translate(-50%, -50%)经常用于绝对定位元素的居中

注意scale 语句用的很少,因为很可能会导致元素模糊的现象发生,视觉效果灾难性的,用户体验极差。

transition方法简介

他的作用,本质上来说就是自动补全动画中间帧。

语法其实很简单:

transition:属性名 时长 过渡方式 延迟;

以及一些小技巧:

  • 可以用逗号分隔两个不同属性名
  • 可以用all来代表所有属性
  • 过渡方式是用函数表示,具体有很多数学知识不方便展开。常用的ease,linear,steps掌握后自行摸索吧

以及还要注意几点:

  • 不是所有属性都有动画效果过渡,比如display: none到block无过渡
  • transition过渡必须有始有终,可以执行一次动画或正反向各执行一次

最经典的用法是hover和非hover状态的过渡

animation方法简介

除了两个节点有始有终以外,如果你还想实现更复杂的动画效果,就不能只用简单的transition过渡了。如果硬要用transition方法去实现多个中间转折点,那就需要借助JS语句来配合实现。这一过程会非常繁琐。

想做复杂动画效果,添加更多的中间帧,关键帧,最好用到animation方法。

animation方法的使用也非常简单,两个步骤:

  1. 声明关键帧
  2. 添加动画

animation缩写语法:

animation:时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充模式 | 是否暂停 | 动画名称;

  • 次数可以是具体数值,或者infinite
  • 方向有 reverse / alternate / alternate-reverse
  • 填充模式 none / forwards / backwards / both
  • 是否暂停属性来控制播放状态 paused / running

申请关键帧 @keyframes

@keyframes name {
  from {
  }
  to {
  }
}

或者

@keyframes name {
  0, 100% {
  }
  50% {
  }
}

个人体会,animation的使用相对于transition会复杂一些,代码维护工作会更繁琐一些,如果能使用transition实现的基础动画效果,那就尽量用transition实现。