百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

CSS的众多小技巧之选择器:你还在为样式不生效而感到苦恼吗?

toyiye 2024-06-23 18:55 11 浏览 0 评论

我写的样式老不生效啊,怎么办呢?要不来个important吧!反正催得急,先上线再说,有五个属性都要修改,但是都被覆盖了,emmm,那就加五个important吧。改到最后项目中随处都可见important的身影,当你或者其他人在为此抓狂的时候,它躲在一旁邪魅的一笑:就喜欢你看不惯我又干不掉我的样子!

还有一种情况就是,不知道怎么选中需要设置样式的元素,所以就不断的加类名,费劲脑筋去想各种各样名称,又要见名知意,又要各有不同,因此五花八门越来越多的类名,搞得多人维护的项目变得越来越头大,甚至让人抓狂。

下面我们就来搞一搞,看看选择器有哪些好玩的地方。

优先级概念解析

一共大致分为五个等级:

  1. 内联样式:权重为(1,0,0,0)
  2. id选择器:权重为(0,1,0,0)。
  3. 类、伪类、属性选择器:权重为(0,0,1,0)。
  4. 标签、伪元素选择器:权重为(0,0,0,1)。
  5. 通用、子、相邻选择器:权重为(0,0,0,0)。

还有三个特殊的规则:!important、继承和默认代理样式。其中!important权重为无穷大。

他们之间的默认优先级顺序为:!important > 行内样式 > id选择器 > 类选择器 > 标签选择器 > 通用选择器 > 继承 > 代理(浏览器)默认属性。

样式生效的规则符合以下几点:

  1. 两个选择器权重不同时,权重搞得优先生效。
  2. 两个选择器权重相同时,后定义的优先生效(即层叠样式表的特性,后面定义的会覆盖前面定义的)
  3. 被!important修饰的属性,会无条件的优先生效。

这里面还有几个需要注意的点:

  1. 所有权重中的0和1代表的是标识位,如内联样式的(1,0,0,0)代表第一等级标识位为1,并不是代表内联样式权重为1000,同样id选择器(0,1,0,0)代表第二个标识位为1,并不代表内联权重为100。也就是说#container {color: red}具有第二级权重。
  2. 同一权重等级下的选择器才可以累加,低等级权重的选择器永远不会超过高等级的选择器,如#a.b.c的优先级比#a.d的优先级要高,因为它们虽然都拥有第二等级权重,但是#a.b.c比#a.b多了一个第三等级的权重,而#a的优先级永远比.b.c(可以有任意多个低于第二等级权重的选择器)高,因为在进行权重比较的时候,是从高到低逐级比较的,#a选择器为第二等级,那么.b.c没有第二等级权重,即使有再多的第三级权重都没用。
  3. !important选择器虽然权重为无穷大,但是与数学中无穷大的比较不同,两个!important权重是可以进行比较的,两个同时拥有!important属性的选择器,也符合上面的比较规则,如#a中的!important要比.b中的!important优先级高。

权重逐级比较公式:(第一等级权重*该选择器个数,第二等级权重*该选择器个数,第三等级权重*该选择器个数,第四等级权重*该选择器个数,第五等级权重*该选择器个数)

会逐个标识位进行比较,并不是进行简单的加法运算。

写了这么长的文字,可是实在找不到可以插入一张图片的地方。总感觉思路会被打断。现在可以休息一下,稍后再往下看。

选择器类型解析

假设你已经对各种类型的选择器有所了解,知道了什么是类选择器、什么是内联样式、什么是标签选择器等。

接下来我们讨论一下几种组合选择器:(示例中都是用类名或标签作为选择器,因此为了简便,对于.a1这种的选择器,在表达的时候直接用a1来表示拥有类名a1的元素)

① *:这里先要介绍一下通用选择器,* {}选择器将会覆盖所有元素的代理默认样式,也可以用div.container * {}来指定对类名为container的div元素下的所有子孙元素应用样式。

② .a1 > .b1:表示给a1的子元素b1应用样式。只能是子元素,不包括孙子元素。

