深入了解CSS中的选择器

本篇文章带大家了解一下css中的选择器,介绍一下简单选择器、复合选择器、复杂选择器的语法,选择器优先级。

深入了解CSS中的选择器

选择器语法

我们先了解一下选择器的语法,然后深入了解背后相关的特性。

简单选择器

星号 —— *  通用选择器,可以选择任何的元素类型选择器|type selector —— div svg|a  也叫做 type selector, 也就是说它选择的是元素中的 tagName (标签名) 属性tagName 也是我们平常最常用的的选择器但是因为 HTML 也是有命名空间的,它主要有三个:HTMLSVGMathML如果我们想选 SVG 或者 MathML 里面特定的元素,我们就必须要用到单竖线 | ,CSS选择器里面单竖线是一个命名空间的分隔符,而HTML 里面命名空间分隔符是 冒号 : 。然后前面说到的命名空间是需要 @namespace 来声明的,他们是配合使用的,但是这个命名空间的使用不是很频繁,它的存在只是为了一个完备性考虑,HTML 和 SVG当中唯一一个重叠的元素名就只有一个 a所以我们可以认为,类型选择器就是一个简单的文本字符串即可类选择器|class selector —— .class-name  以 . 开头的选择器就是 class 选择器,也是最经典之一它会选择一个 class,我们也可以用空格做分隔符来制定多个 class 的这个 .class 只要匹配中其中一个就可以了ID 选择器|id selector —— #id  以 # 开头加上 ID 名选中一个 ID这个是严格匹配的ID 里面是可以加减号或者是其他符号的属性选择器|attribute selector —— [attr=value]  它包括了 class 属性选择器和 id 选择器这个选择器的完整语法就是 attr=value,等于前面是属性名,后面是属性值这里面的等号前面可以加 就表示像 class 一样,可以支持拿空格分隔的值的序列:attr~=value如果在等号前面加单竖线,表示这个属性以这个值开头即可:attr|=value如果我们对优先级没有特殊要求的话,我们理论上是可以用属性选择器来代替 class 选择器和 id 选择器的伪类 —— :hover  以 : 开头的,它主要是一些属性的特殊状态这个跟我们写的 HTML 没有关系,多半来自于交互和效果一些伪类选择器是带有函数的伪类选择器,这些我们都是可以去使用伪类来解决的伪元素选择器 —— ::before  一般来说是以 :: 双冒号开头的实际上是支持使用单冒号的,但是我们提倡双冒号这个写法因为我们可以一眼就看出这个是伪元素选择器,和伪类区分开来伪元素属于选中一些原本不存在的元素如果我们不选择它们,这个地方就不存在这个元素了,选择后就会多了一个元素

复合选择器

立即学习“前端免费学习笔记(深入)”;

* 或则 div 必须写在最前面

首先复合选择器是以多个简单选择器构成的,只要把简单选择器挨着写就变成一个复合选择器了。它的语义就是我们选中的元素必须同时 match 几个简单选择器,形成了 “与” 的关系。

复杂选择器

复合选择器中间用连接符就可以变成复杂选择器了,复杂选择器是针对一个元素的结构来进行选择的。

—— 子孙选择器,单个元素必须要有空格左边的一个父级节点或者祖先节点 “>” —— 父子选择器,必须是元素直接的上级父元素 “~” —— 邻接关系选择器 “+” —— 邻接关系选择器 “||” —— 双竖线是 Selector Level 4 才有的,当我们做表格的时候可以选中每一个列

选择器优先级

在之前的 《实战中学习浏览器工作原理》中也接触过选择器的优先级的概念了。这里我们深入了解一下选择器优先级的概念。

简单选择器计数

我们从一个案例出发,选择器优先级是对一个选择器里面包含的所有简单选择器进行计数。所以选择器列表不被视为一个完整的选择器(也就是逗号分隔的选择器),因为选择器列表中间是以逗号分隔开的复杂选择器来进行简单选择器计数的。

例子:#id div.a#id

这个里面包含了两个 ID 选择器,一个类型选择器和一个 class 选择器根据一个 specificity 数组的计数 [inline-style个数,ID 选择器个数,class 选择器个数,tagName 选择器个数]我们这个例子就会得出 specificity = [0, 2, 1, 1]在选择器的标准里面,有一个这样的描述,我们会采用一个 N 进制来表示选择器优先级所以 1.png我们只需要取一个大的 N,算出来就是选择器的优先级了比如说我们用  N=1000000,那么 S=2000001000001,这个就是这个例子中选择器的 specificity 优先级了

