深入理解CSS字符转义行为
深入理解CSS字符转义行为
- 深入理解CSS字符转义行为
- 前言
- 为什么要转义?
- CSS 转义
- 什么是合法
css
的表达式- 左半部分
- 右半部分
- 练习
- 参考链接
前言
在日常的开发中,我们经常写css。比如常见的按钮:
<button class="btn"></button>
,我们往往写出这样的样式
.btn {display: inline-flex;cursor: pointer;user-select: none;/* ..more decl.. */
}
然而我们有时候也会见到这样的元素:
<div class="2xl:text-base">Hello world</div>
与之对应生效的CSS样式为:
@media (min-width: 1536px) {.\32xl\:text-base {font-size: 1rem;line-height: 1.5rem;}
}
这时候就纳闷了,我明明写的是 2xl:text-base
啊?\:
这个转义还好说,\3
这个又是哪来的呢?本篇文章就来从 W3C
的角度,对 css
转义行为进行揭秘。
为什么要转义?
我们先把目光提升一些,其实 转义 (Escaping
)这个行为,在各个语言系统中都存在,小到正则表达式,html
,css
,大到 javascript
或者其他成熟的编程语言,都多少存在着这种行为。
那些需要转义的字符,往往是和语言中的特定关键字(keywords/meta
)产生了冲突,所以被迫让位。
比如,正则表达式中的 .
就是一个元字符,代表的是匹配任意单个除了换行符的字符。要想匹配 .
就需要转义一下写成 \.
。
html
中的 <
,>
需要写成 <
,>
,不然就会和 html
中的标签匹配方式(<div></div>
)产生冲突。
而 javascript
中我们也经常写出这样的单/双引号字符串 'i\'m a "happy" fool'
or "i'm a \"happy\" fool"
。
同样 css
也是如此。
CSS 转义
首先让我们来看看 w3c
css
转义的说明:
https://www.w3.org/TR/css-syntax-3/#escaping
Any Unicode code point can be included in an ident sequence or quoted string by escaping it. CSS escape sequences start with a backslash (\), and continue with:
- Any Unicode code point that is not a hex digits or a newline. The escape sequence is replaced by that code point.
- Or one to six hex digits, followed by an optional whitespace. The escape sequence is replaced by the Unicode code point whose value is given by the hexadecimal digits. This optional whitespace allow hexadecimal escape sequences to be followed by “real” hex digits.
从这段说明中,我们理解了转义行为具体的逻辑。大致如下图所示:
\0
是一个非常特殊的字符,本篇文章不对它进行讨论,有兴趣可以自行搜索相应文档。
可以看到转义逻辑是很简单的,无非就是加 \
判断是否是16进制数字,然后进行判断走不同的分支罢了。比如:
<div class="a:">a:</div>
我们既可以这么写,
.a\: {color: red;
}
也可以这么写
.a\3a {color: blue;
}
这2
个选择器,效果上是等价的,但是它们各自走了不同的转义分支。
什么是合法css
的表达式
这里我们以最常使用的 <ident-token>
为例,我们写的那些具体的选择器的值就需要符合这样的规范,即:
这类流程图片,相信对正则熟悉的同学,一眼就看懂了。
左半部分
我们先重点看左半部分,可以看到表达式开头必须以 --
或 -
,或者 _
, a-z
,A-Z
,non-ASCII
开头。
这里解释一下什么是 non-ASCII
,本质上就是非ASCII
字符,也就是 code point > 127
的字符。
接着让我们来看看熟悉可爱的 ASCII
表吧。
经过对照之后,可以筛选出表达式第一个字母的 code point
需要满足的要求是:
code === 45 || // -
code === 95 || // _
(code >= 97 && code <= 122) || // a-z
(code >=65 && code<=90) || // A-Z
code > 127 || // non-ASCII
(escape chars) // 或者转义字符
所以根据这个规则,所有不在上述范围内的 ASCII
字符都需要转义,才能正确表达。注意上面的表达式是不包括数字的哟,所以数字开头的类名,在写 css
选择器的时候都要进行转义,不论正负值。比如
<div class="2">2</div>
要想写选择器作用在这些元素上,就需要这样写:
.\32 {color: red;
}
所以你就了解为什么选择 class="2"
的这个 css
选择器是 .\32
了,因为这本质上是一个 十六进制(hex)
的字符。\32
换算一下就是 3 * 16 + 2 = 50
,而 50
这个 code point
在 ASCII
表里对应的字符就是 2
!
让我们再来点进阶的例子:
<div class="2b">2b</div>
<div class="2g">2g</div>
<div class="-2g">-2g</div>
对应匹配的 css
选择器为(注意注释):
/* 补全6位,不需要跟空格*/
.\000032b {color: blue;
}
/* 没有补全6位,需要跟空格*/
.\32 b {color: red;
}
/* 没有补全6位,然而16进制表示的字符范围是 0-f,
而字符g已经超出这个范围,所以空格 可加可不加,
而上面的 .\32 b 必须加空格,不然会认为 \32b 是一个hex数字整体 */
.\32g {color: red;
}
/* 负数开头,即第一位是'-',第二位是数字的也需要转义 */
.-\32 g {color: red;
}
右半部分
接下来我们来观察表达式的右半部分。
再定义完成前置部分之后,右侧不止可以接受 _
,a-z
,A-Z
,non-ASCII
,也可以接受 0-9
,-
这些字符了。用代码来表达则为:
code === 45 || // -
code === 95 || // _
(code >= 48 && code <= 57) || // 0-9
(code >= 97 && code <= 122) || // a-z
(code >=65 && code<=90) || // A-Z
code > 127 || // non-ASCII
(escape chars) // 或者转义字符
相比左半部分要宽泛一些。这里我给出一些示例:
<div class="a:b">a:b</div>
<div class="lg:[&:nth-child(3)]:hover:underline"></div>
<div class="bg-[url('/img/hero-pattern.svg')]"><!-- ... -->
</div>
<div class="text-[color:var(--my-var)]">...</div>
<div class="before:content-['我爱中国\_icebreaker']"><!-- ... -->
</div>
与之对应的那些样式:
/* 语法错误: 字符是 ASCII 且不在合法范围内需要转义为 \:
*/
.a:b{color: red;
}/* 合法表达式 */
@media (min-width: 1024px) {.lg\:\[\&\:nth-child\(3\)\]\:hover\:underline:hover:nth-child(3) {text-decoration-line: underline;}
}.bg-\[url\(\'\/img\/hero-pattern\.svg\'\)\] {background-image: url(/img/hero-pattern.svg);
}.text-\[color\:var\(--my-var\)\] {color: var(--my-var);
}.before\:content-\[\'\6211\7231\4F60_\4E2D\56FD\\_icebreaker\'\]::before {content: '我爱你 中国_icebreaker';
}
练习
假如你已经理解了上述内容,可以试试为下方的元素添加对应的生效的样式:
<div class="-">单个-是特殊情况哟</div>
<div class="我❤️中国,你好,世界。">我❤️中国,你好,世界。</div>
<div class="émotion">émotion</div>
<div class="-3:2yo:ur[x'\ds]">-3:2yo:ur[x'\ds]</div>
参考链接
https://www.w3.org/TR/css-syntax-3/#escaping
https://www.w3.org/TR/css-syntax-3/#ident-sequence
相关文章:
深入理解CSS字符转义行为
深入理解CSS字符转义行为 深入理解CSS字符转义行为 前言为什么要转义?CSS 转义什么是合法css的表达式 左半部分右半部分 练习参考链接 前言 在日常的开发中,我们经常写css。比如常见的按钮: <button class"btn"></button>&am…...
【论文阅读】(2023.05.10-2023.06.03)论文阅读简单记录和汇总
(2023.05.10-2023.06.08)论文阅读简单记录和汇总 2023/05/10:今天状态,复阳大残,下午淋了点雨吹了点风,直接躺了四个小时还是头晕- -应该是阳了没跑了。 2023/06/03:前两周出差复阳,这两周调整作息把自己又…...
FPGA开发-ddr测试
文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示:这里可以添加技术概要 例如: 本文以米联科开发板为例,介绍ddr测试相关例程。 整体架构流程 提示:这里可以添加技术整体架构 技术名词解释 提示:这…...
BUUCTF 大帝的密码武器 1
题目描述:(下载题目,然后修改后缀名为.zip打开:) 公元前一百年,在罗马出生了一位对世界影响巨大的人物,他生前是罗马三巨头之一。他率先使用了一种简单的加密函,因此这种加密方法以…...
Linux 查看目录个数和大小
一、查看某目录下的文件个数 1. 查看目录下的文件个数 即当前目录/hdapp目录下有多少个文件,文件夹不计入数值 ls -l | grep "^-"| wc -l下面的命令文件夹也会计入数值 ls | wc -w2. 查看指定目录下的文件个数 如果省略指定目录就是默认当前目录 ls…...
Unity制作二次元卡通渲染角色材质——4 、内外描边和细节添加
Unity制作二次元材质角色 回到目录 大家好,我是阿赵。 这里继续讲二次元角色材质。这次打算讲一下描边和细节的添加。 一、外描边 外描边的做法也不止一种,比如后处理方法的偏导数ddx/ddy之类的,也能整个屏幕的求出边缘。但一般来说单模型渲…...
Ubuntu安装GCC10
使用包安装的方式安装 sudo apt upgradesudo apt install software-properties-commonsudo add-apt-repository ppa:ubuntu-toolchain-r/test QA: 更新python3.7后出现ModuleNotFoundError: No module named ‘apt_pkg‘错误QA: Cannot import name ‘_gi’ sudo apt updatesu…...
【flutter】Dart 规范2
高效 Dart 语言指南:用法示例 每天在你写的 Dart 代码中都会应用到这些准则。库的使用者可能不需要知道你在其中的一些想法,但是维护者肯定是需要的。 库 这些准则可以帮助你在多个文件编写程序的情况下保证一致性和可维护性。为了让准则简洁…...
k8s CoreDns详解
一、概述 服务发现是 K8s 的一项很重要的功能。K8s 的服务发现有两种方式,一种是将 svc 的 ClusterIP 以环境变量的方式注入到 pod 中;一种就是 DNS,从 1.13 版本开始,coreDNS 就取代了 kube dns 成为了内置的 DNS 服务器。 Cor…...
c++ 连sqlserver
//要在 C 中连接 SQL Server 数据库,可以使用 Microsoft 提供的 SQL Server Native Client 或者 //ODBC 驱动程序。以下是使用 SQL Server Native Client 连接数据库的基本步骤: //1. 安装 SQL Server Native Client 驱动程序。 //2. 在 C 代码中包含头…...
给钉钉的2个建议
1. 建议.MD文件可以实现在线编辑 .MD文件可以实现在线编辑。 现状:word、excel、txt等文件都可以实现在线编辑,期望.MD文件也可以进行在线编辑,便于喜欢用.MD文旦交流的人使用。 2. 增加群内根据关键词自定义提醒功能 随着个人加入的群聊增多…...
STL之优先级队列(堆)的模拟实现与仿函数(8千字长文详解!)
STL之优先级队列(堆)的模拟实现与仿函数 文章目录 STL之优先级队列(堆)的模拟实现与仿函数优先级队列的概念priority_queue的接口介绍优先级队列的构造函数 priority_queue模拟实现类成员构造函数向下调整算法——正常实现 push向…...
设施管理系统
随着经济的快速发展,各种基础设施都在更新,在企事业单位中各种设施也都难以管理,以往传统的管理模式已经无法适应现代社会的需求,设备管理的滞后反而会影响设施设备的使用效果,因此设施设备管理系统必不可少。那么什么…...
JavaScript:获取当前日期、星期、时间 | Data对象
文章目录 1 Date对象2 代码示例3 获取 yyyy-MM-dd 格式的日期 1 Date对象 JavaScript 中的 Date 对象表示日期和时间。Date 对象基于自 1970 年 1 月 1 日 00:00:00 UTC(协调世界时)以来的毫秒数。以下是 Date 对象的一些常用方法和属性。 getFullYear…...
Cadence原理图快速查找元器件的方法
1.Cadence原理图快速查找元器件的方法 ①在红框中输入元器件编号,点击望远镜的图标在底下的状态栏可看到查找到的相关元器件,点击元器件可自动定位当前元器件的位置。 ②点击hierarchy(层)可自主查找,找到后点击序号即…...
科目二 调整座椅
靠背倾角 座椅高低 座椅前后用手抬起座椅前的横杠,让座椅向后移动方便上车 靠背左侧,向后扳扳杠调整倾角 座椅左侧,上下扳动调整高低头顶距车顶有一拳的距离 座椅前横杠一只手提起横杠另一只手握住方向盘前拉、后推调整到合适位置,…...
02.加载GDT表,进入保护模式
加载GDT表,进入保护模式 加载GDT表,实现操作系统从实模式进入保护模式 参考 操作系统学习 — 启动操作系统:进入保护模式 保护模式与实模式 GDT、GDTR、LDT、LDTR 调用门与特权级 趣谈 Linux 操作系统 在01.硬盘启动盘,加载操作系…...
MySQL(进阶篇3.0)
锁 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算机资源(CPU、RAM、I/O)的争用之外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…...
2023.6.8小记——嵌入式系统初识、什么是ARM架构?
今天还挺充实的,早上在图书馆本来想学一下notion,结果看李沐老师的动手深度学习看到十点半,在电脑上配置了李沐老师的d2l和jupyter,等后续有时间的时候再继续学。 下午看了一下notion的使用方法,这玩意初学者用起来是…...
分布式运用之ELK企业级日志分析系统
1.ELK的相关知识 1.1 ELK的概念与组件 ELK平台是一套完整的日志集中处理解决方案,将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用, 完成更强大的用户对日志的查询、排序、统计需求。 ElasticSearch: 是基于Lucene(…...
【华为OD机试真题 C语言】8、停车场车辆统计 | 机试真题+思路参考+代码解析
文章目录 一、题目🎃题目描述🎃输入输出🎃样例1🎃样例2 二、思路参考三、代码参考🏆C语言 作者:KJ.JK 🍂个人博客首页: KJ.JK 🍂专栏介绍: 华为OD机试真题汇…...
c++ MES 对接(XML、JSON、SOAP)
🗑️ 清空 //MES系统对接可以使用多种协议,包括XML、JSON和SOAP等。 //以下是使用C语言进行MES系统对接的示例代码: //1. XML协议对接: //c #include <iostream> #include <string> #include <vector> #incl…...
idea导入java web项目带jar
可参考:idea导入Javaweb项目_小黑cc的博客-CSDN博客 配置tomcat 加载项目jar依赖 最后点ok,tomcat启动 jsp页面的项目,必须要加载这两个jar包...
【第55天|● 392.判断子序列 ● 115.不同的子序列 】
392.判断子序列 class Solution { public:bool isSubsequence(string s, string t) {if(s.size()0)return true;if(t.size()0) return false;vector<bool> dp(t.size()1, true);for(int i0; i<s.size(); i){for(int jt.size(); j>0; j--){if(s[i]t[j-1]&&…...
Dockerfile创建镜像
一、Docker镜像的创建 创建镜像有三种方法,分别为【基于已有镜像创建】、【基于本地模板创建】以及【基于Dockerfile创建】。 1.1 基于现有镜像创建 (1)首先启动一个镜像,在容器里做修改docker run -it centos:7 /bin/bash …...
基于 opencv 的人脸识别上课考勤系统,附源码,可作为毕业设计
一、简介 这个人脸识别考勤签到系统是基于大佬的人脸识别陌生人报警系统二次开发的。 项目使用Python实现,基于OpenCV框架进行人脸识别和摄像头硬件调用,同时也用OpenCV工具包处理图片。交互界面使用pyqt5实现。 该系统实现了从学生信息输入、人脸数据…...
.editorconfig 配置
有人会问:既然项目已经使用了 eslint 和 prettier,为什么还需要 EditorConfig? 为什么需要 EditorConfig? .editorconfig 是一个用于定义和维护跨不同编辑器和开发环境的一致编码样式的文件。它可以确保整个团队在使用不同编辑器…...
Spring 高级依赖注入 —— Bean的延迟依赖查找功能,ObjectFactory 和 ObjectProvider
介绍 首先明确一下什么是延迟查找,一般来说通过Autowired注解注入一个具体对象的方式是属于实时依赖查找,注入的前提是要保证对象已经被创建。而使用延迟查找的方式是我可以不注入对象的本身,而是通过注入一个代理对象,在需要用到…...
VSCode--Config
1. basic 1.1 调整字体 1.2 调整 remote login 输入框都在 TERMINAL 中实现 1.3 界面设置成中文 安装插件: 然后配置即可。 2.Linux 2.1 Install 2.1.1 offline Install vscode server 问题描述 内网开发,vscode 自身通过代理安装完 remote 插件后…...
代码随想录刷题第48天|LeetCode198打家劫舍、LeetCode213打家劫舍II、LeetCode337打家劫舍III
1、LeetCode198打家劫舍 题目链接:198、打家劫舍 1、dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。 2、递推公式: 如果偷第i房间,那么dp[i] dp[i - 2] nums[i] …...
萝岗免费网站建设/如何开发一款app软件
转载来自:http://blog.csdn.net/xiaowei_cqu/article/details/7586847 前一天把系统整个重写了一遍,脉络清晰了很多,也终于解决了以前很多崩溃,异常退出的问题。这里小小总结一下自己遇到的麻烦。 1、内存泄露 内存泄露是说没有释…...
网站建设合同印花税/青岛seo经理
在我们开发中,往往需要加入一些jar包,但是有时候会莫名其妙的报一些找不到类的异常,如: 这个是我在做消息推送的时候遇到的,其实我们在发开地图应用的时候也会遇到过,这是为什么呢,其实就是因为…...
广州制作网站公司电话/g3云推广
文章目录题目描述输入描述输出描述输入输出样例最终代码1. c/c2. java3. python过程理解题目描述 题目背景 在游戏《星际争霸 II》中,高阶圣堂武士作为星灵的重要 AOE 单位,在 游戏的中后期发挥着重要的作用,其技能"灵能风暴"可以…...
免费个人网站制作在线/谷歌关键词分析工具
1.为驳回编译器自动生成函数的技能,可把这些函数的声明放入private,如果是继承类型可把base class的这些函数声明private,可在编译期间得到警告转载于:https://www.cnblogs.com/xuaidongstdudyrecording/p/7259169.html...
建设银行宁夏分行网站/seo推广公司哪家好
C throw(抛出异常)详解 抛出(Throw)--> 检测(Try) --> 捕获(Catch)异常必须显式地抛出,才能被检测和捕获到;如果没有显式的抛出,即使有异常…...
免费英文建设网站/广州seo优化排名推广
前言 前面介绍完了队列(包括双端队列),今天探讨以下Java并发包中一个List的并发数据结构实现CopyOnWriteArrayList,顾名思义CopyOnWriteArrayList也是一种基于数组的类似ArrayList的集合,CopyOnWriteArrayList比起Arra…...