<style>
  .a1 > .b1{
    color: red;
  }
</style>
<ul class="a1">
  <li class="b1">1</li>
  <li>
      <span class="b1">2</span>
  </li>
</ul>

③ .b1 + .b2:表示给b1后面的紧跟着的b2应用样式。

<style>
  .b1 + .b2{
    color: red;
  }
</style>
<ul class="a1">
  <li class="b1">1</li>
  <li class="b2">2</li>
  <li class="b2">3</li>
</ul>

④ .b1 ~ .b2:表示给b1后面的b2应用样式。不用紧跟。

<style>
  .b1 ~ .b2{
    color: red;
  }
</style>
<ul class="a1">
  <li class="b1">1</li>
  <li class="b2">2</li>
  <li class="b2">3</li>
</ul>

⑤ li:first-child:表示给li应用样式,但是li必须是属于其父元素的第一个子元素。li:last-child与其类似,但是li必须是属于其父元素的最后一个子元素,不再给出示例。

<style>
  li:first-child{
    color: red;
  }
</style>
<ul>
  <li>1</li>
  <li>2</li>
  </ul>
  <ul>
    <li>3</li>
  <li>4</li>
</ul>

⑥ span:first-of-type:表示给span应用样式,其中只要span属于其父元素的所有子元素中的第一个span即可,即span前面的兄弟元素再没有其他的span,则应用样式。span:last-of-type与其类似,只是span后面的兄弟元素再没有其他的span,则应用样式,不再给出示例。

<style>
  span:first-of-type{
    color: red;
  }
</style>
<div>
  <span>1</span>
  <p>2</p>
  </div>
  <div>
    <p>3</p>
  <span>4</span>
</div>

(Tips:first-child与first-of-type不同的地方在于,first-child必须是作为第一个子元素,而first-of-type是作为同一种类型中的第一个,他们都可修饰多个选择器,如.a.b:first-child。last-child和last-of-type同理。)

⑦ .b:not(li):表示给b应用样式,但是li除外。

<style>
  .b:not(li) {
    color: red;
  }
li:not(.a) {
  color: red;
}
</style>
<ul>
  <li class="a">1</li>
  <li class="b">2</li>
  </ul>
  <div>
    <div class="a">3</div>
  <div class="b">4</div>
</div>

⑧ li:nth-child(order):表示给li应用样式,但是li必须是属于其父元素的第order个子元素。li:nth-last-child(order)与其类似,但是li必须是属于其父元素的倒数第order个子元素,不再给出示例。