像 IE 的老版本 IE6,因为为了节省内存 N 取值不够大,取了一个 255 为 N 的值,所以就发生了非常好玩的事情,比如说到值我们 256 个 class 就相当于一个 ID。后来我们大部分的浏览器都选择了 65536,基本上就再也没有发生过超过额度的事情了。因为标准里面只说采用一个比较大的值就可以,但是我们要考虑内存暂用的问题,所以我们会取一个 16 进制上比较整的数,一般来说都是 256 的整次幂(因为 256 是刚好是一个字节)。

CSS 伪类

伪类其实是一类非常多的内容的简单选择器。

链接/行为

:any-link —— 可以匹配任何的超链接:link —— 还没有访问过的超链接:link :visited —— 匹配所有被访问过的超链接:hover —— 用户鼠标放在元素上之后的状态,之前是只能对超链接生效,但是现在是可以在很多元素中使用了:active —— 之前也是只对超链接生效的,点击之后当前的链接就会生效:focus —— 就是焦点在这个元素中的状态,一般用于 input 标签,其实任何可以获得焦点的元素都可以使用:target —— 链接到当前的目标,这个不是给超链接用的,是给锚点的 a 标签使用的,就是当前的 HASH指向了当前的 a 标签的话就会激活 target 伪类

一旦使用了 :link 或者 :visited 之后,我们就再也无法对这个元素的文字颜色之外的属性进行更改。为什么要这样设计呢?因为一旦我们使用了 layout 相关的属性,比如说我们给 :visited 的尺寸加大一点,它就会影响排班。这样我们就可以通过 JavaScript 的 API 去获取这个链接是否被访问过了。但是如果我们能获得链接是否被访问过了,那么我们就可以知道用户访问过那些网站了,这个对于浏览器的安全性来说是一个致命打击。所以这里也提醒一下大家,不要以为做一些表现性的东西于安全没有任何关系,其实安全性是一个综合的考量。CSS 它也能造成安全漏洞的。

树结构

:empty —— 这个元素是否有子元素:nth-child() —— 是父元素的第几个儿子(child):nth-last-child() —— 于 nth-child 一样,只不过从后往前数:first-child :last-child :only-child

:nth-child 是一个非常复杂的伪类,里面支持一种语法,比如说可以在括号里面写奇偶 event 或者 odd,也可以写 4N+13N-1,这个就会分别匹配到整数的形态。因为这个是一个比较复杂的选择器,我们就不要在里面写过于复杂的表达式了,只用它来处理一下奇偶,逢3个多1个,逢4个多1个等等这种表达式。

其实 emptynth-last-childlast-childonly-child 这两个选择器,是破坏了我们之前在 《实现中学习浏览器原理》中的说到的 CSS 计算的时机问题。我们可以想象一下,当我们在开始标签计算的时候,肯定不知道它有没有子标签。empty 影响不是特别大,但是 last-child 的这个关系其实还是影响蛮大的。所以浏览在实现这些的时候是做了特别处理的,要么就是浏览器实现的不是特别好,要么就是浏览器要耗费更大的性能来得以实现。所以建议大家尽量避免大量使用这些。

逻辑型

:not 伪类 —— 主流浏览器只支持简单选择器的序列(复合选择器)我们是没有办法在里面写复杂选择器的语法的:where :has —— 在 CSS Level 4 加入了这两个非常强大了逻辑型伪类

这里还是像温馨建议一下大家,不建议大家把选择器写的过于复杂我们很多时候都可以多加一点 class 去解决的。如果我们的选择器写的过于复杂,某种程度上意味着 HTML 结构写的不合理。我们不光是为了给浏览器工程省麻烦,也不光是为了性能,而是为了我们自身的代码结构考虑,所以我们不应该出现过于复杂的选择器。

CSS 伪元素

一共分为 4 种

::before::after::first-line::first-letter

::before::after 是在元素的内容的前和后,插入一个伪元素。一旦应用了 before 和 after 的属性,declaration(声明)里面就可以写一个叫做 content 的属性(一般元素是没有办法写 content 的属性的)。content 的属性就像一个真正的 DOM 元素一样,可以去生成盒,可以参与后续的排版和渲染了。所以我们可以给他声明 borderbackground等这样的属性。

