CSS 回忆录

本文深入探讨了CSS的基础知识,包括语法、选择器、注释、@规则、优先级、继承性、文档流、盒模型、视觉格式化模型等核心概念。详细阐述了BFC、IFC的创建条件和渲染规则,以及CSS优化和提高性能的方法,如减少HTTP请求、利用缓存、优化选择器等。此外,还讨论了CSS在页面布局和响应式设计中的重要角色。
摘要由CSDN通过智能技术生成

前言

本文章将围绕CSS的基础知识进行回忆,加深巩固CSS的知识点

内容

语法

定义

层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种 样式表 语言,用来描述 HTML 或 XML(包括如 SVG、MathML、XHTML 之类的 XML 分支语言)文档的呈现。CSS 描述了在屏幕、纸质、音频等其它媒体上的元素应该如何被渲染的问题.

注释

/* 单行注释 */
/*
* 多行注释
*/

@规则

  • @namespace 是用来定义使用在CSS样式表中的XML命名空间的@规则。定义的命名空间可以把通配、元素和属性选择器限制在指定命名空间里的元素。
  • @media, 可用于基于一个或多个 媒体查询 的结果来应用样式表的一部分。使用它,您可以指定一个媒体查询和一个CSS块,当且仅当该媒体查询与正在使用其内容的设备匹配时,该CSS块才能应用于该文档
  • @page, 描述打印文档时布局的变化.
  • @font-face, 指定一个用于显示文本的自定义字体。
  • @keyframes, 描述 CSS 动画。
  • @document, 根据文档的 URL 限制其中包含的样式规则的作用范围
  • @import 用于告诉 CSS 引擎引入一个外部样式表

选择器

基础选择器

标签选择器 a
类选择器 .a1
id选择器 #a1
通配选择器 *

属性选择器

[href]:指定属性的元素;
[href=val]:属性等于指定值的元素;
[href*=val]:属性包含指定值的元素;
[href^=val] :属性以指定值开头的元素;
[href$=val]:属性以指定值结尾的元素;
[href~=val]:属性包含指定值(完整单词)的元素(不推荐使用);
[href|=val]:属性以指定值(完整单词)开头的元素(不推荐使用);

组合选择器

相邻兄弟选择器:div + div
普通兄弟选择器:div ~ div
子选择器:div > p
后代选择器:div p

伪类
条件伪类

:lang():基于元素语言来匹配页面元素;
:dir():匹配特定文字书写方向的元素;
:has():匹配包含指定元素的元素;
:is():匹配指定选择器列表里的元素;
:not():用来匹配不符合一组选择器的元素;

行为伪类

:active:鼠标激活的元素;
:hover: 鼠标悬浮的元素;
::selection:鼠标选中的元素;

状态伪类

:target:当前锚点的元素;
:link:未访问的链接元素;
:visited:已访问的链接元素;
:focus:输入聚焦的表单元素;
:required:输入必填的表单元素;
:valid:输入合法的表单元素;
:invalid:输入非法的表单元素;
:in-range:输入范围以内的表单元素;
:out-of-range:输入范围以外的表单元素;
:checked:选项选中的表单元素;
:optional:选项可选的表单元素;
:enabled:事件启用的表单元素;
:disabled:事件禁用的表单元素;
:read-only:只读的表单元素;
:read-write:可读可写的表单元素;
:blank:输入为空的表单元素;
:current():浏览中的元素;
:past():已浏览的元素;
:future():未浏览的元素;

结构伪类

:root:文档的根元素;
:empty:无子元素的元素;
:first-letter:元素的首字母;
:first-line:元素的首行;
:nth-child(n):元素中指定顺序索引的元素;
:nth-last-child(n):元素中指定逆序索引的元素;;
:first-child :元素中为首的元素;
:last-child :元素中为尾的元素;
:only-child:父元素仅有该元素的元素;
:nth-of-type(n) :标签中指定顺序索引的标签;
:nth-last-of-type(n):标签中指定逆序索引的标签;
:first-of-type :标签中为首的标签;
:last-of-type:标签中为尾标签;
:only-of-type:父元素仅有该标签的标签;

伪元素

::before:在元素前插入内容;
::after:在元素后插入内容;

优先级

为了方便记忆,可以将权重分成几个等级,数值越大权重越高:

  • 10000: !important;
  • 01000:内联样式;
  • 00100:ID选择器;
  • 00010:类选择器、伪类选择器、属性选择器;
  • 00001:元素选择器、伪元素选择器;
  • 00000:通配选择器、后代选择器、兄弟选择器

