在2020年岁末有幸和一群优秀大学生在一块儿聊CSS相关的话题,感到很是的荣幸!在此很是感谢平台(阿里巴巴集团.前端练习生计划)给我这样的机会,同时也要很是感谢好友 裕波,墨苒对个人鼓励和支持。在结束直播的时候,说事后面要整理一篇文字版本,因为我的新转团队(互动团队转到 F(x) Team团队),加上本身太懒,因此今天才开始整理文字版本。所幸能在岁末完成,还算是一种补救。但愿接下来的内容,对于新接触CSS或对CSS感兴趣的同窗有所帮助,更但愿有更多的同窗能参与阿里巴巴集团练习生计划的学习,并有所获。css
虽然之前也参加过一些前端行业的会议分享,但在线直播仍是生平第一次,感受仍是很不一样。其一没有这方面的经验,其二我仍是更喜欢线下会议的感受,由于这样能和你们在一块儿,有目光的交流。这是一种支持,一种鼓励,一种锻炼,也是一种幸福。html
在前端社区中,你们常称我“大漠”。我我的比较喜欢CSS,在这个领域深耕了近十年,虽无大的成就,但有所小收获。我的平时比较宅,爱写写博客,看看电影,听听音乐等。前端
在2014年出版了一本有关于CSS方面的的书:git
好像如今没有加印了,网上好象尚未停售,但内容有点偏老,不过还没过期!github
在手淘互动呆了五年,最近刚到淘系前端技术F(x) Team团队:编程
F(x) Team ,F(x) 指函数 F(x) ,是机器学习中常出现的符号,深度学习的本质也是求 f(x) 的最优解; 意味拥有不一样特征的成员通过 fx 团队神奇做⽤,不断“训练”,⼀起找到前端智能化团队的最优解。浏览器
接下来和你们围绕着这六个方面和你们聊今天的话题。markdown
自从1994年万维网之父蒂姆.伯纳斯-李在美国麻省理工学院创立了万维网(W3C),至今天也有几十年了。你可能会感到好奇,当初的的第一个网页长得像什么:框架
和今天你所看到的Web页面是否是相差十万八千里。有这种见解是正确的,在那个时候,对于Web页面而言,并无什么样式一说,并且那个时候Web页面所承担的也就是信息的传递。再简单地说,他只有文字和图像两种,并无其余的信息元素。机器学习
人老是爱漂亮的,即便是在那个年代,人们也想让本身构建的Web页面看上去更美。就在同年(1994年),哈肯.维姆.莱 提出层叠HTML样式表(Cascading HTML Style Sheets,CHSS):
在HTML的标签上新增了一些属性,好比 bgcolor 、 face 等,也有一些相似 标签来设置文本样式。
时至今日估计不多有人接触过,或者这样写过Web页面。就我我的而言,虽没有使用这些东西来构建Web页面,但仍是看到过不少页面长成这样。那时候我并不知道,原来这种技术也有本身的专业术语,即 CHSS ( 层叠HTML样式表 )。虽然说这些标签和属性能让页面上的元素有一些个性化的UI效果,好比改变文本颜色,字体,背景色之类的,但这样的写法对于Web开发者来讲是痛苦的,特别对于一个复杂,大型的Web应用,这样的方式来美化Web页面,绝对会让你痛苦难堪。
不说别的,最起码这种方式增长了代码的维护难度,同时也让代码变得臃肿。更没有什么灵活性,可扩展性,可用性一说了。
咱们这一批Web开发者是幸运的。就在1994年,哈肯.维姆.莱 和 伯特.波斯合做设计CSS,并在芝加哥的一次会议上展现了CSS的建议。这也是CSS第一次出如今Web开发者(不过,那个时候并无这个职称)眼中。并且在两年以后,CSS 1.0的规范出来了:
并且经历两年的发展,有了CSS2.0版本,在这以后,还经历了CSS 2.1和CSS 2.2版本的迭代。同时CSS 2.1规范指导Web开发者写CSS不少年。直到后面,也就是大约2015年,W3C规划的CSS工做小组发现CSS发展的愈来愈快,有关于CSS方面的特性增长了很多,并且不一样的特性推动速度都有所不一样。也就这个时候,W3C的CSS工做小组为了能更好的维护和管理CSS的特性,该组织决定不在以CSS的版本号,好比咱们熟悉的CSS1.0、CSS2.0、CSS2.1这样的方式来管理CSS。而是将每一个CSS功能特性拆分红独立的功能模块,而且以Level 1, Level2,Level 3等方式来管理CSS规范中的特性:
正如上图所示,即便CSS按功能模块拆分向前推动,但也并不表明拆分以后的CSS特性模块就能很快的进入到正式的标准规范中,就比如CSS2.0到正式进入标准规范也历时很长。这主要是由于,任何一个CSS的特性到成为真正的规范要经历多个阶段:
这个时候你可能已经感受到了,一个东东到成为正式规范是多么漫长的。这个漫长的过程除了W3C规范组织本身的问题,也还有客户端厂商为了各自的利益,在特性的支持上也有所不一样。对于咱们这些Web开发者来讲也是有问题,由于大家更多的时候只是CSS特性的使用者或者说布道者,但并非推进者。对于咱们身在国内的Web开发者而言,不多有人直接参与CSS特性的制定,讨论和推动。
在CSS 选择器 Level4模块出来的时候,社区开始有CSS4这个说法。事实上呢,早在2016年 @Rachelandrew就在社区中发声过《Why there is no CSS4 - explaining CSS Levels》:
在Github上@Jen Simmons 在 CSSWG Drafts上单独开了一个关于CSS4相关的帖子,社区中一些大神都对这个话题发表了本身的观点:
上面主要和你们聊了CSS的历史以及她的发展历程。
聊完CSS发展以后,咱们来再来聊聊CSS的现状。从2019年和2020年CSS发展状态报告中,咱们就能够看到CSS发展的一个现状:
这份报告相对于来讲仍是比较详细的:
除了对CSS特性、单位和选择器、方法论、框架、工具、环境等有统计以外,还对使用CSS的人群及现状也有描述,好比:
除了CSS状态发展报告以外,还有每一年的Web年鉴对CSS也会有相应的调查统计:
另外,还有一些其余的调查报告也会有一些CSS相关的报告,但都没有CSS状态发展报告这样详细和针对性。若是你对其余报告中关于CSS方面的调查分析,能够阅读 @Geoff Graham 的《2020 Roundup of Web Research》一文中列出的报告中查阅:
CSS称为 层叠样式表,便是 Cascade Style Sheets三个词的首字母缩写。每一个字母表明的含义不一样:
Web开发者都知道,一个Web页面或Web应用都由HTML、CSS和JavaScript三个部分组成:
每一个部分在Web中所起的做用都有所不同:
时至今日,Web应用或Web页面除了咱们上面所说的HTML、CSS、JavaScript三个部分组成以外,它还有一个新的部分,即 WAI-ARIA :
WAI-ARIA 是Web可访问性(A11Y)规范中的一部分,主要用来帮助咱们构建一个更具可访问性的Web应用。
对于初次接触CSS的同窗来讲,确定会感到好奇,CSS是如何工做的。要详细的讲清楚,那所涉及到的东西就多了,其中就少不了关于 浏览器工做原理 相关的内容。这方面也不是我擅长的领域,我只能在此抛砖引玉。
前面提到过,Web页面至少由HTML、CSS和JavaScript三个部分构成,其中HTML会通过HTML Parser将HTML结构转换成DOM Tree;CSS会通过CSS Parser将CSS转换成CSSOM Tree,正以下图所示:
DOM树和CSSOM树将会构建出渲染树:
最终通过几个过程就渲染出咱们所能看到的Web页面:
若是再把AOM(可访问树)引入起来的话,大体就像下图这样:
这有点偏离咱们今天要聊的主题了。若是你其中过程不想了解太多的话,只须要简单地记做:“CSS样式要和相应的HTML元素结合在一块儿使用,才能在浏览器渲染出来,呈现给用户”。
就我我的而言,我更喜欢把CSS称为七巧板或积木:
实现同一效果,咱们能够经过多种不一样方式来完成。
也正由于如此,不少同窗都认为CSS很烦人:
@Jeremy Keith 在2017年的CSS Day 大会说过:
大体意思是:
CSS与其编程语言不一样,她没有循环、逻辑和其余概念,它只是声明式的语言,所以,CSS很容易上手。也许正是由于如此,它才得到了简单的美誉。在 "不复杂 "的意义上,它是简单的,但这并不意味着它很容易。把 "简单 "误认为是 “容易”,只会让人心痛”
就此话题,在Twitter上,或者在社区时不时的就会有所争论:
有时候在Twitter上你也会感到,原来全世界的前端圈都像是个娱乐圈!
那么为何会有这些争论呢?为此我讲讲我本身对这方面的见解。
先上一张图:
若是从CSS的语法规则和属性的使用上来讲,它的确很是地简单,由于你只须要知道选择器选中了HTML中的哪一个元素,给他运用了什么样的属性和值,应该能在浏览器中呈现出来,好比:
body {
color: #fff;
background-color: #09f;
}
复制代码
上面几行简单的CSS代码,就可让你在浏览器中看到一个蓝底白字的效果:
并且也不须要一个一个把全部CSS属性及属性的值都记在脑中,由于咱们有不少方式能够查阅到,好比MDN上就有CSS属性列表:
这就是为何说CSS简单的主要缘由。
那么为何说CSS不容易呢?这是有不少缘由的,先拿你们认为CSS简单的规则来讲:
<div class="card">1</div>
<div class="card__news">2</div>
.card {
width: 100px;
}
.card.card__news {
width: 100%;
}
复制代码
想象一下,这两个 div 的 width 分别是什么呢?试问一下,你本身一看到上面的代码能自信,立刻的说出正确的答案?若是你心理想的答案和本身验证获得的答案是一致的,那么恭喜你,你对CSS有必定的认知,至少不是菜鸟级。那么请继续往下看这个示例:
<div class="a">Text</div>
<div class="b">Text</div>
<div class="a b">Text</div>
<div class="b a">Text</div>
.a {
color: red;
}
.b {
color: blue;
}
.a.b {
color: orange;
}
.b.a {
color: yellow;
}
复制代码
试问这四个 div 的文本颜色分本是什么?印象中 @Max Stoiber 在twitter上也出过相似的一个问卷:
就此题可让很多同窗感到困惑。除此以外,CSS中还有不少基本概念,可让你再也不以为CSS容易,好比:
上面列的这些基础概念,每个都须要一篇或多篇长文才能完全讲清楚。因此我只能在此为你们抛砖引玉,并在相应的内容上多附上相关知识点的连接。感兴趣的同窗,能够点击相应的连接进行扩展阅读。
CSS的层叠
按照前面的解释,层叠是指“Cascade”,拿个示例来解说可能会更易于理解。好比咱们在一个 style.css 样式文件中,对同一个元素写了两个样式规则:
<a href="#" class="link">Link</a>
a {
color: #90f;
}
.link {
color: #f36;
}
复制代码
a 先于 .link 出现,就是对同一元素使用的样式规则出现的前后顺序,被称为层叠。
事实上,CSS中的层叠要比这个更为复杂,除了前面示例中提到的样式规则出现的顺序还有另外一种层叠之说,它会涉及到CSS其余的一些概念,好比说:
也基于这个缘由,我把CSS中的层叠分为两个部分来阐述:
先来讲第一部分的。
文档流
在CSS中,文档流是一个很基础也是很重要的一个概念。不少时候她被称为Document Flow,但在CSS的标准被称为Normal Flow,即普通流或常规流。你们更喜欢称之为文档流。那么CSS的文档流是怎么一回事呢?
在HTML中任何一个元素其实就是一个对象,也是一个盒子。在默认状况下它是按照出现的前后顺序来排列,而这个排列的顺序就是文档流。
文档流是元素在Web页面上的一种呈现方式。全部的HTML元素都是块盒子(Block Boxes,块级元素)或行内框(Inline Boxes,行内元素)。当浏览器开始渲染HTML文档时,它从窗口的顶端开始,通过整个文档内容的过程当中,分配元素须要的空间。除非文档的尺寸被CSS规则限定,不然浏览器垂直扩展文档来容纳所有的内容。每一个新的块级元素渲染为新行。行内元素则按照顺序被水平渲染直到当前行遇到边界,而后换到下一行垂直渲染。
事实上,在普通文档流中的盒子属于一种格式化上下文(Formatting Context),你们较为熟悉的就是块格式化上下文(Block formatting context)和行内格式化上下文(Inline formatting context)。不过有一点面要注意,它们只能是其中一者,但不能同时属于二者。言外之意,任何被渲染的HTML元素都是一个盒子(Box),这些盒子不是块盒子就是行内盒子。即便是未被任何元素包裹的文本,根据不一样的状况,也会属于匿名的块盒子或行内盒子。
综合上面的描述,也能够理解格式化上下文对元素盒子作了必定的范围的限制,其实就是相似有一个width和height作了限制同样。若是从这方面来理解的话,普通流就是这样的一个过程:
扯了这么多,若是简单的描述就是:如何排列HTML元素而已。拿个块格式化上下文的普通文档流来举例,就像下面这样:
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
复制代码
对应的效果以下:
格式化上下文
前面屡次提到 格式化上下文 ,在CSS中,格式化上下文指的是:
初始元素定义的环境
其主要包含两个要点,一个是 元素定义的环境 ,另外一个是 初始化。
咱们使用CSS的 display 属性能够对元素进行格式化,即 建立格式化上下文 。
使用 display 对元素进行格式化以后,能够把内容装置在不一样的容器中,比如咱们生活中的器皿同样,不一样的器皿能够看到不一样的效果:
来看一个简单的示列:
上图中最大的差别就是左侧中的 ul 未显式设置 display: contents ;右侧中的 ul 显式设置了 display: contents ,设置了 display: contents 会改变原有的格式,即其子元素 li 都会变成网格项目,二者效果差别以下:
层叠上下文
平时咱们从设备终端看到的HTML文档都是一个平面的,事实上HTML文档中的元素倒是存在于三个维度中。除了你们熟悉的平面画布中的 x 轴和 y 轴,还有控制第三维度的z轴。
对于 x 和 y 轴咱们很易于理解,一个向右,一个向下。但对于 z 轴,理解起来就较为费力。在CSS中要肯定沿着 z 轴排列元素,表示的是用户与屏幕的这条看不见的垂直线:
该系统包括一个三维 z 轴,其中的元素是层叠(Stacked)的。 z 轴的方向指向查看者, x 轴指向屏幕的右边, y 轴指向屏幕的底部。
一般,浏览器会按照CSS规范中指定的特定顺序放置元素:
在DOM树中最早出现的元素被放在首位,以后出现的元素被放在前面的元素之上。但它并不老是那么简单。只有当页面上的全部元素是天然流才起做用。也就是说,当没有元素在流中的位置被改变或者已经脱离文档流,才起做用。
事实上,每一个HTML元素都属于一个层叠上下文。给定层叠上下文中的每一个定位元素都具备一个整数的层叠层级,具备更大堆栈级别的元素盒子老是在具备较低堆栈级别的盒子的前面(上面)。盒子可能具备负层叠级别。层叠上下文中具备相同堆栈级别的框根据文档树出现的顺序层叠在一块儿。
文档中的层叠上下文由知足如下任意一个条件的元素造成:
并且每一个页面都有一个默认的层叠上下文。这个层叠上下文的根就是 html 元素。 html 元素中的一切都被置于这个默认的层叠上下文的一个层叠层上。
叠层水平
层叠水平(Stacking Level)决定了同一个层叠上下文中元素在z轴上的显示顺序。Level这个词很容易让咱们联想到咱们真正世界中的三六九等、论资排辈。在真实世界中,每一个人都是独立的个体,包括双胞胎,有差别就有区分。例如,又胞胎虽然长得很像,但实际上,出生的时间仍是有前后顺序的,先出生的那个就大(大哥或大姐)。网页中的元素也是如此,页面中的每一个元素都是独立的个体,他们必定是会有一个相似排名排序的状况存在。而这个排名排序、论资排辈就是咱们这里所说的层叠水平。层叠上下文元素的层叠水平能够理解为官员的职级,一品两品,县长省长之类;对于普通元素,这个嘛...你本身随意理解。
因而,显而易见,全部的元素都有层叠水平,包括层叠上下文元素,层叠上下文元素的层叠水平能够理解为官员的职级,一品两品,县长省长之类。而后,对于普通元素的层叠水平,咱们的探讨仅仅局限在当前层叠上下文元素中。为何呢?由于不然没有意义。
翻译成术语就是:
普通元素的层叠水平优先由层叠上下文决定,所以,层叠水平的比较只有在当前层叠上下文元素中才有意义。
须要注意的是,诸位千万不要把层叠水平和CSS的 z-index 属性混为一谈。没错,某些状况下 z-index 确实能够影响层叠水平,可是,只限于定位元素以及Flex盒子的孩子元素;而层叠水平全部的元素都存在。
叠层顺序
在HTML文档中,默认状况之下有一个天然层叠顺序(Natural Stacing Order),即元素在 z 轴上的顺序。它是由许多因素决定的。好比下面这个列表,它显示了元素盒子放入层叠顺序上下文的顺序,从层叠的底部开始,共有七种层叠等级:
这七个层叠等级构成了层叠次序的规则。 在层叠等级七上的元素会比在等级一至六上的元素显示地更上方(更靠近观察者)。 能够结合w3help中的一张图来帮助咱们更好的理解这七个层叠等级:
其实对于层叠顺序规则仍是较为复杂的。
当页面包含浮动元素、绝对定位的元素、固定定位的元素或相对定位的元素(元素从正常位置偏移必定量)以及内联元素时,浏览器会以不一样的方式显示它们(放置它们)。元素从最靠近查看者的地方排列到最远的地方,以下所示:
这就是浏览器在呈现页面上的元素时应用的默认层叠顺序。
若是你想要更改定位元素在 z 轴上的渲染顺序,可使用 z-index 属性。例如,你有两个绝对定位的元素,它们在某个点上重叠,而且你但愿其中一个元素显示在另外一个元素的前面,即便它在源代码中出如今它以前,你也可使用 z-index 属性来实现这一点。
此时须要注意的第一件重要的事情是, z-index 属性只适用于定位元素。因此,即便为元素提供 z-index 的值将其置于其余元素以前, z-index 也不会对元素产生影响,除非它被定位;也就是说,除非它具备除 static 以外的 position 值。
所以,若是全部定位的元素具备z-index的索引值,则将元素从最靠近查看者排列到最远的位置,以下所示:
具备正值的 z-index 的定位元素。较高的值更接近屏幕。而后,按照它们出如今源代码中的顺序排列:
当咱们在定位元素上设置 z-index 值时,它指定该元素在它所属的层叠顺序上下文中的顺序,而且它将根据上述步骤在屏幕上渲染。
可是,当咱们设置元素的 z-index 时会发生另外一件事。获取除默认值 auto 以外的 z-index 值的元素实际上为其全部定位的后代元素建立层叠上下文。咱们以前提到过,每一个层叠上下文都有一个根元素,它包含其中的全部元素。当你将 z-index 属性应用于这个元素时,它将在其包含的下下文中指定元素的 z 轴顺序,而且还将建立以该元素为根的新层叠顺序上下文。
一个具备值为 z-index:auto 的定位元素被视为建立了新的堆叠顺序上下文,但任何实际建立新层叠顺序上下文的定位后代和后代被视为父层叠顺序上下文的一部分,而不是新的层叠顺序上下文。
当一个元素成为一个新的层叠顺序上下文时,它所定位的后代元素将会按照咱们前面提到的元素自己的规则在其中进行层叠渲染。所以,若是咱们再次重写渲染过程,它会是这样的:
所以,当咱们使用 z-index 属性来肯定其层叠顺序中定位元素的顺序时,咱们还建立了“原子(Atomic)”层叠顺序上下文,其中每一个元素成为其全部定位后代的层叠顺序上下文。
样式层叠
再回过头来看样式的层叠。CSS在任何代码块中,好比 {} 中均可以同时书写相同的样式规则,好比:
p {
color: red;
color: blue; /* 被采用 */
}
复制代码
虽然这样书写并不会引发错误,但不建议这么来写CSS样式规则。
前面咱们也提到过,在同一个样式文件中也有可能在对同一个元素使用相同的样式规则,好比:
<a class="link"></a>
a {
color: red;
}
.link {
color: blue;
}
复制代码
甚至是咱们在不一样的样式文件中也可对同一元素使用相同的样式规则,好比
/* base.css */
a {
color: red
}
/* style.css */
@import base.css;
a {
color: orange;
}
<!-- index.html -->
<link href="style.css" />
<style>
a {
color: lime;
}
</style>
复制代码
上面几种不一样的样式写法,均可以被称为样式的层叠。只不过最终被运用到元素上的规则以最终出现的规则为准,固然这也有一个前提条件,那就是他们选择器权重是相同。
权重
在CSS领域说到权重,或许你们更多关注到的是CSS选择器的权重。其实除了选择器权重对元素样式有影响以外,也和CSS样式规则出现的前后顺序有关(正如前面所提到的层叠顺序)。并且除了选择器有权重以外,也有属性权重一说。
对于选择器权重,下图能够很形象的阐述:
选择器权重能够相似于海洋世界中的生存规则,大鱼吃小鱼,小鱼吃虾米。若是你实现不清楚两个选择器的权重,也能够 使用在线的测试工具来检测:
对于一个选择器的权重,将会按下面这样的规则进行计算:
4个数连起来 a-b-c-d (在一个基数很大的数字系统中)表示特殊性,好比下面这样的示例:
* {} /* a=0 b=0 c=0 d=0 -> 选择器权重 = 0,0,0,0 */
li {} /* a=0 b=0 c=0 d=1 -> 选择器权重 = 0,0,0,1 */
li:first-line {} /* a=0 b=0 c=0 d=2 -> 选择器权重 = 0,0,0,2 */
ul li {} /* a=0 b=0 c=0 d=2 -> 选择器权重 = 0,0,0,2 */
ul ol+li {} /* a=0 b=0 c=0 d=3 -> 选择器权重 = 0,0,0,3 */
h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> 选择器权重 = 0,0,1,1 */
ul ol li.red {} /* a=0 b=0 c=1 d=3 -> 选择器权重 = 0,0,1,3 */
li.red.level {} /* a=0 b=0 c=2 d=1 -> 选择器权重 = 0,0,2,1 */
#x34y {} /* a=0 b=1 c=0 d=0 -> 选择器权重 = 0,1,0,0 */
style="" /* a=1 b=0 c=0 d=0 -> 选择器权重 = 1,0,0,0 */
复制代码
客户端渲染页面时,除了选择器权重会影响元素样式规则以外,还有样式来源也会影响元素样式规则。就CSS规则的来源而言,规则主要来自三个地方:
这三种样式表将在必定范围内重叠,而且它们按照层叠互相影响。
CSS中运用于同一元素时的属性也会有权重一说,好比说一样用来描述元素宽度的属性 width 、 min-width 、 max-width ,好比:
最终 max-width: 100% 取胜,即max-width权重高于 width 和 min-width ,但这并非绝对的,这和场景有着紧密关系。不过同时在同一个元素上使用了这三个属性时,他们的权重大体以下:
若是你使用Flexbox来构建Web的布局,那么对于Flex项目的宽度也有必定的权重规则:
首先根据 content ➜ width ➜ flex-basis 来决定用哪一个来决定用于Flex项目。若是Flex项目显式设置了 flex-basis 属性,则会忽略 content 和 width 。并且 min-width 是用来设置Flex项目的下限值; max-width 是用来设置Flex项目的上限值。
即:
因为 min-width 大于 max-width 时会取 min-width ,有了这个先取条件咱们就能够将 flex-basis 和 min-width 作权重比较,即: flex-basis 会取于 min-width 。反过来,若是 min-width 小于 max-width 时则依旧会取 max-width ,同时要是 flex-basis 大于 max-width 就会取 max-width 。
注意,Flexbox布局中有关于Flex项目的宽度计算是很是复杂的。
继承
“继承”是CSS中另外一个重要概念。在W3C规范中,描述每一个CSS属性时都会有一个选项是“Inherited”,若是值为“no”表示该属性是不可继承的,好比下图左侧的 border 属性;若是值为“yes”表示该属性是可继承的,好比下图右侧的 color 属性:
在CSS中提供了处理CSS继承的机制,简单地讲就是CSS提供了几个属性值,能够用来处理属性的继承。这几个属性值就是 initial 、 inherit 、 unset 和 revert 。其实除了这四个属性值以外,还有一个 all 属性值。虽然这几个属性值主要用来帮助你们处理CSS属性继承的,但他们之间的使用,仍是有必定的差别化。
也就是说,CSS的层叠、权重和继承都会对你的CSS有影响。在实际使用的时候,若是很好的运用这些概念和手段,能够更好的帮助你们少写不少样式代码,并且更易于维护本身的CSS代码。
这里提到的CSS层叠、权重和继承都是CSS的基础概念,也是CSS的核心概念,掌握或者了解这些概念对于每一位从事Web开发者同窗而言都是颇有必要的。只有掌握这些概念,有助于帮助你们更好的理解CSS和正确的使用CSS。
视觉格式化模型
首先要声明一点:
视觉格式化模型和CSS盒模型不是同一个东西!
简单点说呢。Web页面(文档树)是由很一个个盒子组成(由于任何元素均可以被视为是一个盒子),而视觉格式化模型倒是一套规则,用来计算元素转换为盒子的规则。而页面的布局都由这些盒子的所处的各处位置组合而成。那么理解了元素怎么转成盒子的规则,就理解了Web页面是怎么布局。而每一个盒子的布局主要由如下几个因素决定:
若是你想完全理解CSS的视觉可式化模型,其中还有一些概念须要掌握,好比:
除了上述说到的盒子,在CSS中还定义了几种内容模型,这些模型一样能够应用于元素。这些模型通常用来描述布局,它们可能会定义一些额外的盒子类型:
就这些概念也足让咱们感到烦人了吧。我想你看到这些概念,应该不会再说CSS容易了。
有了这些概念,咱们再来讲CSS中的格式化上下文。我想你或多或少听过这个词吧。在CSS中,格式化上下文有不少种,除了你们熟悉的 BFC 、 IFC 以外还有由Flexbox布局建立的 FFC 和Grid布局建立 GFC 等。这些统称为CSS 格式化上下文 ,也被称做 视觉格式化模型 。而CSS视觉格式化模型是用来处理文档并将它显示在视觉媒体上的机制。
简单地说, 就是用来控制盒子的位置,即实现页面的布局 。
格式化上下文也能够说是CSS视觉渲染中的一部分, 其主要做用是决定盒子模型的布局,其子元素将如何定位以及和其余元素的关系和相互做用 。那么理解CSS格式化上下文有助于咱们掌握各种CSS布局的关键。
行内格式化上下文
行内格式化上下文(Inline Formatting Context),简称 IFC 。主要用来规则行内级盒子的格式化规则。
IFC的行盒的高度是根据包含行内元素中最高的实际高度计算而来。主要会涉及到CSS中的 font-size 、 line-height 、 vertical-align 和 text-align 等属性。
行内元素从包含块顶端水平方向上逐一排列,水平方向上的 margin 、 border 、 padding 生效。行内元素在垂直方向上可按照顶部、底部或基线对其。
当几个行内元素不能在一个单独的行盒中水平放置时,他们会被分配给两个或更多的(Vertically-stacked Line Box)垂直栈上的行盒,所以,一个段落是不少行盒的垂直栈。这些行盒不会在垂直方向上被分离(除非在其余地方有特殊规定),而且他们也不重叠。
下面这些规则都会建立一个行内格式化上下文:
IFC主要用于:
块格式化上下文
块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其余元素交互的区域。
BFC实际上就是页面中一块渲染区域,该区域与其余区域隔离开来。容器里面子元素不会影响到外部,外部的元素也不会影响到容器里的子元素。
BFC 内部的盒子会从上至下一个接着一个顺序排列。BFC 内的垂直方向的盒子距离以 margin 属性为准,上下 margin 会叠加。每一个元素的左侧最外层边界与包含块 BFC 的左边相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此。BFC 的区域不会与浮动元素的盒子折叠。BFC 的高度也会受到浮动元素的影响,浮动元素参与计算。
下面这些规则能够建立一个BFC:
块格式化上下文包含建立它的元素内部的全部内容。其主要使用:
Flex格式化上下文
Flex格式化上下文(Flexbox Formatting Context)俗称 FFC 。当 display 取值为 flex 或 inline-flex ,将会建立一个Flexbox容器。该容器为其内容建立一个新的格式化上下文,即Flex格式化上下文。
不过要注意的是,Flexbox容器不是块容器(块级盒子),下列适用于块布局的属性并不适用于Flexbox布局:
Grid格式化上下文
Grid格式化上下文(Grid Formaatting Context),俗称 GFC 。和FFC有点相似,元素的 display 值为 grid 或 inline-grid 时,将会建立一个Grid容器。该完彻底全器为其内容建立一个新的格式化上下文,即Grid格式化上下文。这和建立BFC是同样的,只是使用了网格布局而不是块布局。
网格容器不是块容器,所以一些假定为块布局设计的属性并不适用于网格格式化上下文中。特别是:
盒模型
在CSS世界中,会何一个HTML元素能够解析成一个盒子。能够经过CSS属性(物理属性)来决定盒子的大小。而决定盒子大小主要由四个属性来决定:
若是咱们用一张图来描述的话,能够相似下面这样的:
上面提到的几个属性就是浏览器渲染元素盒子所须要的一切。对于CSSer来讲,都喜欢用相似下图来阐述元素的盒模型:
而在浏览器调试器中“Computed”能够看到它是怎么来解释一个元素的盒模型:
在通常状况之下,咱们所说的盒子的 width 是元素内容的宽度,内距和边框的和,这也经常被称之为内盒的宽度。若是你在内盒的宽度上加外距的大小就能够计算出盒子外盒的宽度。
盒子的 height 计算和 width 相似。
但在布局中,盒子的宽度计算会直接影响到布局,甚至会直接打破页面的布局。好比说,一个 div 元素:
div {
width: 100%;
padding: 1rem;
}
复制代码
会让 div 超出容器,相似下图这样:
面对这样的场景时,就须要借助CSS的 box-sizing 属性,它能够更好的帮助咱们控制盒子的大小:
用个实例来解释,这样更易于理解:
你们是否有留意到,在前面提到的 padding 、 border 和 margin 等都是采用的物理特性来描述一个盒子,并且开发者讨论盒模型的时候,都习惯使用下图来阐述它:
但随着CSS的逻辑属性的出现,在CSS中就除咱们所熟悉的物理属性以外,还新增了不少逻辑属性:
同时逻辑属性对于CSS盒模型也将带来相应的变化:
若是你在布局时,使用逻辑属性来替代物理属性,对于一些国际网站,好比阿拉伯语的网站,有着明显的做用。在改变书写模式时,不须要额外调整布局相关的属性:
布局
Web布局对于Web前端开发者而言,它就是一个永恒的话题。
随着Web技术不断向前推动,Web布局相关技术也在Web不一样的演化过程也有相应的演进。
在Web布局整个演进过程中,经历了没有任何布局、表格布局、定位布局、浮动布局、Flexbox布局等布局模式。除了这些咱们常看到的布局以外,即将还会有Grid、Shapes(相似杂志不规则布局)和多列布局(相似报纸排版布局)等现代布局模式。这些布局模式从侧面也反映出其自身是Web演进过程当中的一种产物,都承载了本身在当时那个时期的史命。
对于Web前端开发人员而言面对Web的布局始终跟着网页的设计在走。而网页的设计在不一样的时期也在不断的发生变化:从最初的站点到如今流行的站点在设计的发展有三个阶段:
不一样是代的的设计情景之下,Web的元素的定位也有其演变过程:
若是咱们用乐高积木来形容的话,会更为形象一些,如上图所示。
针对不一样阶段,Web布局相对应的模式也能够套入整个设计演变过程,若是有人猿进化来描述的话,有点相似下图:
时至今日,已经是移动端的天下,咱们须要针对的设备类型也多起来了,为了知足更多的设备终端,咱们还可使用响应式Web布局:
但这并无终止Web布局的讨论。或许你不久就须要面对折叠设备或多屏设备的布局适配:
多屏和折叠屏设备的出现,有多是下十年Web开发方式,设计和交互的模式都将带来改变。一样的,有关于这方面设备的CSS相关规范也开始在草案阶段。
写CSS的姿式
正由于CSS的层叠、权重、继承等因素,不少开发者在编写CSS的时候老是会碰到选择器冲突、样式覆盖、代码冗余等种种问题。为此,社区中有不少种关于书写或者说维护CSS的方法论,好比:
也有不少相关的CSS框架(CSS Frameworks)来帮助你们快速编写CSS,构建项目:
特别是这两年,社区讨论比较多的是Utility-first CSS,而这方面的表明框架就是Tailwind CSS:
就我的而言,我比较喜欢BEM和Atomic:
如今我喜欢的是**Utility-first CSS是Tailwind CSS。
除了CSS的方法论和框架,为了提升你们的编码效率和维护项目的CSS,社区中还有不少CSS方面的处理器:
不少时候,Sass、Stylus和LESS常被称为预处理器,PostCSS常被称为后处理器,他们能够说是一前一后:
他们之间的关系以下图所示:
不过,随着React和Vue这样的框架出来以后,社区中出现另外一种声音,那就是在JavaScript中编写CSS(即:CSS-in-JS):
经历的这些种种,CSS的编写和维护也发生了很大的变化:
不过,无论怎么变,咱们在编写CSS时,均可以像下面这张找到最为适合的方式。由于没有最好,只有最合适:
@Brandon Smith 有一篇博文是专门说 CSS is Awesome!
为何说CSS很是棒(很是强大)呢?我从我本身的角度来和你们聊这个话题。
有一点年纪的CSSer(或者说Web开发者)对于CSS禅意花园应该不会感到陌生。CSS禅意花园有一个最大的特点,那就是基于同一套HTML的结构,能够实现不一样的Web UI效果,即,有着不一样的布局风格:
它也被称为CSS设计之美。并且还有一本这方面的书:
感兴趣的同窗不仿也去试试,看看本身能基于同一套HTML结构,能实现多少种不一样的UI效果。
另一个和CSS禅意花园类似的就是 @Stephanie Eckles 推出的 Style Stage,也能够基于同一HTML结构,实现 同的UI效果:
我把她称为现代版的CSS禅意花园,现代版的CSS设计之美。
时至今日,在现代Web开发中,CSS愈来愈强大,她的做用不只仅是实现Web布局,简单的UI效果。咱们可使用CSS实现项目中不少复杂的UI效果:
我把她称之为CSS的视觉之美。
使用CSS的 border 、 box-shadow 、 border-radius、渐变、 clip-path、 transform和 mask 等属性能够直接用来绘制不一样的视觉效果,甚至实现一些复杂的UI,还能够结合CSS的 transition和 animation 实现带有微动效的UI场景。
想象一下,使用一个 div 绘制不一样的UI效果,你可能看到效果,会以为难以想象吧:
更难以想象的是,使用CSS还能够绘画:
在咱们国内 @袁川 老师在这方面也颇有研究,好比袁川老师在CSSConf(中国)分享的《Generative Art With CSS》的话题:
给你们展现了如何使用以 绘制不一样的艺术做品,你会领略到CSS神奇的另外一面,也会感叹到原来CSS离艺术的创做是这么的近:
除此以外,近几年CSS发展也特别的快,推出不少新特性。好比@argyleink在伦敦(LondonCSS 2020)CSS第四次活动中分享的一个话题《What's new with CSS?》,就提到了不少个CSS的新特性:
在PPT中提到:
我在该基础上从新整理了一篇新的文章,在文章中介绍了近24个有关于CSS方面的特性。
另外,在分享的时候,还遗漏了一个话题,那就是CSS的Houdini,我自已对这方面很是的感兴趣。今年的GDS大会上 @Una Kravets 就分享了一个这方面的话题,并且还向特区推出了houdini.how网站,收集了CSS Houdini中Paint API和自定义属性构建的Demo集:
在houdini.how提供的Demo,咱们均可以经过调整自定义属性值,看到不一样的效果:
若是你对这方面感兴趣的话,也能够把本身构建的Demo提交到Github的仓库中。
接下来简单地聊一下,我本身是怎么学习CSS的,仅是本身的一点当心得,仅供参考。
我想无论是学习什么知识,应该都离不开书吧!就CSS方面,我以为有几本书是很值得你们花点时间阅读的,好比:
若是你已不是初级的CSSer,那么W3C中有关于CSS相关的规范文档是值得一读:
说实话,阅读规范是件痛苦的事情,但不一样的时期,不一样的阶段去阅读规范都会有不一样的收获。比如我本身,我今年从新阅读这些规范时,收获就很多。可能阅读规范更多关注点是CSS属性的使用,但近一年来从新阅读规范时,我更关注的是属性使用的临界点相关的知识。换句话说,咱们在平时使用CSS时碰到的问题,其实在规范中都有相应的描述,也能找到相应的答案。
除了阅读规范以外,社区中不少优秀的博客也是值得咱们去阅读:
在中国社区,有关于CSS方面的博客,特别推荐:
在社区中发现好的博客或者站点时,你还可使用RSS应用来订阅它们:
RSS是一个好东西,她能帮你省下很多的时间,并且获取信息更有针对性,都有多是你本身喜欢的内容。
须要这个RSS列表的,能够私密偶!
若是你不太喜欢使用RSS的话,也可使用一些浏览器的扩展插件,好比Chrome浏览器,我就整了一个Daily.dev:
获取信息还有另外一种方式,那就是订阅Github上感兴趣仓库或者关注行业内的一些大神:
获取信息渠道不少,形成获取信息成本很大。不少时候可能今天看到了好的话题,只是草草瞄了一下,想在有时间的时候深读,却在这个时候找不到文章的连接了。我就常犯这样的毛病,为此我这两年养成了一个习惯,在本地建立了一个本地Blog,其中有一个栏目就是收集每月本身认为有意思的文章:
上面说的都是看和读,仅此是不够的,咱们应该还须要多写。
写Demo,我本身经常会在Codepen上写一些Demo,无论是验证性的,仍是创做性的,或者说是练习性的。我都喜欢在上面写:
Codepen上除了可让本身作练习以外,还能够看到不少Demo,从别人写的Demo中学到一些新知识,新技巧。若是你尚未开始体验的话,那么这里强烈建议你开启在Codepen之旅。
除了写Demo仍是不够的,咱们还应该针对本身学的知识点作总结,其中写博客就是很好的一种方式:
我本身通常会先对问题分类:
针对这些都列出一些清单,那么就能够有计划的去看一些东西,学一些东西,写一些东西。
到如今为止,应该是2020年最后一天了,回忆了一下,我自2010年建立W3cplus到如今,我坚持写了十年的博客,差不写了1561篇文章:
固然,你可能会以为有些是无用的,但就我本身而言都是有用的。除了有写博客的习惯以外,我有时候还会对本身的一年,或一个阶段作一些总结。
每一个人和每一个人都会有所不一样的,均可能有适合本身的一套方法,个人学习方法可能比较笨,简单地说就是 多看 、 多写 、 多问 、 多总结 等。
临近年末,我本身从呆了五年以外的互动团队换到了 淘系F(x) Team 团队。开启了新的征程,在新团队主要作的是一款技术产品:imgcook
若是你感兴趣的话,能够直接来先体验一波!若是你使用imgcook碰到任何问题,均可以私密偶!
最后留一个话题,但愿对该话题感兴趣的同窗能够一块儿来探讨:
“ 在不久的将来,AI会取替CSSer吗? ”