前言
从1996年W3C推出的第一版CSS规范代表CSS的诞生到现在2022年,CSS已经有了20多年的沉淀。我在了解CSS的发家史发现,CSS在一系列为解决HTML越来越庞杂的问题的技术中脱颖而出的核心竞争力是有奥秘的。它能在当时的那么多样式表语言中脱颖而出,我认为层叠特性有着举足轻重的功劳,层叠策略对于样式的显示是相当灵活的.其次CSS的核心“武器”便是“普通流(文档流)”的概念。为了使得描述有一定的逻辑性和时间顺序,在第一扎CSS2的讨论中我将作重围绕【层叠特性|文档流】这两个大的点来展开对CSS2中琐碎的知识点的扩充说明。CSS3作为互联网洪流时代适应移动端的产物,在和CSS2相比之下更加丰富更加规范,更加具有体系化,同时也更加的复杂。在第二扎中我主要是对CSS3中添加的新特性以及其使用方法做个展示。随着硬件科技的日渐发达,在现在移动端在主流开发中的占比也越来越大,在第三扎中则是对目前主流的移动端布局的几个方式进行展示梳理,通过实战案例让新的布局方式能够有熟练的使用。最后,希望在整篇的记录和梳理之下我能够有所感悟和收获。
第一扎 CSS2.1
从DOM的角度认识CSS
DOM(Document Object Model),翻译过来就是文档对象模型,它定义了所有 HTML 元素的对象和属性,以及访问它们的方法(接口)。核心观点就是将整个HTML文档比喻成一棵树,而我们所说的每个元素就相当于是这棵树上的节点,如下图所示:
从图中可以看出,节点就是我们所说的HTML的元素,我们可以给这些节点元素添加绑定任意的属性值,而这些节点元素对象中的属性就会被浏览器按照约定好的规则解析并且渲染最终展示在我们的面前,形成我们所说的网页。我们经常有这样的比喻:HTML是骨架、CSS是皮肤、JavaScript是灵魂,他们构建出我们形形色色的网页。但是我们要明确一点——浏览器是这个世界的造物主。
浏览器是造物主,HTML是骨架、CSS是皮肤、JavaScript是灵魂,通过造物主将这些元素融合就形成了世间万物。除开人我们本身这个例子,世界万物都是如此,比如:石头是只有骨架和皮肤不会动的东西,所以它没得灵魂不会动。HTML属于CSS和JavaScript必要不充分条件,建造的顺序没法颠倒。总不会有人能够成功将HTML写进CSS或者JavaScript中能够成功在浏览器中运行吧!当然现在出现的诸如Node等等这些脚本语言,我们不做讨论,因为他们的造物主并不是浏览器,属于另外一个世界。
由此可以得出结论,CSS本质是字符串,想要让他们有意义就需要浏览器的解析并且作为对象嵌入到HTML DOM对应的节点元素当中,这样渲染出来后就能够在浏览器中成功看到CSS给HTML文档穿上的华丽的衣服了。
CSS的专业术语及使用
那么有意思的就来了。如何让CSS文件中这些普普通通的字符串赋予意义用在美化网页上呢?我们就要学习CSS的专业术语让浏览器能够正确知道我们的意图,按照我们的意图渲染出我们想要的样式。
1.属性
属性对应的是平常我们书面或交谈时对CSS的中文称谓。例如,上面示意CSS代码中的height和color就是属性。当我们聊天或者分享时说起CSS的时候,嘴里冒出来的都是“这个元素高度99像素”,或者“这个文字颜色透明”,而“高度”和“颜色”就是CSS世界的属性,感觉有点儿像现实世界里人的姓氏。
2.值
“值”大多与数字挂钩。例如,上面的99px就是典型的值。在CSS世界中,值的分类非常广泛,下面是一些常用的类型。
整数值,如z-index:1中的1,属于,同时也属于。
数值,如line-height:1.5中的1.5,属于。
百分比值,如padding:50%中的50%,属于。
长度值,如99px。
颜色值,如#999。
此外,还有字符串值、位置值等类型。在CSS3新世界中,还有角度值、频率值、时间值等类型,这里就不全部展示了。
3.关键字
顾名思义,关键字指的是CSS里面很关键的单词,这里的单词特指英文单词,abc是单词吗?不是,因此,如果CSS中出现它,一定不是关键字。上面示例CSS代码中的transparent就是典型的关键字,还有常见的solid、inherit等都是关键字,其中inherit也称作“泛关键字”,所谓泛关键字,可以理解为“公交车关键字”,就是“所有CSS属性都可以使用的关键字”的意思。
4.变量
CSS中目前可以称为变量的比较有限,CSS3中的currentColor就是变量,非常有用。
5.长度单位
CSS中的单位有时间单位(如s、ms),还有角度单位(如deg、rad等),但最常见的自然还是长度单位(如px、em等)。需要注意的是,诸如2%后面的百分号%不是长度单位。
6.功能符
值以函数的形式指定(就是被括号括起来的那种),主要用来表示颜色(rgba和hsla)、背景图片地址(url)、元素属性值、计算(calc)和过渡效果等,如rgba(0,0,0,.5)、url(‘css-world.png’)、attr(‘href’)和scale(-1)。
7.属性值
属性冒号后面的所有内容统一称为属性值。例如,1px solid rgb(0,0,0)就可以称为属性值,它是由“值+关键字+功能符”构成的。属性值也可以由单一内容构成。例如,z-index:1的1也是属性值。
8.声明
属性名加上属性值就是声明,例如:
color: transparent;
9.声明块
声明块是花括号({})包裹的一系列声明,例如:
{
height: 99px;
color: transparent;
}
10.规则或规则集
出现了选择器,而且后面还跟着声明块,比如本小节一开始的那个例子,就是一个规则集:
.vocabulary {
height: 99px;
color: transparent;
}
在明确CSS的基本语法之后就是使用的阶段了。
CSS引入和使用方式
有了对专业术语和对css基本规则的认识我们就要,按照规范在HTML文档中使用我们的CSS层叠样式表。有三种引入和使用的方式分别是【行内样式】【内部样式】【外部样式】,下面将通过案例来认识:
一、行内样式
使用style属性引入CSS样式。
二、内部样式表
在style标签中书写CSS代码。style标签写在head标签中。
三、外部样式表
CSS代码保存在扩展名为.css的样式表中
HTML文件引用扩展名为.css的样式表,有两种方式:链接式、导入式。
导入的链接可以使用相对路径也可以是绝对路径
语法:
1、链接式
<link type="text/css" rel="styleSheet" href="CSS文件路径" />
2、导入式
<style type="text/css">
@import url("css文件路径");
</style>
综合实例【完整案例CSS引入方式.html】:
<head>
<!-- 外部样式引入--链接式 -->
<link rel="stylesheet" href="css/style.css" />
<!-- 外部样式引入--导入式 -->
<style>
@import url(CSS/style.css);
</style>
<!-- 内部样式使用 -->
<style>
div {
margin-left: 50%;
color: #ffe8e8;
transform: translateX(-50%);
text-align: center;
}
</style>
</head>
<body>
<!-- 行内样式使用[在元素节点标签内] -->
<p style="color: pink; font-size: 20px">给我一个粉红的回忆</p>
</body>
案例效果:
引入样式的说明
外链css为什么放在head
这是因为浏览器对HTML文档的读取解析顺序是从上到下的,如果把css放在底部,当网速慢时,html代码加载完成但css没加载完,会导致页面没有样式而难以阅读,所以先加载css样式能让页面正常显示。
CDN引用技术
CDN(Content Delivery Network)是指内容分发网络,我们只需要知道它对我们的CSS有什么用处。
我们可以通过引用CDN的链接直接使用别人分享的链接作为外联引用从而直接使用别人的第三方样式库。常用的CDN托管网站有【https://staticfile.org/】
CSS2选择器的使用
选择器可以理解成用来瞄准HTML DOM树上节点元素的东西,想要对元素进行操作,我们就将写好的声明块通过选择器发射给指定的节点元素上,为改节点添加样式(化妆)。
在CSS2.1中已经出现的选择器有5类分别是【基本选择器】【多元素的组合选择器】【CSS 2.1 属性选择器】【CSS 2.1中的伪类】【CSS 2.1中的伪元素】
一、基本选择器
在开发中我们最常见的4个选择器
序号 | 选择器 | 含义 |
---|---|---|
1. | ***** | 通用元素选择器,匹配任何元素 |
2. | E | 标签选择器,匹配所有使用E标签的元素 |
3. | .info | class选择器(类选择器),匹配所有class属性中包含info的元素 |
4. | #footer | id选择器,匹配所有id属性等于footer的元素 |
实例:
* {
margin:0; padding:0; }
p {
font-size:2em; }
.info {
background:#ff0; }
p.info {
background:#ff0; }
p.info.error {
color:#900; font-weight:bold; }
#info {
background:#ff0; }
p#info {
background:#ff0; }
二、多元素的组合选择器
序号 | 选择器 | 含义 |
---|---|---|
5. | E,F | 多元素选择器,同时匹配所有E元素或F元素,E和F之间用逗号分隔 |
6. | E F | 后代元素选择器,匹配所有属于E元素后代的F元素,E和F之间用空格分隔 |
7. | E > F | 子元素选择器,匹配所有E元素的子元素F |
8. | E + F | 毗邻(兄弟)元素选择器,匹配所有紧随E元素之后的同级元素F |
实例:
div p {
color:#f00; }
#nav li {
display:inline; }
#nav a {
font-weight:bold; }
div > strong {
color:#f00; }
p + p {
color:#f00; }
三、CSS 2.1 属性选择器
CSS 属性选择器通过已经存在的属性名或属性值匹配元素。
序号 | 选择器 | 含义 |
---|---|---|
9. | E[att] | 匹配所有具有att属性的E元素,不考虑它的值。(注意:E在此处可以省略,比如"[cheacked]"。以下同。) |
10. | E[att=val] | 匹配所有att属性等于"val"的E元素,即匹配任何形式的单词 |
11. | E[att~=val] | 匹配所有att属性具有多个空格分隔的值、其中一个值等于"val"的E元素,即属性值中可以有其他空格隔开的元素 |
12. | E[att|=val] | 表示带有以 att 命名的属性的元素,属性值为“value”或是以“value-”为前缀("- "为连字符,Unicode 编码为 U+002D)开头。典型的应用场景是用来匹配语言简写代码(如 zh-CN,zh-TW 可以用 zh 作为 value) |
实例:
/*很容易忽略的一个点,当存在这个属性的时候使用该声明块*/
p[title] {
color:#f00; }
/* 匹配.my error, .error,但不匹配.myerror。*/
div[class=error] {
color:#f00; }
/* 匹配.coll,.cor coll 但不匹配.corcoll */
td[headers~=coll] {
color:#f00; }
p[lang|=en] {
color:#f00; }
blockquote[class=quote][cite] {
color:#f00; }
四、CSS 2.1中的伪类
CSS 伪类 是添加到选择器的关键字,指定要选择的元素的特殊状态。例如,:hover
可被用于在用户将鼠标悬停在按钮上时改变按钮的颜色。
/* 所有用户指针悬停的按钮 */
button:hover {
color: blue;
}
伪类连同伪元素一起,他们允许你不仅仅是根据文档 DOM 树中的内容对元素应用样式,而且还允许你根据诸如像导航历史这样的外部因素来应用样式(例如 :visited
),同样的,可以根据内容的状态(例如在一些表单元素上的 :checked
),或者鼠标的位置(例如 :hover
让你知道是否鼠标在一个元素上悬浮)来应用样式。
序号 | 选择器 | 含义 |
---|---|---|
13. | E:first-child | 匹配父元素的第一个子元素 |
14. | E:link | 匹配所有未被点击的链接 |
15. | E:visited | 匹配所有已被点击的链接 |
16. | E:active | 匹配鼠标已经其上按下、还没有释放的E元素 |
17. | E:hover | 匹配鼠标悬停其上的E元素 |
18. | E:focus | 匹配获得当前焦点的E元素 |
19. | E:lang© | 基于元素语言来匹配页面元素。 |
实例:
p:first-child {
font-style:italic; }
input[type=text]:focus {
color:#000; background:#ffe; }
input[type=text]:focus:hover {
background:#fff; }
/* 选取任意的英文(en)段落 */
p:lang(en) {
quotes: '\201C' '\201D' '\2018' '\2019';
}
五、 CSS 2.1中的伪元素
伪元素是一个附加至选择器末的关键词,允许你对被选择元素的特定部分修改样式。下例中的 ::first-line
伪元素可改变段落首行文字的样式。
序号 | 选择器 | 含义 |
---|---|---|
20. | E::first-line | 匹配E元素的第一行 |
21. | E::first-letter | 匹配E元素的第一个字母 |
22. | E::before | 在E元素之前插入生成的内容 |
23. | E::after | 在E元素之后插入生成的内容 |
实例:
p:first-line {
font-weight:bold; color;#600; }
.preamble:first-letter {
font-size:1.5em; font-weight:bold; }
.cbb:before {
content:""; display:block; height:17px; width:18px; background:url(top.png) no-repeat 0 0; margin:0 0 0 -18px; }
a:link:after {
content: " (" attr(href) ") "; }
CSS三大特性
CSS有三个非常重要的三个特性:【层叠性】、【继承性】、【优先级】。
层叠性
CSS全称是Cascading Style Sheets,翻译成中文就是“层叠样式表”,由名字就可以知道层叠性,对于CSS的核心重要性。可以说是CSS在众多样式表中脱颖而出占据今天的地位,层叠性就是重要的一笔。下面我们就来了解一下什么是CSS的层叠性:
层叠性定义:相同的选择器设置了相同的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式。层叠性主要解决样式冲突的问题。
样式冲突:遵循就近原则
实例说明:
<style>
div {
/*第一次定义文本为红色*/
color: red;
font-size: 12px;
}
div {
/*在第二次的定义中就会被覆盖*/
color: pink;
}
</style>
<body>
/*最终文本的颜色为粉红色*/
<div>长江后浪推前浪,前浪死在沙滩上</div>
</body>
案例效果:
继承性
子标签会继承父标签的某些样式,如文本颜色和字号。
实际案例:
<style>
/* 父类样式 */
div {
color: red;
/* font: 文字大小/行高 字体 */
font: 12px/24px 'Microsoft YaHei';
/* 1.5相当于当前元素文字大小的1.5倍 */
font: 12px/1.5 'Microsoft YaHei';
font-size: 14px;
}
</style>
<body>
<div>
<!-- 子类继承 -->
<p>龙生龙,凤生凤</p>
</div>
</body>
案例效果:
优先级(Specificity)
优先级是CSS重要的概念,它决定了在样式被层叠之后应该选择哪一个声明块的属性加入到DOM元素节点当中。引用MDN官方对优先级的定义:
浏览器通过优先级来判断哪一些属性值与一个元素最为相关,从而在该元素上应用这些属性值。优先级是基于不同种类选择器组成的匹配规则。
当同一个元素指定多个选择器,就会有优先级的产生。
-
选择器相同,则执行层叠性。
-
选择器不同,则根据选择器权重执行
选择器 选择器权重 继承 或者 * 0,0,0,0 元素选择器 0,0,0,1 类选择器,伪类选择器 0,0,1,0 ID选择器 0,1,0,0 行内样式style=‘’ ‘’ 1,0,0,0 !important重要的 ∞ 无穷大
当样式写在HTML文档中不同位置的时候效果也会不一样。
他们的顺序如下:行内样式 > 页内样式 > 外部引用样式 > 浏览器默认样式
优先级注意点:
- 权重是由4组数字组成,但不会进位。
- 可以理解为类选择器永远大于元素选择器,id选择器永远大于类选择器,以此类推。
- 等级判断从左向右,如果某一位数值相同,则判断下一位数值。
- 可以简单记忆法:通配符和继承权重为0,标签选择器为1,类/伪类选择器为10,id选择器100,行内样式表为1000,!important无穷大。
- 继承的权重为0,父元素的优先级再高,通过继承传给子元素后优先级为0
总结优先级的关系如下:
- 行内样式 > 页内样式 > 外部引用样式 > 浏览器默认样式
- important > 内联 > ID > 伪类|类 | 属性选择 > 标签 > 伪对象 > 通配符 > 继承
优先级权重叠加
符合选择器会有权重叠加的问题
/* ul li 权重 0,0,0,1 + 0,0,0,1 = 0,0,0,2 */
ul li {
color: green;
}
/* li 权重 0,0,0,1 */
li {
color: red;
}
注意:当样式层叠冲突的时候可以使用权重叠加来解决冲突。
优先级的特殊情况说明
在开发过程中有遇到过添加!important
属性之后不生效的问题,
!important
真的是的无法超越的王者吗?其实不是的,一些情况,我们可以超越 !important
, 可以看看下面的例子:
<style>
.box {
max-width: 100px;
}
</style>
<body>
<div class="box" style="background: #f00;
width: 300px!important;">
我的宽度是多少呢??
<div>
</body>
案例效果【important优先级的特殊情况.html】:
这时候 .box
的宽度只有 100px
, 而不是 300px
, 可见,max-width
可以超越 width!important
!但是,这实际上不是优先级的问题,因为优先级是比较相同属性的,而 max-width
和 width
是两个不同的属性。
CSS流的概念
流作为CSS中的一种基本的定位和布局机制无处不在。它很重要,重要到我们觉得理所应当这样就像1+1=2一样,大家都知道但是却鲜有人证明得当。如果需要做一个比喻来说明什么是CSS世界中的流我认为将HTML元素标签比作一个盛水的容器,将CSS比作容器中的水,而我们在这个容器里的水上面铺设各种各样我们喜欢的小黄鸭,这些比喻都再合适不过,甚至你可以想象在这个布满水的容器里不断填充小黄鸭它会溢出来的画面,这么说来是不是就突然变得简单并且有趣起来了呢?CSS世界构建的基石是HTML,而HTML最具代表的两个基石
通过一个案例来演示流的概念
【页面地址:CSS流概念的解释.html】CSS和HTML代码如下:
<style>
.body {
margin: 0;
padding:0;
box-sizing: border-box;
}
.vat{
/* position: relative; */
margin-top: 300px;
margin-left : 50% ;
transform: translateX(-50%);
width: 400px;
height: 200px;
background: url("./img/vat.png") no-repeat;
background-size: 100%;
overflow:hidden;
}
.duck{
/*除去定位的干扰*/
/* position:absolute;
top: -15px;
left: 120px; */
display: inline-block;
width: 80px;
height: 80px;
background: url("img/duck.png") no-repeat;
background-size: 100%;
}
.mlee {
left: 200px;
}
</style>
<body>
// HTML块级容器元素
<div class="vat">
// 内联级元素
<span class="duck"></span>