使用!important的注意事项:

  • 优先考虑使用样式规则的优先级解决问题而不是使用!important;
  • 只有在需要覆盖全站或者外部CSS的特定页面中使用!important;
  • 永远不要在你的插件中使用!important
  • 永远不要在全站的范围的CSS代码中使用!important;

继承性

在CSS中有一个很重要的特性就是子元素会继承父元素对应到计算属性后的值。
CSS属性有很多,但并不是所有属性默认都能继承父元素对应的属性,能默认继承的属性一定是那些不会影响到页面布局的属性。可以分成如下几类:

  1. 字体类:font-family、font-style、font-size、font-weight等。
  2. 文本类:text-align、text-indent(规定文本块中首行文本的缩进)、text-decoration(规定添加到文本的修饰)、text-shaow(向文本设置阴影)、letter-spacing(增加或减少字符间的空白(字符间距))、word-spacing(增加或减少单词间的空白(即字间隔))、white-space、line-hight、color等
  3. 列表相关类:list-style、list-style-image、list-style-type、list-style-position等
  4. 其他:visibility,cursor等

对于其他默认不继承的属性也可以通过以下几个属性值来控制继承行为:

inherit:继承父元素对应属性的计算值;
initial:应用该属性的默认值,比如 color 的默认值是 #000;
unset:如果属性是默认可以继承的,则取 inherit 的效果,否则同 initial;
revert:效果等同于 unset,兼容性差。

文档流

文档流中,内联元素默认从左到右流,遇到阻碍或者宽度不够自动换行,继续按照从左到右的方式布局。块级元素单独占据一行,并按照从上到下的方式布局。

脱离文档流的方法:

  1. float:left;
  2. position: absolute;
  3. position:fixed;

盒模型

在 CSS 中任何元素都可以看成是一个盒子,而一个盒子是由 4 部分组成的:内容(content)、内边距(padding)、边框(border)和外边距(margin)。
盒模型分为2种:标准盒模型IE盒模型。分别由W3C和IExplore制定的标准。

标准盒模型:内容(设置的高/宽)+ 内边距 + 边框
IE盒模型:内容(包含了宽/高 + 内边距 + 边框)

在CSS3中新增了一个属性box-sizing,可以通过设置不同的值来制定盒子以什么标准使用:

  • content-box:标准盒模型;
  • border-box:IE盒模型;

视觉格式化模型

视觉格式化模型(Visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。CSS 中一切皆盒子,而视觉格式化模型简单来理解就是规定这些盒子应该怎么样放置到页面中去,这个模型在计算的时候会依赖到很多的因素,比如:盒子尺寸、盒子类型、定位方案(是浮动还是定位)、兄弟元素或者子元素以及一些别的因素。

盒子类型是有display决定的,同时给一个元素设置display后,将会有盒子区分成俩种显示类型

  • outer display type:决定了该元素本身如何布局的
    1 block
    2 inline
    3 inline-block
  • inner display type:其实就相当于把该元素当成了容器,规定了其内部子元素是如何布局的
    1 block container:建立 BFC 或者 IFC;
    2 flex container:建立 FFC;
    3 grid container:建立 GFC;
    4 ruby container:接触不多,不做介绍。
    值得一提的是如果把 img 这种替换元素(replaced element)申明为 block 是不会产生 container box 的,因为替换元素比如 img 设计的初衷就仅仅是通过 src 把内容替换成图片,完全没考虑过会把它当成容器。

格式化上下文

格式化上下文(Formatting Context)是 CSS2.1 规范中的一个概念,大概说的是页面中的一块渲染区域,规定了渲染区域内部的子元素是如何排版以及相互作用的。
不同类型的盒子有不同格式化上下文,大概有这 4 类:

BFC (Block Formatting Context) 块级格式化上下文;
IFC (Inline Formatting Context) 行内格式化上下文;
FFC (Flex Formatting Context) 弹性格式化上下文;
GFC (Grid Formatting Context) 格栅格式化上下文;

BFC

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

如何创建 BFC?
  • 根元素(html)
  • 浮动元素(元素的 float 不是 none)
  • 绝对定位元素(元素的 position 为 absolute 或 fixed)
  • 行内块元素(元素的 display 为 inline-block)
  • 表格单元格(元素的 display 为 table-cell,HTML表格单元格默认为该值)
  • 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  • 匿名表格单元格元素(元素的 display 为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot 的默认属性)或 inline-table)
  • overflow 计算值(Computed)不为 visible 的块元素
  • display 值为 flow-root 的元素
  • contain 值为 layout、content 或 paint 的元素
  • 弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)
  • 网格元素(display 为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width (en-US) 不为 auto,包括 column-count 为 1)
  • column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更Chrome bug)。