li:nth-child(2) {
  color: red;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

这里还有一个小技巧,比如我想要选择前五个li,能做到吗?当然可以。请看代码。

<style>
  li:nth-child(-n + 5) {
    color: red;
  }
</style>
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
</ul>

这是因为除了可以指定order之外,还可以指定一个迭代序列n(从0开始),ul有8个li子元素,所以n可以取0,1,2,3,4,5,6,7,所以-n + 5可取出5,4,3,2,1,0,-1,-2,舍去负数,那么就是选中了1,2,3,4,5也就是前五个元素,注意这里只能写成-n + 5的形式,而不能写成5 - n的形式。

同样,它还有几种表达方式:(由于html部分与上面相同,不再重复列出)

<style>
  /* 选择第五个li元素,以及后面的所有li */
  li:nth-child(n + 5) {
    color: red;
  }
</style>

n+一个数字,表示这个数字以及之后的元素应用样式,-n+一个数字,表示这个数字以及之前的元素应用样式。

/* 以2的倍数选择li元素 */
li:nth-child(2n) {
  color: red;
}

注意这里只能写成2n的形式,不能是2 * n或n * 2。

<style>
  /* 以2的倍数加1选择li元素 */
  /* n从0开始 */
  li:nth-child(2n + 1) {
    color: red;
  }
</style>

⑨ li:nth-of-type(order):只在li类型中查找符合条件的来应用样式,与nth-child一样,只不过加了个类型区分。li:nth-last-of-type(order)与其类似,但是li必须是属于其父元素的倒数第order个子元素,不再给出示例。

<style>
  /* 按照同类型查找,不会受div影响 */
  li:nth-of-type(2n) {
    color: red;
  }
</style>
<ul>
  <li>1</li>
  <li>2</li>
  <div>9</div>
  <div>10</div>
  <li>3</li>
  <div>11</div>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
</ul>

它们同样可以指定一个迭代序列n,与上面相同,故在此不做示例。

⑩ .a:only-of-type:表示给a应用样式,但是a的标签类型必须在其父元素中唯一。

<style>
  /* 注意:type指的是标签名要唯一才会生效 */
  .a:only-of-type {
    color: red;
  }
</style>
<div>
  <div class="a">1</div>
  <span>2</span>
  <p>3</p>
</div>
<div>
  <div class="a">1</div>
  <span>2</span>
  <p class="a">3</p>
  <!-- 如果去掉下面这一行,那么第一行的1也会变颜色 -->
  <div class="a">4</div>
</div>

哇!终于大概都讲完了。由于选择器太多了,篇幅有限,不能一一列举,其他的伪类、伪元素、属性选择器等,大家直接可以去官网查阅就可以了,都是基础的内容。

局部作用域

在vue中,由于组件化的概念,我们希望当前的样式只能当前文件中生效,不要影响全局的样式,因此可以给style标签设置scoped属性。这里有一套机制来保证每个组件间的样式是处于隔离状态的,不会互相影响,不但兄弟组件如此,父子组件也可以这样。

这样是很好的,为我们带来了便利,并且不用为同名的问题所困扰,但是有一种情况是:当我们引用子组件的时候,想要修改它里面的样式,这个时候正常的选择器是无法生效的,我们无法选择到子组件里面的元素。

这是因为每一个组件都是独立样式作用域,它用一个唯一标识来区分,在父组件中写的样式,会自动在选择器的最后面加上这个唯一标识,而子组件中有自己的另一个唯一标识,所以会选择不到该元素。

这个时候我们可以使用一个叫做深度选择器的功能来帮助我们解决这个问题。

用>>>来表示,你也可以使用/deep/或者::v-deep,都代表相同的含义,只不过是写法不同,一个别名而已。

<style scoped lang="scss">
  .a >>> .b {
    color: red;
  }
</style>

经典案例

我们以下面这段html片段为例。

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
</ul>

区间选择:我们可以指定一个区间来选择指定的元素。

<style>  
	/* 选择2到5之间的 */
  li:nth-child(n + 2):nth-child(-n + 5) {
    color: red;
  }
</style>
<style>
  /* 选择4以及之后的,但必须是2的倍数 */
  li:nth-child(n + 4):nth-child(2n) {
    color: red;
  }
</style>
<style>
  /* 选择3的倍数之外的 */
  li:not(:nth-child(3n)) {
    color: red;
  }
</style>

伪类选择:我们可以通过伪类来做一些事情。

<style>
  span {
    cursor: pointer;
  }
  span + span {
    display: none;
  }
  span:hover + span {
    display: inline;
  }
</style>
<div>
  <span>查看识别码</span>
	<span>5201314</span>
</div>

题外话

说几句题外话,虽然不是选择器的内容,但是也跟它有关系,主要有以下几个方面:

  1. 我们在修改元素样式的时候,尽量先预设好选择器的样式,然后通过动态增加或移除相应的类名来达到效果,而不是直接设置style。
  2. 应该尽量避免使用id选择器,最好都通过标签、类名、属性选择器来操作样式。因为id选择器权重大,有时候覆盖起来不方便。而且id只能存在一个。再有一个就是id选择器会比类选择器给浏览器带来更大的负担。
  3. 尽量少使用!important,多通过上面讲述的权重规则来设定相应的样式。
  4. 尽量少用通用选择器,即通配符*,也会给浏览器增加负担。

总的来说

CSS选择器在我们实际开发工作当中不但是不可缺少的一部分,而且几乎时时刻刻都要与之打交道,熟练掌握他们的用法和原理,能够使我们在操作元素样式的时候得心应手,今天内容你学会了吗?[比心]

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码