在 CSS 编写中,你是否遇到过这样的场景:需要给多个不同父元素下的子元素设置相同样式,结果写出一长串重复的选择器?比如给headermainfooter中的p标签设置相同的颜色,传统写法可能是header p, main p, footer p { color: #333; }。这样的代码不仅冗长,还容易出错。而 CSS 新增的:is():where()伪类,就像两把 “简化神器”,能将复杂的选择器合并成简洁的形式,让代码更易读、易维护。今天,我们就来解锁这两个提升 CSS 效率的 “语法糖”。

一、认识 :is () 与 :where ():选择器的 “合并工具”

:is():where()都是 CSS Selectors Level 4 规范中引入的伪类,它们的核心功能相同:接收一个选择器列表作为参数,匹配列表中任意一个选择器能匹配的元素。简单说,就是将多个选择器 “合并” 成一个,避免重复书写。

1.1 基础语法:化繁为简的选择逻辑

/* 传统写法:多个选择器重复部分 */
header h1,
header h2,
header h3 {color: #222;
}/* :is() 简化写法 */
header :is(h1, h2, h3) {color: #222;
}/* :where() 简化写法 */
header :where(h1, h2, h3) {color: #222;
}

可以看到,:is(h1, h2, h3)等价于h1, h2, h3,但与前面的header结合后,代码从三行精简为一行,且避免了重复书写header

1.2 解决的核心问题:减少选择器冗余

在复杂布局中,选择器可能包含多层嵌套,此时:is():where()的优势更加明显:

/* 传统写法:冗长且重复 */
section .title,
article .title,
aside .title,
nav .title {font-weight: bold;margin-bottom: 1rem;
}/* 简化写法:用 :is() 合并父元素 */
:is(section, article, aside, nav) .title {font-weight: bold;margin-bottom: 1rem;
}

这种简化不仅让代码更短,还降低了修改成本 —— 如果需要添加或移除一个父元素(如footer),只需在:is()的参数中操作一次,无需修改多个选择器。

二、:is () 与 :where () 的核心区别:优先级不同

:is():where()的功能几乎完全相同,但有一个关键区别:优先级计算方式不同

  • :is():它的优先级等于参数列表中优先级最高的选择器的优先级。

  • :where():它的优先级始终为0(最低优先级),不会影响整体选择器的优先级。

2.1 优先级对比示例

/* 基础样式 */
.text {color: black;
}/* :where() 选择器:优先级 0 */
:where(.container) .text {color: blue;
}/* :is() 选择器:优先级由 .container 决定(10) */
:is(.container) .text {color: red;
}
<div class="container"><p class="text">这段文字是什么颜色?</p>
</div>

结果:文字最终为红色。原因是:

  • :where(.container) .text的优先级是0 + 10.text的优先级)= 10。

  • :is(.container) .text的优先级是10.container的优先级) + 10.text的优先级)= 20,高于前者。

  • 因此:is()的样式会覆盖:where()的样式。

2.2 优先级应用场景

  • 需要保持低优先级时,用:where():比如通用组件库的样式,希望用户能轻松覆盖。

  • 需要继承高优先级时,用:is():比如项目中的特定样式,不希望被轻易覆盖。

/* 组件库样式:用 :where() 确保低优先级,方便用户覆盖 */
:where(.btn) {padding: 0.5rem 1rem;border: none;
}/* 项目样式:用 .btn 即可覆盖(优先级 10 > 0) */
.btn {padding: 0.6rem 1.2rem;
}

三、进阶用法:嵌套与复杂选择器处理

:is():where()支持嵌套,还能处理包含组合选择器(如后代、子元素、相邻兄弟等)的场景,进一步简化代码。

3.1 嵌套使用:多层选择器合并

/* 传统写法:多层嵌套的重复选择器 */
header nav ul li a,
header nav ul li span,
footer nav ul li a,
footer nav ul li span {color: #666;
}/* 简化写法:嵌套 :is() */
:is(header, footer) nav ul li :is(a, span) {color: #666;
}