参考:MDN - 块格式化上下文

BFC 渲染规则
  • 内部的Box会在垂直方向上一个接一个的放置
  • 内部的Box垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生折叠,不同BFC不会发生折叠。)
  • 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
  • BFC的区域不会与float的元素区域重叠
  • 计算BFC的高度时,浮动子元素也参与计算
IFC

Inline Formatting Contexts,也就是“内联格式化上下文”。

如何创建IFC?

块级元素中仅包含内联级别元素
形成条件非常简单,需要注意的是当IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个IFC,这里不做过多介绍。

IFC布局规则
  • 子元素水平方向横向排列,并且垂直方向起点为元素顶部。
  • 子元素只会计算横向样式空间,【padding、border、margin】,垂直方向样式空间不会被计算,【padding、border、margin】。
  • 在垂直方向上,子元素会以不同形式来对齐(vertical-align)
  • 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和与其中的浮动来决定。
  • IFC中的“line box”一般左右边贴紧其包含块,但float元素会优先排列。
  • IFC中的“line box”高度由 CSS 行高计算规则来确定,同个IFC下的多个line box高度可能会不同。
  • 当 inline-level boxes的总宽度少于包含它们的line box时,其水平渲染规则由 text-align 属性值来决定。
  • 当一个内联盒子超过父元素的宽度时,它会被分割成多盒子,这些盒子分布在多个 line box 中。如果子元素未设置强制换行的情况下,inline box 将不可被分割,将会溢出父元素。
IFC 应用场景

水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过 text-align 则可以使其水平居中。
垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align: middle,其他行内元素则可以在此父元素下垂直居中。

查看更多,请看这篇传送门

常见的面试题

1 你对BFC规范的理解?

涉及的知识点(层层递进)::
1 什么是BFC
2 BFC的形式条件
3 BFC的特性

定义: 块级格式化上下文。是CSS中的一个渲染机制,BFC就相当于一个盒子,内部的元素与外界的元素互不干扰。它不会影响外部的布局,外部的布局也不会影响到它。

常见的形成条件(任意一条):
- 根元素:html
- float的值不是none
- position 为 absolute 或 fixed
- display的值是inline-block,table-cell,flex,table-caption或者inline-flex
- overflow的值不是visible

特性: 
1 内部的盒子会在垂直方向上一个接一个的放置
2 对于同一个BFC的俩个相邻的盒子的margin会发生重叠,与方向无关。
3 每个元素的左外边距与包含块的左边界相接触(从左到右),即使浮动元素也是如此
4 BFC的区域不会与float的元素区域重叠
5 计算BFC的高度时,浮动子元素也参与计算
6 BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然

2 谈谈你对CSS盒模型的理解?

涉及知识点(层层递进):

1 基本概念:标准模型+ IE模型(区别)
2 CSS如何设置这两种模型

1 基本概念:
在 CSS 中任何元素都可以看成是一个盒子,而一个盒子是由 4 部分组成的:
内容、内边距、边框和外边距。
CSS盒模型分成标准模型和IE模型

2 CSS如何设置这两种模型:
可以通过设置box-sizing,它有 2 个值:
content-box:标准盒模型;
border-box:IE 盒模型;
对于俩个有什么区别,例如一个块级元素的高度是100px, 内边距是20px。在标准盒模型中内容高度是100px,而对于IE盒模型而言,高度是60px。
IE盒子模型的 content 部分包含了 border 和 pading;

3 CSS优化、提高性能的方法有哪些?

涉及知识点(层层递进):
1 加载性能
2 选择器性能
3 渲染性能
4 可维护性、健壮性

加载性能:
1 css压缩: 将写好的css进行打包压缩,可以减少很多的体积;