可以理解为:伪元素向界面上添加了一个不存在的元素。

::first-line::first-letter 的机制就不一样了。这两个其实原本就存在 content 之中。他们顾名思义就是 选中“第一行” 和选中 “第一个字母”。它们 不是一个不存在的元素,是把一部分的文本括了起来让我们可以对它进行一些处理。

before 和 after

在我们概念里,我们可以认为带有 before 伪元素的选择器,会给他实际选中的元素的内容前面增加了一个元素,我们只需要通过他的 content 属性为它添加文本内容即可。(这里我们也可以给伪元素赋予 content: '' 为空的)所以我们可以任何的给 before 和 after 指定 display 属性,和不同元素一样比较自由的。

我们在实现一些组建的时候,也会常常使用这种不污染 DOM 树,但是能实际创造视觉效果的方式来给页面添加一些修饰性的内容。

content content content content content content content content content content content content content content content content

first-letter 和 first-line

first-letter 相当于我们有一个元素把内容里面的第一个字母给括了起来。这个 first-letter 我们是可以任意声明各种不同的属性的,但是我们是无法改变它的 content 的。我们应该都看到过报纸上的第一个字母会比较大,然后会游离出来的效果,这个在 CSS 里面我们就可以用 ::first-letter的伪元素选择器了。使用这个来实现相比用 JavaScript 来实现就会更加稳定和代码更加优雅一些。

content content content content content content content content content content content content content content content content

first-line 是针对排版之后的 line,其实跟我们源码里面的 first line 没有任何的关系的。假如说我们的浏览器提供的渲染的宽度不同,first-line 在两个环境里面它最终括住的元素数量就不一样多了。所以我们用这个选择器的时候需要去根据需求的情况使用,很有可能在我们开发机器上和用户的机器上渲染出来的效果是不一样的!

content content content content content content content content content content content content content content content content content

这两个选择器其实可用的属性也是有区别的:

first-line 可用属性

font 系列color 系列background 系列word-spacingletter-spacingtext-decorationtext-transformline-height

first-letter 可用属性

font 系列color 系列background 系列text-decorationtext-transformletter-spacingword-spacingline-heightfloatvertical-align盒模型系列:margin, padding, border

小练习

编写一个 match 函数。它接受两个参数,第一个参数是一个选择器字符串性质,第二个是一个 HTML 元素。这个元素你可以认为它一定会在一棵 DOM 树里面。通过选择器和 DOM 元素来判断,当前的元素是否能够匹配到我们的选择器。(不能使用任何内置的浏览器的函数,仅通过 DOM 的 parent 和 children 这些 API,来判断一个元素是否能够跟一个选择器相匹配。)以下是一个调用的例子。

              Match Example —— by 三钻        
