我将通过一系列的分享和大家一起从零开始学习CSS。 目标如下:
帮助后端人员巩固和深化CSS相关领域的知识,最终获得不一样的收获。
帮助对风格感兴趣的人从入门到精通再到放弃
帮助自己系统梳理基础知识并查漏补缺
为什么它
我们先看一张旧图
根据阅读习惯,我们从左到右首先看到的是选择器,也就是“主谓宾”中的“主语”。 其重要性和优先级可想而知。 简单理解:选择器是一个定义要应用的样式的对象(组)。 简单来说就是:她(他们)要开始化妆了~那么这些人都包括什么呢?
从问题开始
按照国际惯例,我先问一个问题。 右图是Google主页。 如果你想改变“我很幸运”的按钮图案,有多少种方法可以找到她并改变她?
来吧,直接得到答案!
可以看到css并集选择器,方法确实有很多,而且相对来说,有的方法更准确,有的方法更高效,有的方法使用起来更合理。 至于如何选择,让读者通过下面的介绍得出自己的结论。
入门
选择器有很多种类型。 我们根据不同的用途、书写方式等做一个简单的分类,来定个基调。
ID 选择器:#id
类选择器:.class
标签选择器:html
属性选择器:[type=submit]
通用选择器:*请注意,尽管它*涵盖了基本上所有元素,但它不包括 ::before 和 ::after 伪元素
相交关系(无符号):.ab
并集关系(,):.a,.b
后代关系(空格):.ab
母女关系(>):.a>.b
相邻兄弟 (+):.a+.b
兄弟会(~):.a~.b
列(||):.col||td
:徘徊
:重点
:最后一个孩子
:是
:在哪里
:...
伪类很多,一共60多个,迭代还在减少。 许多伪类非常有用。 如果你觉得自己写的样式很复杂,不妨想想是否可以用伪类来解决。明显的特点:以逗号(:)开头
::前
::后
::第一行
::选择
::……
与伪类相比,伪元素少了很多,但也有15个以上。最常用的是before和after,其特点也很明显:以双引号(::)开头,不'别告诉我有关 IE 的事!
1、从常用选择器来看,基本上都很容易理解和使用。 唯一复杂的是属性选择器。 整理成表格后就一目了然了。
写作意义的描述
[属性]
有这个属性
[disabled] 不可用的元素,Vue的作用域样式隔离是通过拥有属性来实现的
[属性=“值”]
属性全匹配
最常用的一种,属性值相等
[attr~=“val”]
当有多个属性值(空格样式)时,可以匹配其中一个,如可以匹配[name~="a"]。
[attr|="val"]
开始匹配,注意不是模糊匹配
顾名思义,它是从属性开头开始匹配,匹配整个属性或者以“-”分隔的第一部分,如:[name|="a"]匹配、name="ax"、name= “ba-x”[名称| =“a”]不匹配
[attr^="val"]
以val开头的模糊匹配
这个很好理解,就是不匹配,而是从头开始。 例如,[name^="a"] 匹配,name="ab"[name^="a"] 不匹配 name="ba"
[attr$="val"]]
以 val 结尾的模糊匹配
更容易理解。 它被放置在模糊匹配的末尾。
[属性* =“值”]
包含 val 的模糊匹配
Val 可以是属性中的任意位置,例如:a[href^="http"]:not[href*="epay.163.com"] 匹配 Ironforge 链接
上表基本上列出了属性选择器的所有用法。 现在还有一个问题。 属性选择器中的属性值是否区分大小写?
以前有一个i属性用来忽略大小写[attr^="a"i]css并集选择器,实际测试了多个浏览器后发现它基本上不再区分大小写了。 大致可以得出以下推论:
1. ID和类选择器区分大小写
2.标签选择器和属性选择器不区分大小写。
3. 伪类和伪元素不区分大小写
2. 我们来看看选择器。 它的作用是通过一个元素找到它的后代或者兄弟元素。 很容易理解,这里就不再重复了。 你注意到一个问题了吗? 所有选择器都选择后代或以前的兄弟。 没有对应的祖先母亲选择器,也没有姨妈选择器。 为什么是这样?
虽然很简单,但也不是不可能,也不值得去做。 根据DOM的渲染规则,我们遵守自上而下的规则。 如果有祖先选择器,这必然会造成回溯,已经渲染过的元素会再次渲染。 ,影响体验和性能
3. 接下来看伪类别。 有很多伪类别很好用,但不是那么容易记住,所以我们先用一个表格来做一个简单的分类。
名称介绍功能
激活类伪类
(:悬停,:活动,:焦点...)
一些与用户行为相关的伪类
主要用于用户操作时附加样式
位置伪类
(:链接,:访问过,:任何链接,:目标...)
主要是url相关的伪类
主要用来描述链接的状态:
输入伪类
(:启用,:默认:选中,:只读...)
主要是表单类型交互的伪类
与表单交互时,不同情况下表单风格的差异
结构化伪类
(:根,:空,:第一个孩子,第n个孩子...)
主dom树结构关系的伪类
使用它可以直接选择单个特殊元素或根据其他节点选择当前元素。
逻辑组合伪类
(:不是,:是,:哪里,:有)
顾名思义,按关系对元素进行排序
通过逻辑判断条件过滤到元素
其他伪类
(:范围、:主机、:全屏、:目录、:语言...)
功能不同,分开理解
功能不同,分开理解
虽然伪类选择器有很多,而且大多数使用起来并不难,但灵活使用、合理组合往往可以达到很多意想不到的效果。 接下来我会挑选一些比较有趣的来介绍一下。
1. :empty 是一个空元素伪类,它不包含任何内容(空格),也没有子元素。 应该注意的是,单个标签也将被包括在内。 使用场景如下:
防止空元素占用空间:
例如,有些元素没有内容,但由于padding、margin等样式的原因,页面上仍然会存在一些空白。 这种方法是去除它们最方便、最快捷的方法。
默认数据填充:
,这常用于列表查询。 如果有数据,则显示数据,如果没有数据,则显示默认值。 比js或者模板判断更简单、方便。
2. :not 否定伪类,支持链式写法和复杂参数。 主要用于更方便的元素匹配。 同时,与其他选择器一起使用也能产生意想不到的效果,例如
更好的匹配:
这里主要介绍一下用法
选项卡切换:
选项卡切换非常常见。 我们通常使用js来实现,用css来实现会更容易。
3. :is, :where 任意匹配伪类。 之所以将两者放在一起,是因为最终的疗效是相似的。 最大的区别可能是优先级。 is的权重估计是根据参数中的权重最高的就是它的权重,无论参数是什么,最终的权重估计仍然是0(下面会介绍权重估计)。 在我看来,任何匹配的伪类都不是必须的。 它没有实现一些附加功能。 最大、最有用的是精简选择器,如下所示:
此外,它还可以用来突破一些框架的css范围,而不会造成副作用。 具体可以查看文章,里面有更详细的描述。 其实这也是基于框架的“漏洞”而不是框架本身有什么特殊功能。 能力。
4. :has 有一个选择器,可以实现类似于父选择器和兄弟选择器的功能。 哪个! 上面我们已经明确结论,由于性能问题,不会出现父兄选择器,那么这里怎么会弹出父兄伪类选择器呢?
。 Igalia啃下了这块硬骨头,最终通过特定的缓存和过滤优化等中间优化策略解决了性能问题。 相信不久的将来,父兄选择器也会出现。
,使用起来非常简单:
/**给”具有img子元素“的a元素添加样式,注意这里的样式是作用到a标签上的!**/
a:has(img){
}
4.最后我们看一下伪元素。 这里我就不过多介绍了。 不仅 ::before 和 ::after 其他的使用频率较低。
优先事项
介绍完选择器的类型,我们就需要说说选择器最重要的一点:优先级,看右图(估计值越高,优先级越高)
级别定义估计
0级
通配符选择器、选择器和逻辑组合伪类
1级
标签选择器、伪元素
2级
类选择器、属性选择器和伪类
10
3级
ID选择器
100
4级
内联样式属性
1000
5级
!重要的
10000
总的来说,上图的内容是非常清晰的。 通过设置估计值来估计选择器的优先级。 举个反例:
html body #nav .selected > a:hover
最终估计值为:1(html标签)+1(bod标签)+100(ID)+10(类别)+0(选择器)+1(a标签)+10(伪类别)=123
但是,我们可能仍然有一些疑问。 我们来看看以下问题:
Q1:预估值相同时如何确定优先级
A:从后到先,谁先写,谁的优先。
Q2:style和dom级别有什么关系?
答:没关系。 例如,htmldiv{} 和 bodydiv{} 是完全等价的。
Q3:10 个低级选择器可以抵得上 1 个初级选择器吗?
答:完全没有。 目前一个级别的选择器存储在16位空间中,所以如果想要超过上一级的选择器,就必须至少写入2的16次方低级选择器,而我们使用的是这里10次通常就足够了,因为没有人会写超过10个相同级别的选择器。 如果你真的遇到这些可笑的人,你也一定知道,等级是不能跨域的
扩展和延伸
至此,我们是不是已经很清楚选择器的用途和优先级了呢? 不不,还不够,我们看一下@layer,翻译过来就是“层”,对,其实就是层的概念,简单理解,就是给一堆样式套上一层壳,做成一个层,然后聚合这一层 类严格性是唯一可以提高选择器优先级的(另一个是:where)。 概括起来,它有以下几个特点:
我们通过下面的问题来直接了解前面的特点。
/* 最终颜色为blue,遵循后来居上原则 */
@layer {
div {
color: red;
}
}
@layer {
div {
color: blue;
}
}
/* 最终颜色为red*/
@layer B,A;/**可以先定义后赋值,顺序为后来居上 **/
@layer A {
div {
color: red;
}
}
@layer B {
div {
color: blue;
}
}
/* 最终颜色为yellow 优先级为yellow->red->blue 被层级包裹的优先级更低*/
div {
color: yellow;
}
@layer A {
div {
color: red;
}
@layer B {
div {
color: blue;
}
}
}
/* 最终颜色为blue 优先级为blue->yellow->red */
div {
color: yellow;
}
@layer A {
div {
color: red;
}
@layer B {
div {
color: blue !important; /** !import的权柄更重,有了他,可以突破@layer的层级限制 **/
}
}
}
好了,通过前面的几个反例,你应该对@layer的层次结构有了一定的了解。 这些风格的优先级在这里完全清楚吗? ,我们来看下面的例子
/* 优先级为blue->red->yellow 为什么?*/
.test {
color: red !important;
}
div {
color: yellow !important;
}
@layer A {
div {
color: blue !important;
}
}
你对这个结果感到困惑吗?
由于!import确实有点不正常,看一张图就更清楚了:
我们先解释一下图中的术语:
UA:浏览器默认样式。 只要我们把它放在代码后面,浏览器就会加载默认的样式,通常是一些按惯例也叫的样式,比如给div添加一个display:block
site:作者风格,也就是我们写的css代码
local:用户风格。 浏览器允许用户通过配置加载一些样式表,使用频率很低。可以理解为多样化的浏览器默认样式
好吧,回头看,样式的优先级很明确,作者>用户>浏览器,而一旦加上!import,顺序就完全颠倒了,单独列出了@layer层。 site@layer!import 的优先级低于 site!important,因此上述问题中蓝色的优先级最高。 与红黄色处于同一级别(站点),因此根据权重估计值来判断。 很明显类(.test)低于标签(div),所以红色的优先级低于黄色
最后附上一张大墨老师比较完整的照片。
最佳推荐
根据前面的分析,总结了几种与选择器相关的推荐写法。
虽然,其中的那些点并不是那么重要。 如今随着浏览器的功能越来越强大,通常的性能问题和代码大小问题显然已经不再是我们迫切关心的问题了。 书写准确,阅读清晰。 在我看来,这是最重要的。
综上所述
看来我们从来没有考虑过兼容性。 有很多兼容性不是特别好,比如上面提到的@layer。
但这并不能成为我们不学习、不使用的理由。 相信随着浏览器的迭代更新,越来越多有趣的css功能将会得到全面支持。 我们要做的就是与时俱进,让我们的代码更加高贵,更加令人印象深刻。
- 结尾 -
点击下方公众号入口,关注“技术对话”微信公众号,查看历史文章。 投稿请在公众号后台回复:提交