3.2 处理组合选择器:后代、子元素、伪类等

/* 传统写法:多个伪类选择器 */
.card:hover .title,
.card:focus-within .title,
.card:active .title {transform: scale(1.05);
}/* 简化写法:用 :is() 合并伪类 */
.card:is(:hover, :focus-within, :active) .title {transform: scale(1.05);
}

3.3 配合否定伪类 :not () 使用

:is():where()可以与:not()结合,实现更灵活的排除逻辑:

/* 选择除了 h1、h2 之外的标题元素 */
:is(h1, h2, h3, h4, h5, h6):not(:is(h1, h2)) {font-size: 1.2rem;
}/* 等价于 */
h3,
h4,
h5,
h6 {font-size: 1.2rem;
}

四、实战案例:让 CSS 代码更简洁

4.1 响应式布局:简化媒体查询中的选择器

在响应式布局中,不同断点下可能需要给多个元素设置相同样式,:is()可以减少重复:

/* 传统写法:断点中重复的选择器 */
@media (max-width: 768px) {header .logo,header .nav,footer .logo,footer .nav {flex-direction: column;}
}/* 简化写法:用 :is() 合并 */
@media (max-width: 768px) {:is(header, footer) :is(.logo, .nav) {flex-direction: column;}
}

4.2 通用样式重置:用 :where () 降低优先级

在样式重置(Reset CSS)中,使用:where()可以确保重置样式的优先级最低,方便后续覆盖:

/* 传统重置:优先级可能过高,难以覆盖 */
ul,
ol,
menu {margin: 0;padding: 0;list-style: none;
}/* 用 :where() 重置:优先级 0,易覆盖 */
:where(ul, ol, menu) {margin: 0;padding: 0;list-style: none;
}/* 后续样式可以轻松覆盖(优先级 10 > 0) */
.custom-list {margin: 1rem 0;list-style: disc;
}

4.3 组件样式:用 :is () 统一处理多种状态

在组件设计中,一个组件可能有多种状态(如默认、禁用、加载中),:is()可以合并这些状态的选择器:

/* 按钮组件的多种状态样式 */
.btn:is(:disabled, .loading) {opacity: 0.7;cursor: not-allowed;pointer-events: none;
}/* 等价于 */
.btn:disabled,
.btn.loading {opacity: 0.7;cursor: not-allowed;pointer-events: none;
}

五、避坑指南:使用时的注意事项

5.1 浏览器兼容性

:is():where()兼容所有现代浏览器(Chrome 88+、Firefox 78+、Safari 14+、Edge 88+),但需要注意:

  • 早期浏览器可能需要带前缀的版本(如:-webkit-any():-moz-any()),但现在已基本淘汰。

  • IE 完全不支持,如需兼容 IE,需避免使用或通过 PostCSS 等工具转译。

5.2 避免选择器范围过大

:is():where()会匹配参数列表中的所有选择器,若范围过大可能导致意外匹配:

/* 问题:会匹配所有 div 中的 p,包括嵌套在其他元素中的 div */
:is(div) p {color: red;
}/* 优化:明确父元素范围 */
.container:is(div) p {color: red;
}

5.3 注意优先级陷阱

:is()的优先级由参数中优先级最高的选择器决定,可能导致样式覆盖不符合预期:

/* :is() 的优先级由 #id 决定(100) */
:is(.class, #id) p {color: blue;
}/* 这个选择器的优先级是 10(.class)+ 10(p)= 20,会被上面覆盖 */
.class p {color: red;
}

解决方法:了解:is()的优先级计算规则,必要时用更具体的选择器覆盖。

六、总结

:is():where()作为 CSS 中的 “语法糖”,虽然没有引入新的功能,但显著提升了代码的简洁性和可维护性。它们的核心价值在于:

  • 简化代码:将重复的选择器合并,减少冗余,让 CSS 更易读。

  • 降低维护成本:修改选择器时只需操作一次,避免遗漏。

  • 灵活控制优先级:where()的低优先级适合通用样式,:is()的动态优先级适合特定样式。