content
/** * 匹配选择器 */ function matchSelectors(selector, element) { // 先匹配当前元素是否匹配 let tagSelector = selector.match(/^[w]+/gm); let idSelectors = selector.match(/(?<=#)([wd-_]+)/gm); let classSelectors = selector.match(/(?<=.)([wd-_]+)/gm); /** * 实现复合选择器,实现支持空格的 Class 选择器 * -------------------------------- */ // 检查 tag name 是否匹配 if (tagSelector !== null) { if (element.tagName.toLowerCase() !== tagSelector[0]) return false; } // 检测 id 是否匹配 if (idSelectors !== null) { let attr = element.attributes['id'].value; if (attr) { for (let selector of idSelectors) { if (attr.split(' ').indexOf(selector) === -1) return false; } } } // 检测 class 是否匹配 if (classSelectors !== null) { let attr = element.attributes['class'].value; if (attr) { for (let selector of classSelectors) { if (attr.split(' ').indexOf(selector) === -1) return false; } } } return true; } /** * 匹配元素 */ function match(selector, element) { if (!selector || !element.attributes) return false; let selectors = selector.split(' ').reverse(); if (!matchSelectors(selectors[0], element)) return false; let curElement = element; let matched = 1; // 递归寻找父级元素匹配 while (curElement.parentElement !== null && matched < selectors.length) { curElement = curElement.parentElement; if (matchSelectors(selectors[matched], curElement)) matched++; } // 所有选择器匹配上为 匹配成功,否则是失败 if (matched !== selectors.length) return false; return true; } let matchResult = match('div #id.class', document.getElementById('id')); console.log('Match example by 三钻'); console.log('matchResult', matchResult);

更多编程相关知识,请访问:编程视频!!

以上就是深入了解CSS中的选择器的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1620978.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
css写法怎么优化
上一篇 2025年12月24日 07:21:19
8个值得了解的纯CSS布局排版技巧
下一篇 2025年12月24日 07:21:42

相关推荐

  • 修复Django电商项目中AJAX过滤产品列表图片不显示问题

    在Django电商项目中,当使用AJAX动态加载过滤后的产品列表时,常遇到图片无法正常显示的问题。这通常是由于前端模板中图片加载方式(如data-setbg属性结合JavaScript库)与AJAX动态内容更新机制不兼容所致。解决方案是直接在AJAX返回的HTML中使用标准的标签来渲染图片,确保浏览…

    2026年5月10日
    700
  • css max-height属性怎么用

    max-height 属性设置元素的最大高度。 说明 该属性值会对元素的高度设置一个最高限制。因此,元素可以比指定值矮,但不能比其高。不允许指定负值。 注意:max-height 属性不包括外边距、边框和内边距。 立即学习“前端免费学习笔记(深入)”; 值描述none 默认。定义对元素被允许的最大高…

    2026年5月10日
    100
  • 修复点击时按钮抖动:CSS垂直对齐实践

    本文探讨了在Web开发中,交互式按钮(如播放/暂停按钮)在点击时发生意外垂直位移的问题。通过分析CSS样式变化对元素布局的影响,我们发现这是由于按钮不同状态下的边框样式和内边距改变,以及默认的垂直对齐行为共同作用所致。核心解决方案是利用CSS的vertical-align属性,将其设置为middle…

    2026年5月10日
    100
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    300
  • 前端缓存策略与JavaScript存储管理

    根据数据特性选择合适的存储方式并制定清晰的读写与清理逻辑,能显著提升前端性能;合理运用Cookie、localStorage、sessionStorage、IndexedDB及Cache API,结合缓存策略与定期清理机制,可在保证用户体验的同时避免安全与性能隐患。 前端缓存和JavaScript存…

    2026年5月10日
    200
  • JavaScript 动态菜单点击高亮效果实现教程

    本教程详细介绍了如何使用 JavaScript 实现动态菜单的点击高亮功能。通过事件委托和状态管理,当用户点击菜单项时,被点击项会高亮显示(绿色),同时其他菜单项恢复默认样式(白色)。这种方法避免了不必要的DOM操作,提高了性能和代码可维护性,确保了无论点击方向如何,功能都能稳定运行。 动态菜单高亮…

    2026年5月10日
    200
  • html5怎么画实线_HTML5用CSS border-style:solid画元素实线边框【绘制】

    可通过CSS的border-style属性设为solid添加实线边框:一、内联样式用border:2px solid #000;二、内部样式表统一设置如div{border:1px solid #333};三、外部CSS文件定义.my-box{border:3px solid red}并引入;四、单…

    2026年5月10日
    400
  • css如何禁止滚动条

    css禁止滚动条的方法:1、完全隐藏,代码为【】;2、在不需要时隐藏,代码为【】;3、样式表方法。 本教程操作环境:windows7系统、css3版,DELL G3电脑。 1、完全隐藏 在里加入scroll=”no”,可隐藏滚动条;   立即学习“前端免费学习笔记(深入)”;…

    2026年5月10日
    000
  • 动态更新圆形进度条:JavaScript成绩计算器集成指南

    本文档旨在指导开发者如何将JavaScript成绩计算系统与动态圆形进度条集成,实现可视化展示平均成绩。我们将详细讲解如何修改现有的JavaScript代码,使其在计算出平均分后,能够动态更新圆形进度条的进度,从而提供更直观的用户体验。本文档包含详细的代码示例和注意事项,帮助开发者轻松实现这一功能。…

    2026年5月10日
    000
  • React组件中动态属性值的管理与同步:利用状态实现受控组件

    本教程旨在解决react组件中动态属性值同步使用的问题。我们将探讨如何利用react的`usestate` hook来管理组件内部状态,从而实现一个属性的值动态地影响另一个属性,并构建出可预测、易于维护的受控组件。文章将通过具体代码示例,详细阐述从初始化状态到处理状态更新的完整过程,并强调受控组件在…

    2026年5月10日
    000
  • 如何讲html和css_讲解HTML与CSS结合使用基础【基础】

    需将HTML与CSS结合使用以实现网页结构与样式的分离:HTML定义标题、段落等语义结构,CSS控制颜色、字体等外观;可通过内联样式、内部样式表或外部CSS文件引入样式,并利用类选择器和ID选择器精准应用。 如果您希望网页不仅展示内容,还能具备基本的样式和结构布局,则需要将HTML与CSS结合使用。…

    2026年5月10日
    100
  • CSS伪元素与固定背景:移动友好的实现策略

    本文深入探讨了如何利用CSS的::before伪元素、position: fixed和z-index属性,创建一种在移动设备上表现更稳定的全屏固定背景效果,以替代传统background-attachment: fixed可能存在的兼容性问题。教程将详细解析这些核心CSS概念及其在构建响应式布局中的…

    2026年5月10日
    000
  • JavaScript计算器开发:解决数值显示与初始化问题

    本教程深入探讨了使用JavaScript构建计算器时常见的数值显示异常问题,特别是由于类属性未初始化导致的`Cannot read properties of undefined`错误。我们将详细分析问题根源,并通过在构造函数中调用初始化方法来解决该问题,同时优化显示逻辑,确保计算器功能稳定且界面显…

    2026年5月10日
    000
  • HTML表单如何实现PWA支持?怎样添加离线功能?

    答案是利用Service Worker缓存资源并结合Background Sync API实现离线提交与自动同步。通过注册Service Worker缓存表单相关文件,拦截提交行为,将离线数据存入IndexedDB,并注册后台同步任务,待网络恢复后由Service Worker自动发送数据,确保提交…

    2026年5月10日
    000
  • CSS技巧:在复杂悬停效果中确保图像始终可见

    CSS技巧:在复杂悬停效果中确保图像始终可见CSS技巧:在复杂悬停效果中确保图像始终可见CSS技巧:在复杂悬停效果中确保图像始终可见CSS技巧:在复杂悬停效果中确保图像始终可见

    本教程探讨如何在包含悬停效果的CSS卡片布局中,确保图像始终显示在最顶层而不被裁剪或遮挡。通过调整HTML结构,利用CSS的position和z-index属性,以及引入pointer-events,我们将解决图像被overflow: hidden和扩展叠加层遮盖的问题,实现复杂的视觉交互效果。 在…

    2026年5月10日 用户投稿
    000
  • HTML文档如何工作?如何编辑HTML格式文件?

    HTML文档如何工作?如何编辑HTML格式文件?HTML文档如何工作?如何编辑HTML格式文件?HTML文档如何工作?如何编辑HTML格式文件?HTML文档如何工作?如何编辑HTML格式文件?

    浏览器解析和渲染html的过程包括:1. 解析html构建dom树;2. 结合css构建渲染树;3. 布局计算元素位置;4. 绘制像素到屏幕。编辑html可使用记事本、vs code、sublime text等文本或代码编辑器,其中vs code因语法高亮、自动补全和插件生态成为主流选择。标准htm…

    2026年5月10日 用户投稿
    100
  • JavaScript 中使用多个 querySelector 更新页面元素

    本文旨在讲解如何在 JavaScript 的 if 语句中使用多个 querySelector 来更新不同的页面元素,并提供示例代码和注意事项,帮助开发者理解并应用此技术。通过该方法,可以根据特定条件动态修改页面内容,提升用户体验。 使用 querySelector 在 if 语句中更新多个元素 在…

    2026年5月10日
    100
  • HTTP客户端请求缓存与重用优化

    合理使用客户端缓存与连接复用可显著提升Web性能。通过Cache-Control、ETag和Last-Modified实现条件请求,避免重复传输;启用Keep-Alive并维护TCP连接池以减少握手开销;优先采用HTTP/2或HTTP/3实现多路复用与低延迟连接;针对静态资源设置长缓存,动态数据使用…

    2026年5月10日
    100
  • CodeIgniter在IIS环境下实现URL重写与index.php移除指南

    本教程详细指导如何在IIS服务器上部署的CodeIgniter应用中,移除URL中不必要的index.php。核心解决方案涉及修改CodeIgniter的config.php文件,将$config[‘index_page’]设置为空,并辅以正确的IIS web.config重…

    2026年5月10日
    100

发表回复

登录后才能评论
关注微信