做为程序员,技术的落实与巩固是必要的,所以想到写个系列,名为 why what or how
每篇文章试图解释清楚一个问题。css
why what or how
的第二章,什么是 CSS
?html
CSS
- Cascading Style Sheets
,层叠样式表程序员
CSS
也算是一种标记语言,其内容做为浏览器的输入,浏览器会解析其文本内容,做为 HTML
附加的样式信息,用以修饰标签。bootstrap
标记语言,一类以固定的形式描述文档结构或是数据处理细节的语言,通常为纯文本形式,其内容做为其余程序的输入。数组
样式表你们都很清楚,记录样式信息的表格,以键值对的形式存在,格式以下浏览器
p {
font-size: 10px;
}
复制代码
那么何为层叠呢?层叠的意义是什么?sass
层叠,字面意思:层层叠加,咱们知道 HTML
的页面结构是树状的,不一样标签的层级嵌套最终组合造成了页面,那么从另外一个角度来看,页面的结构就是一层一层的,以下图所示bash
html
为最底层,body
位于 html
层之上,header
、nav
、article
、aside
、footer
这些标签位于 body
之上,section
位于 article
之上,标签的堆叠就造成了网页结构,那么这关 CSS
什么事?less
先抛出一个问题:若是说 article
标签表明一篇文章,那么其内部的文字大小,样式,排版是否是应该一致?ide
是!那么样式进行层叠的意义也在于此,只要我给 article
标签固定的样式,那么 article
内部的标签就会(部分)继承这个默认的样式信息,层级结构表明了节点间的关系,那么就有了父子级的区别,也就有了继承的关系。
那有的朋友就会问了?如今的 CSS
不就是这样的吗?这不是默认的行为?
CSS
确实如此,但刚开始为 HTML
进行修饰的样式规则却并不是如此,CSS
只是在众多规则中,最终成为标准的那一个。
1991 - 1993
年,各类浏览器相继出现,但每一个都实现了本身制定样式规则,网页呈现由用户控制,样式没有统一的规定。1993
年,Mosaic
浏览器采用增长新种类的 HTML
标签实现样式的表达,以知足设计师的要求,<FONT></FONT>
之类表明样式的标签开始出现。1994
年,Håkon W Lie
提出层叠 HTML
样式表(Cascading HTML Style Sheets
),CSS
的雏形出现。1995
年,W3C
创建,W3C
对 CSS
很感兴趣,为此专门组织了一次讨论会。1996
年,CSS
语法完成,发布了 CSS1.0
,但因为当时主流的浏览器并不支持(每家都有本身的样式写法),而且当时主流的方式为 HTML
的样式标签,所以 CSS
等几年后才流行起来。1997
年,W3C
组织了专门管 CSS
的工做组。1998
年,浏览器市场份额被微软公司的 IE4
和网景公司的 Netscape Navigator
两大浏览器巨头所占据。IE4
率先实现了 CSS 1.0
但因为不重视,致使规范实现不完善,bug
不少。因为不一样浏览器支持的标准不一致,网页设计人员不得不为 IE
和 Netscape Navigator
分别设计一套网页。民间设计人员团体 网页标准计划(WaSP)
发动水军将 W3C
的建议宣扬为标准,并批评还未加盟 W3C
标准的业界厂商。1998
年,W3C
组织出版 CSS2.0
网页标准计划的 7
位成员成立了 CSS武士团(CSS Samurai)
,指出 Opera
浏览器和 IE
浏览器在支持 CSS
方面存在的诸多问题。Opera
公司着手解决了问题,但微软并未解决。他们同时也劝说其余浏览器开始支持 CSS
标准。1999
年,W3C
开始制定 CSS3
标准。2003
年,Dave Shea
推出了一个名为 CSS禅意花园("CSS Zen Garden")
的站点,向人们展现出仅经过应用不一样页面样式规则,就能够实现对网页艺术风格的面目一新。2006 - 2009
年, DIV+CSS
布局逐步取代缺少灵活性的传统表格布局,无表格网页设计成为网页内容布局的主流方案。2009 - 至今
,CSS3
标准已部分公布,但仍未所有制订完毕,浏览器厂商也逐步跟进,W3C
官方将这些不一样的特性分门别类,称为 modules
,不在沿用 CSS3.0
的版本号,而是将单独的 module
分别命名,每一个 module
也有不一样的版本号。CSS
从标准制定,到最终有浏览器开始实现,至少间隔了 5
年的时间,而 CSS
的上位也由民间组织推进,到浏览器厂商最终采纳。直到目前,咱们还能在 HTML
中使用相似 <FONT></FONT>
之类表明样式的标签,也是历史遗留下来的产物,但 HTML5
的推出,规范了 HTML
标签是做为网页的结构,CSS
做为网页的样式信息,所以那些表明样式的标签已经被规范所移除,咱们也应该少用甚至不用。
CSS
在众多的样式规则中脱颖而出,其实和 IE4
的成功有这很大的关系,IE
系列最早实现了 CSS1.0
标准,能够说是在与 Netscape Navigator
战争中胜利的因素之一,甚至不少的 CSS3
属性背后也有着 IE
的影子,但后来 IE
系列的落寞很大程度上是由于它的不做为。
一条 CSS
规则的结构以下:
┌─────── 选择规则 ──────┐ ┌────────── 声明块 ──────────┐
p + p > span:first-child {
┌────── CSS 属性 ───────┐
font-size : 10px ;
└─ 属性名 ─┘ └─ 属性值 ─┘
}
复制代码
由两部分组成,选择器与声明块。
HTML
中符合要求的标签一条选择规则有两部分组成,选择器与链接符,上面例子中,p
、span
、:first-child
属于选择器,而 +
、>
这些符号属于链接符。
一个声明块由多条 CSS
属性组成,属性分为两部分,属性名与属性值,以 :
分隔,以 ;
结尾,一条属性规定了标签的一个样式。
选择规则,意如其名,用于选择 HMTL
文档中的标签,那么如何进行选择的呢?选择规则分为两部分,咱们分开介绍
选择器用于选择 HMTL
页面中存在的标签。选择器分为几大类,以下:
选择器类型 | 含义 |
---|---|
元素选择器(elementname ) |
选择对应标签 |
类选择器(.classname ) |
选取具备对应类名的标签 |
ID 选择器(#idname ) |
选取具备对应 ID 的标签 |
通配选择器(* ) |
选取全部标签 |
属性选择器([属性名=值] ) |
选取有相应规则属性的标签 |
伪类选择器 | 选取伪类规定的标签 |
属性选择器有多种写法,以下:
写法 | 含义 |
---|---|
[attr] |
选取带 attr 属性的标签 |
[attr=value] |
选取 attr 属性值为 value 的标签 |
[attr~=value] |
选取 attr 属性中有 value 单词(单词不与其余字母相连)存在的标签 |
[attr|=value] |
选取 attr 属性为 value 或以 value- 开头的标签 |
[attr^=value] |
选取 attr 属性以 value 开头的标签 |
[attr$=value] |
选取 attr 属性以 value 结尾的标签 |
[attr*=value] |
选取 attr 属性中含有 value 的标签 |
注: 属性选择器写法,如 [attr=value]
其后均可以跟 i
,好比 [attr=value i]
表明在匹配时,忽略 value
的大小写。
经常使用伪类,以下
写法 | 含义 |
---|---|
:active |
选中被用户激活的标签 |
:hover |
选中被鼠标悬浮的标签 |
:visited |
选中已访问过的连接 |
:focus |
选中获取到焦点的标签 |
:first-child |
选中一组兄弟标签中的第一个标签 |
:last-child |
选中一组兄弟标签中的最后一个标签 |
:first-of-type |
选中一组兄弟标签中其类型的第一个标签 |
:last-of-type |
选中一组兄弟标签中其类型的最后一个标签 |
:not(X) |
选中不被 X 选择器选中的全部标签 |
:nth-child(an+b) |
a b 为固定值,n 为任意天然数,选中一组兄弟标签中第 an+b 个元素 |
:nth-last-child(an+b) |
同上规则,从后往前匹配 |
:nth-of-type(an+b) |
同上规则,从前日后找,匹配相同类型的标签 |
:nth-last-of-type(an+b) |
同上规则,从后往前匹配 |
:only-child |
若是父标签中只有一个子元素则选中该子标签 |
:only-of-type |
若是父标签中只有一个该类型的子元素则选中该子标签 |
链接符规定了选择器该如何进行组合,为了方便解释,我会将符号取一个名字,最终的选择规则表明的含义只需按顺序从前日后读便可。
符号 | 名字 | 含义 |
---|---|---|
'' (无) |
而且 | 选择器叠加 |
',' |
或者 | 选择器共用 |
' ' (空格) |
内 | 后代选择 |
'>' |
内第一级 | 子元素选择 |
'+' |
以后的第一个 | 相邻兄弟选择 |
'~' |
以后的全部 | 兄弟选择 |
给几个例子
p.class1
p,div
p .class1
p > .class1
p + .class1
p ~ .class1
咱们顺起来念:
p
而且带有 class1
类名的标签。p
标签或者 div
标签。p
标签内的带有 class
类名的标签。p
标签内第一级带有 class
类名的标签。p
标签以后的第一个带有 class
类名的标签。p
标签以后的全部带有 class
类名的标签。针对于复杂的选择规则的编写,好比在 bootstrap
中有这样一段:
.btn-group > .btn-group:not(:first-child):not(:last-of-type) > .btn {
border-radius: 0;
}
复制代码
表明的意义是什么呢?
按照顺序念:选中带有 btn-group
类名标签内第一级带有 btn-group
类名而且不是第一个子元素而且不是最后一个子元素标签内第一级带有 btn
类名的标签。
对应的 html
以下:
<span class="btn-group">
<span class="btn">按钮1</span>
<span class="btn-group">
<span class="btn">按钮2</span>
<span class="btn">按钮3</span>
<span class="btn">按钮4</span>
</span>
<span class="btn">按钮5</span>
</span>
复制代码
选中的标签为按钮2/3/4。
咱们从该条规则的意义来理解这条规则:btn-group
中的 btn-group
下的 btn
不该该有圆角(在中间时)。由于正常的按钮都是带圆角的,而放在按钮组中的按钮其实只要左右两边的按钮带上圆角就好,这时候就须要经过特殊的手段来吧这些要去除圆角的元素给选择,并去掉圆角。
接着咱们在看咱们翻译出来的内容,是否是不那么绕了呢?
最后在提一段 bootstrap
中的样式规则,你们一块儿翻译翻译吧
.btn-group > .btn-group:last-of-type:not(:first-child) > .btn:first-child {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
复制代码
选择器的内容到此为止,接下来就要谈谈声明块中的 CSS
属性了。
CSS 中样式分不少种,按照样式效果进行区别,大体能够分为以下几类
大类 | 做用 | 表明属性 |
---|---|---|
字体 | 控制字体的显示效果 | font-* color text-transform text-decoration text-shadow |
文字排版 | 控制文字的排版 | text-align text-align-last text-indent text-overflow line-height word-spacing letter-spacing |
背景 | 控制元素背景显示 | background-* |
布局 | 控制元素的布局行为 | flex 系列属性 grid 系列属性 |
文档流相关 | 控制元素在文档流中的位置 | position top left bottom right z-index float clear |
列表 | 控制列表的行为 | list-* |
盒模型 | 控制元素大小 | width height padding border margin box-sizing |
动画 & 过渡 | 控制元素动画 | transition-* transform animation-* @keyframes |
该篇仅介绍 CSS
是什么,而不解释 CSS
有什么,因此不过于深究这些属性的具体内容,能够经过查看 CSS参考来了解。
开篇咱们就提到了,CSS
为层叠样式表,层叠表明的意思为属性的继承。
这个继承能够简单的总结为一句话:
父级标签的字体样式和文章排版样式会被子标签所继承,也就是说子标签不用写这些属性,就拥有了这些属性。
CSS
中有几个特殊的属性值,须要特别关注一下:
unset
- 若是该属性为继承属性则使用继承值,不是则使用浏览器默认值initial
- 使用初始化的值,也就是浏览器默认值inherit
- 使用继承值因为相同的标签能够由不一样的选择规则所选中,那么这时候就出现了一个状况,若是有多个选择规则同时选中了同一个元素,而且同时设置了相同属性,那么标签最终是要按照哪条规则定义的属性来显示?
不一样
CSS
规则对同一个标签设置了相同属性,CSS
选择规则权重最高的规则会覆盖权重低的样式设置。
何为权重,通过上面的介绍,CSS
设置标签的样式有以下几种
从上到下,选择器的权重依次递减,就像是一样是一张纸币,100
的纸币表明的比 10
块的纸币大,可是与纸币不一样的是,权重高的永远比权重低的优先级要高,无论低权重的选择器有几个。
除去 style
的方式咱们用一个数组来表明选择规则的权重。
[0, 0, 0, 0, 0]
复制代码
从左到右为:ID 选择器
、类名选择器
、伪类
、标签选择器
、通配符
,数组的初始值全为 0
,咱们能够变看选择规则来肯定最终数组,好比那个很复杂的 btn
选择:
.btn-group > .btn-group:not(:first-child):not(:last-of-type) > .btn {
border-radius: 0;
}
复制代码
从左到右,每出现一个选择器,就将对应的数组内的数组加一,那么上条规则最终的数组以下:
[0, 3, 2, 0, 0]
复制代码
这时,有的朋友可能会问了,伪类选择有 4
个啊,怎么是 2
?这里须要注意的是::not
伪类仅带有取反的意思,并不增长权重。
那么权重该如何比较?
简单的来讲,从前日后比,谁比谁先大,谁的权重高。相信写一段比较程序你们就了解了:
function compare(weight1, weight2){
for(let i = 0; i < 5; i++){
if(weight1[i] !== weight2[i]){
if(weight1[i] > weight2[i]){
console.log('参一权重大');
}else{
console.log('参二权重大');
}
return;
}
}
}
复制代码
那么 style
所规定的样式权重如何?
style
样式所规定的权重,比ID 选择器
的权重还要高。
那么咱们想要在 CSS
文件中修改 style
所规定的样式该怎么办?
使用
!important
修饰特定的样便可。以下所示
p {
color: red !important;
}
复制代码
那么 p
标签的字体颜色即为红色,即便设置了 style
也没用。
总结一下:权重等级由高到低为:!important > style > 选择规则。就像是老大哥说东小弟不敢说西,权重也是绝对服从上一级的。
所以为了不出现尴尬的情况,请慎重使用 !important
。
CSS
发展到如今,人们发现 CSS
虽然含有层叠的含义,可是写法倒是一维的,就好比文档结构以下的一个网页:
<article>
<p>这是一段文字</p>
</article>
复制代码
咱们要在 article
,p
标签上设置样式,看起来是这样的:
article {
font-size: 14px;
}
article p {
color: red;
}
复制代码
因为样式规则按照一条一条的形式进行编写,看起开就是一维,标签的层级结构不能在其中体现,若是这样写那就行了:
article {
font-size: 14px;
p {
color: red;
}
}
复制代码
从样式编写上就说明了层级结构,p
标签所继承的样式明了,可是浏览器又仅能识别一维的样式编写,那该如何让浏览器认识该结构呢?
预编译器因运而生,经常使用的 css
预编译器有:sass
、less
、stylus
等,这些预编译器须要特定的语法,但都支持二维的写法。
那么这些个预编译干了什么?
很简单的一句话,将符合预编译器语法的文件转化为
css
文件。
一样的这些预编译器的语法,这里不过多介绍,提供几个网站供你们查阅:
我是在 2019
年写下这篇文章,为什么要特意的声明时间,是由于一个东西的出现:CSS Modules
,咱们须要好好来了解了解。
何为 CSS Modules
,官方解释以下:
CSS files in which all class names and animation names are scoped locally by default.
翻译过来就是:
CSS 的类名和动画名字都在一个命名空间下。
不懂?写个例子。
如下为伪源码:
// test.css
.box{
color:red;
}
复制代码
import style from 'test.css'
function Test(){
return (<div class={style.box} />)
}
复制代码
如下为伪输出:
<div class="_styles__box_34682763478"></div>
复制代码
_styles__box_34682763478
就是在加了命名空间后的类名,这样构建出的代码就不会出现相同类名被覆盖的问题。
总的来讲,
CSS Modules
作了一件时,混淆了class
类名、id
和动画名。
这时就有一些开发站出来讲,这个东西好啊,我不再用去想类名该如何取才能不致使冲突了。冷静下来先考虑这几个问题:
JavaScript DOM API
?若是是,那么经过样式名选取变的不可靠。CSS Modules
后项目中是否出现了极多的 :global
若是是,那要仔细思考下,不用 CSS Modules
成本是否更低?如下是问题对应的一些场景
问题一:你引用了团队中其余人写的组件,但须要你本身修改(覆盖)一些样式,而其余人也是用 CSS Modules
编写样式,所以他的类名是不固定的,你该如何去覆盖这个组件中标签的样式?
CSS Modules
的意义在于哪?问题三四:当你程序须要使用 DOM API
但经过 CSS Modules
生成的样式名会随着文件的位置或内容改变,这样程序就变得不可靠,固然这个问题有办法解决
js
中也用 CSS Modules
的命名,只不过调试变得些许困难js
中使用的样式名与 CSS Modules
进行区分,js
和 CSS Modules
使用两套样式单独的样式那么接下来讲说个人使用体验,或者说我以为好的使用体验
CSS Modules
和原始的 CSS
一同使用。CSS Modules
仅使用在组件内部,项目中依然使用公共样式。CSS Modules
仅使用在一些与结构无关的但又很差命名的标签上,这些标签通常也不会被 js
所选择。CSS Modules
混淆采用和文件位置相关的命名空间产生方式,而不根据文件内容。CSS Modules
,经过项目规定的命名空间在原始 CSS
文件中定义。UI
库或公共组件,不用 CSS Modules
。总的来讲就是一个原则,CSS Modules
用在非共用,无所谓命名以及非跨组件通用的标签上,这些标签能够认为是组件的内部状态,不会被外部影响或修改。
也不知道多年之后 CSS Modules
是否真的解决了编译慢的问题(至少个人电脑上是),CSS Modules
原理上还是传统的 CSS
编写方式,只不过它混淆了名称,并添加了映射,可是之后的发展会如何呢?我不知道,但我会持续的关注它。
惯例以问句开篇,用问句来结尾
CSS
的层叠体如今哪?CSS
选择规则分为那两部分,每部分都如何组成?CSS Modules
是什么?CSS Modules
的见解吧。最后,其实本篇还想谈谈布局和文档流的内容,但篇幅过长,也涉及到了 HTML
,因此就打算将布局单独出来,之后会有如何进行网页布局的单篇,已经记录,但愿你们持续关注。
该系列全部问题由 minimo
提出,爱你哟~~~