在实际开发中,建议:

  • 写通用组件库或样式重置时,优先用:where(),方便用户覆盖。

  • 写项目特定样式时,根据优先级需求选择:is():where()

  • 处理多层嵌套或多状态选择器时,用它们合并重复部分,提升代码质量。

如果你还在为冗长的 CSS 选择器烦恼,不妨试试:is():where()—— 这两个小小的 “语法糖”,可能会让你的 CSS 代码变得清爽许多。

你在项目中用过:is():where()吗?欢迎在评论区分享你的使用心得~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917971.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917971.shtml
英文地址,请注明出处:http://en.pswp.cn/news/917971.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue打包号的文件如何快速查找文件打包后的位置

解析“explorer yz-front-dist”&#xff1a;前端开发者的实用命令小知识 在前端开发的日常工作中&#xff0c;我们经常会接触到各种命令行操作&#xff0c;其中“explorer yz-front-dist”是一个看似简单却暗藏实用价值的命令。对于刚接触开发的新手来说&#xff0c;理解它的含…

Go语言数据类型深度解析:位、字节与进制

Go语言数据类型深度解析&#xff1a;位、字节与进制 在计算机编程中&#xff0c;数据类型是构建一切的基础。理解不同数据类型的特性、内存占用以及在不同场景下的应用&#xff0c;对于编写高效、可靠的代码至关重要。 本文将深入探讨Go语言中的数据类型系统&#xff0c;重点讲…

计算机视觉(opencv)——图像本质、数字矩阵、RGB + 基本操作(实战一)

OpenCV 入门教程&#xff1a; OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉库&#xff0c;广泛应用于图像处理、视频分析、机器学习等领域。 在 Python 中&#xff0c;cv2 是 OpenCV 的主要接口模块。本文将带你一步步掌握 cv2…

【数据库】使用Sql Server创建索引优化查询速度,一般2万多数据后,通过非索引时间字段排序查询出现超时情况

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录前言SQL 创建索引…

MyBatis联合查询