2 内联首屏关键CSS: 因为在HTML下载完成之后就才能进行渲染, 
所以内联CSS能够使浏览器开始页面渲染的时间提前。
既然内联CSS能够使页面渲染的开始时间提前,那么是否可以内联所有的CSS呢?
答案显然是否定的,这种方式并不适用于内联较大的CSS文件。
因为[初始拥塞窗口](https://tylercipriani.com/blog/2016/09/25/the-14kb-in-the-tcp-initial-window/)
存在限制(TCP相关概念,通常是 14.6kB,压缩后大小),
如果内联CSS后的文件超出了这一限制,
系统就需要在服务器和浏览器之间进行更多次的往返,
这样并不能提前页面渲染时间。
因此,我们应当只将渲染首屏内容所需的关键CSS内联到HTML中。

3 异步加载CSS: CSS会阻塞渲染,在CSS文件请求、下载、解析完成之前,
浏览器将不会渲染任何已处理的内容。
有时,这种阻塞是必须的,因为我们并不希望在所需的CSS加载之前,
浏览器就开始渲染页面。那么将首屏关键CSS内联后,
剩余的CSS内容的阻塞渲染就不是必需的了,可以使用外部CSS,并且异步加载。
那么如何实现CSS的异步加载呢?可以通过下面四种方式。

 - 第一种方式是使用JavaScript动态创建样式表link元素,并插入到DOM中
 - 第二种方式是将link元素的media属性设置为用户浏览器不匹配的媒体类型
(或媒体查询),如media="print",
甚至可以是完全不存在的类型media="noexist"。
对浏览器来说,如果样式表不适用于当前媒体类型,其优先级会被放低,
会在不阻塞页面渲染的情况下再进行下载。
当然,这么做只是为了实现CSS的异步加载,别忘了在文件加载完成之后,
将media的值设为screen或all,从而让浏览器开始解析CSS。
<link rel="stylesheet" href="a.css" media="noexist" 
                                    οnlοad="this.media='all'">

 - 第三种方式和第二种类似。我们还可以通过rel属性将link元素标记为
alternate可选样式表,也能实现浏览器异步加载。
同样别忘了加载完成之后,将rel改回去。
<link rel="alternate stylesheet" href="a.css" 
                                   οnlοad="this.rel='stylesheet'">
 - 前三种方式比较古老,现在,rel="preload" (参考网址: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Preloading_content#compat-desktop)
这一Web标准指出了如何异步加载资源,包括CSS类资源
rel="preload"在现在的浏览器中支持度不算乐观,
不过我们可以通过loadCSS(飞机票: https://github.com/filamentgroup/loadCSS/tree/v2.0.1#loadcss)进行polyfill,所以支持不支持,这都不是事儿。

4 去除无用CSS: 如果手动删除这些无用CSS是很低效的。
我们可以借助Uncss库来进行。
Uncss可以用来移除样式表中的无用CSS,并且支持多文件和JavaScript注入的CSS
飞机票: https://github.com/uncss/uncss

5 减少使用 @import, 而建议使用link, 因为
后者在页面加载时一起加载,
前者是等待页面加载完成之后再进行加载; 
首先,使用@import引入CSS会影响浏览器的并行下载; 
使用@import引用的CSS文件只有在引用它的那个css文件被下载、解析之后,
浏览器才会知道还有另外一个css需要下载,
这时才去下载,然后下载后开始解析、构建render tree等一系列操作; 
这就导致浏览器无法并行下载所需的样式文件。
其次,多个@import会导致下载顺序紊乱。在IE中,@import会引发资源文件的下载顺序被打乱,
即排列在@import后面的js文件先于@import下载,并且打乱甚至破坏@import自身的并行下载。
所以不要使用这一方法,使用link标签就行了; 

选择器性能: 
CSS选择符是从右到左进行匹配的
当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等; 

避免使用通配规则: 如*{} 计算次数惊人!只对需要用到的元素进行选择; 

尽量少的去对标签进行选择,而是用class: 如#nav li{},可以为li加上nav_item的类名; 
如下选择.nav_item{}; 

不要去用标签限定ID或者类选择符: 如:ul#nav,应该简化为#nav; 

尽量少的去使用后代选择器,降低选择器的权重值: 后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素

考虑继承: 了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则

css单一样式: 当需要下边距和左边距的时候,
很多时候选择:margin: top 0 bottom 0;margin-bottom: bottom; margin-left: left;执行的效率更高;

渲染性能: 
1 慎重使用高性能属性:浮动、定位;
2 尽量减少页面重排、重绘;
3 充分利用css继承属性,减少代码量;
4 抽象提取公共样式,减少代码量;
5 去除空规则:{};
6 属性值为0时,不加单位;
7 css雪碧图,同一页面相近部分的小图标,方便使用,减少页面的请求次数
8 选择器优化嵌套,尽量避免层级过深;
9 标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后;

可维护性、健壮性:
1 将具有相同属性的样式抽离出来,整合并通过class在页面中进行使用,提高css的可维护性;
2 通过定义可复用的、语义化良好的基础类,然后添加到html中,
这也是很多ui框架都在使用的一种方法,例如:class="btn btn-active btn-blue";
3 样式与内容分离:讲css代码定义到外部css中;
4 容器与样式分离;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值