文章目录数据库设计MyBatis 配置MyBatis 映射文件Mapper 接口总结数据库设计 建表 SQL CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL );CREATE TABLE order (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT NOT NULL,order_no VARCHAR(…

项目中使用的设计模式

项目中使用的设计模式请列举几个项目中常用的设计模式什么是设计模式&#xff0c;在项目中使用了那些设计模式动态代理模式JDK动态代理CGLIB动态代理单例模式懒汉式&#xff08;非线程安全&#xff09;饿汉式懒汉式&#xff08;线程安全&#xff09;工厂模式观察者模式装饰器模…

实战教程:从“对象文件为空“到仓库重生——修复 Git 仓库损坏全记录

文章目录实战教程&#xff1a;从"对象文件为空"到仓库重生——修复 Git 仓库损坏全记录案发现场&#xff1a;一个严重损坏的仓库修复之旅&#xff1a;四步让仓库重获新生准备工作&#xff1a;创建安全备份第 1 步&#xff1a;清理战场——删除所有空对象第 2 步&…

ansible 操作家族(ansible_os_family)信息

1. 操作系统系列 &#xff08;ansible_os_family&#xff09;ansible web -m setup -a filteransible_os_family2. 操作系统家族为 RedHat 时执行任务--- - hosts: websrvsremote_user: roottasks:- name: Install package on RedHat systemsyum:name: httpdstate: presentwhen…

一文学会c++继承 组合

文章目录继承简介定义访问限定符和继承方式⭐基类派生类赋值转换继承的作用域派生类的默认成员函数继承与友元继承与静态成员⭐复杂的菱形继承虚拟继承组合继承简介 继承是面向对象程序设计代码复用的重要手段&#xff0c;使得程序员可以在保持原类的基础上扩展&#xff0c;新…

.Net下载共享文件夹中的文件

由于IIS站点权限等问题&#xff0c;总是没找到处理办法&#xff0c;所以改用外挂的winform的方式来下载共享文件&#xff08;也可以改为使用windows服务的方式&#xff09;。 前提需要先在资源管理器中登录到共享文件夹&#xff0c;确保系统能访问。 服务端代码 (.NET后端) usi…

目标检测数据集 - 眼睛瞳孔检测数据集下载「包含COCO、YOLO两种格式」

数据集介绍&#xff1a;眼睛瞳孔检测数据集&#xff0c;真实采集高质量人脸眼部图片数据&#xff0c;适用于人脸定位、人脸疾病如白内障等疾病的视觉检测。数据标注标签包括 eyepupil 瞳孔一 个缺陷类别&#xff1b;适用实际项目应用&#xff1a;眼睛瞳孔检测项目&#xff0c;以…

Keil MDK-ARM V5.42a 完整安装教程

文章目录一、安装前期准备二、Keil MDK-ARM 主程序安装三、器件支持包&#xff08;Pack&#xff09;安装四、许可证激活五、安装验证Keil MDK&#xff08;Microcontroller Development Kit&#xff09;是针对 Arm Cortex-M 系列微控制器的专业开发环境&#xff0c;集成了 μVis…

WPF中引用其他元素各种方法

在WPF中&#xff0c;引用其他元素的方式有多种&#xff0c;每种方式适用于不同场景&#xff0c;各有优缺点。除了x:Reference&#xff0c;常用的还有以下几种&#xff1a; 一、ElementName 绑定&#xff08;最常用的XAML绑定方式&#xff09; 通过元素的x:Name属性引用同一作用…

Python生成统计学公式

一元线性回归模型 2.1回归分析概述/25 一、回归分析基本概念/25 二、总体回归函数/27 三、随机误差项/29 四、样本回归函数/30 2.2 一元线性回归模型的参数估计/32 一、参数估计的普通最小二乘法/32 二、拟合优度/35 2.3基本假设与普通最小二乘估计量的统计性质/36 一、一元线性…

网络工程师--华为命令专题

一、交换机 交换机分类&#xff1a;1.根据交换方式划分&#xff1a;&#xff08;1&#xff09;存储转发式交换&#xff08;Store and Forward&#xff09;&#xff08;2&#xff09;直通式交换&#xff08;Cut-through&#xff09;&#xff08;3&#xff09;碎片过滤式交换&…

判断可编辑div的光标是否在最前面

要判断一个可编辑div(contenteditable)中的光标是否位于最前面&#xff0c;可以使用以下几种方法&#xff1a; 方法一&#xff1a;使用Selection和Range API function isCaretAtStart(div) {const selection window.getSelection();if (selection.rangeCount 0) return false…

【unity实战】使用Unity程序化生成3D随机地牢(附项目源码)

最终效果 文章目录最终效果前言1、理解程序生成的核心概念2、种子值的核心作用3、程序生成的实际应用4、主流程序生成技术概览5、选择合适的技术实战1、素材2、生成一面墙变换矩阵数据3、渲染墙壁4、加点随机不同的墙壁效果5、绘制四面墙壁4、在四个角落生成支柱5、生成地板6、…

多账号管理方案:解析一款免Root的App分身工具

之前有小伙伴问阿灿有没有可以软件分身的免费软件&#xff0c;后来阿灿找到了一款可以无限分身的app感觉很实用&#xff0c;只有10M大小 02软件介绍说白了它能给各种app和游戏做分身&#xff0c;包括V信、qQ、某音、某付宝这些&#xff0c;而且支持最新的安卓15系统。每个分身…

(附源码)基于PHP和Vue的网上购物平台

内容摘要 内容摘要: 随着互联网技术的迅猛发展&#xff0c;网上购物已成为人们日常生活的重要组成部分。本文围绕PHPVue技术栈构建的网上购物平台展开研究&#xff0c;深入探讨了该平台的架构设计与实现细节。平台前端采用Vue框架&#xff0c;利用其组件化开发和数据驱动的特性…

51单片机

中断系统1.什么是中断当CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这个紧急事件&#xff0c;处理完以后&#xff0c;再回到原来被中断的地方&#xff0c;继续原来的工作&#xff0c;这样的过程称为中断2.为什么要…