本仓库的 CSS 技巧是从我另一个仓库 blog 的常用的一些 CSS 技巧一和常用的一些 CSS 技巧二 — 选择器(伪类与伪元素)整理过来的,目的是为了方便后续的阅读和添加新内容。
其他 CSS 内容:
- CSS
- 关于布局可以查阅 CSS Layout
- CSS3 中的 counter
- 使用 CSS
white-space
修复文本重叠 - Flexbox 居中元素
- 在 CSS 中更改光标颜色
- 使非密码输入使用符号替代
- 禁用文本选择
- 自定义 CSS 选择样式
- CSS 变量
- CSS
text-rendering
属性 - 类似原生的 IOS 滚动
- 蚀刻文字
- 实现文本溢出省略效果
- 渐变文字
- 文本描边效果
- 系统字体堆栈
- 叠纸效果
- 隐藏数字输入微调器
- 发光的蓝色输入亮点
- 使用 fieldset 禁用表单
- 非表单 fieldset 外观
- 将 WebKit 的文件上传按钮强制向右移动
- 简单而漂亮的 Blockquote 样式
- 使用纯 CSS 创建三角形
- 制作一个列宽相等的表格
- 重置所有样式
- 在 HTML 中的字符串中保留空格和换行符
- 使用 hr 作为分隔符
- 从图像中剔除白色背景
- 使用指针事件来控制鼠标事件
- 指示缺少 alt 属性的 img 元素
- 快速输入颜色变量
- 使用 currentColor 关键字重用当前颜色
- 给"默认"链接定义样式
- 用 rem 来调整全局大小;用 em 来调整局部大小
- 为 body 元素添加行高
- 转义 CSS 类名
- 使用 SVG 图标
- 在打印模式下显示链接
- 隐藏 Microsoft Edge 的密码显示按钮
- 防止锚链接消失在粘性标题后面
- 创建自定义表情符号光标
- CSS 重置盒模型
- 清除浮动
:focus
状态样式:focus-within
伪类- 实现分割线
- 为破损的图片定义样式
- CSS
:empty
- CSS
:only-child
伪类 - CSS
:not()
伪类 - 单独的项目列表
- CSS 设置
::placeholder
文本的样式 - CSS
:placeholder-shown
伪类 - 自定义文字选择
- 自定义 WebKit 滚动条
- 首字大写
- 只显示第一个字母
- 使用
:nth-child()
创建具有交替背景颜色的列表 - 使用负
:nth-child
和:nth-last-child
来选择元素 - :hover
- CSS
::marker
伪元素 - 使用
:invalid
和:valid
校验表单元素 - 使用
:checked
和:default
赋予元素状态 - 将前导零附加到有序列表项
- 使用特殊字符设置列表项的样式
- 使用 "形似猫头鹰" 选择器
- 将样式与
:is
伪类选择器组合 - 使用
:root
选择器灵活控制字体大小 - 利用属性选择器来选择空链接
- 利用
+
隐藏额外的换行符 - 在行内元素之间添加换行符
- CSS 滚动阴影
使用 counter
属性可将任何元素转换为编号列表,它类似于有序列表 <ol>
标签的工作方式。
- 定义并初始化计数器
counter-reset: tidbit-counter 19;
- 增量计数器
counter-increment: <counter name> <integer>
- 使用
counter(<counter name>, <counter list style>)
作为content
的内容 - 查看 counter list style 样式的完整列表
<div> <h2>HTML</h2> <h2>CSS</h2> <h2>JS</h2> </div>
CSS 如下:
div { counter-reset: tidbit-counter 19; } h2::before { counter-increment: tidbit-counter; content: counter(tidbit-counter, thai); }
效果如下:
有时 nowrap
会导致文本重叠:
.container { display: flex; } div { white-space: nowrap; }
我们设置了 nowrap
并没有发生重叠的问题,但当我们爲为其添加 width
的时候,看看会发生什么情况:
div { width: 100px; }
发生这种情况是因为原本的 div
宽度的默认值为 width: auto
,这意味着盒子会根据其内容展开。但是,当我们给其一个固定的宽度时,会限制它的增长。文本无处可去,流进了同级框中。
我们可以通过将设置 white-space
为 normal
轻松修复它:
div { white-space: normal; }
使用 CSS Flexbox,能够水平和垂直居中放置某些东西非常简单。标准方法是使用 flex 属性。但是您也可以使用 margin
来做。
使用 flex 属性:
.parent { display: flex; align-items: center; justify-content: center; }
使用具有自动 margin
边距的 Flexbox:
.parent { display: flex; } .child { margin: auto; }
效果如下:
推荐:CSS 居中
使用 caret-color
更改光标的颜色:
input { /* default */ caret-color: auto; } input { /* custom */ caret-color: DeepPink; }
这适用于文本输入(例如 text
、textarea
等),但不能更改实际的密码输入。
password
默认样式:
input { -webkit-text-security: disc; /* default */ }
input { -webkit-text-security: none; } input { -webkit-text-security: circle; } input { -webkit-text-security: square; }
注意:
-webkit-text-security
不在标准中。
- 使用
user-select: none
使元素的内容不可选。 - 使用
user-select: all
用户只需点击一次选择文本
如果您试图创建一个简单的文本复制和粘贴体验,这将非常有用 👍
/* 只需单击一次即可选择所有文本 */ p { user-select: all; } /* 禁用文本选择 */ p { user-select: none; }
CSS ::selection
伪元素使您可以在文本突出显示时将样式应用于文本。
p::selection { background: DeepPink; color: white; }
对于 Firefox,您将需要使用 ::-moz-selection
p::-moz-selection { background: DeepPink; color: white; }
原生 CSS 支持变量,而无需 sass 预处理器,也无需编译
你可以在全局范围的任何地方访问变量,而本地作用域将只在特定的选择器中
/* 所有选择器中都可用 */ :root { --color-red: red; } .text { color: var(--color-red); } .text-1 { color: var(--color-red); }
/* 仅限于.local 类 */ .local { --color-blue: blue; color: var(--color); /* blue */ } .text { color: var(--color-blue); /* 没有效果,找不到改变量 */ }
CSS 关于文本渲染的 text-rendering
属性告诉渲染引擎工作时如何优化显示文本。浏览器会在渲染速度、易读性(清晰度)和几何精度方面做一个权衡。
语法:
text-rendering: optimizeLegibility | auto | optimizeSpeed | geometricPrecision;
auto
:浏览器依照某些根据去推测在绘制文本时,何时该优化速度,易读性或者几何精度。对于该值在不同浏览器中解释的差异,请看兼容性表。optimizeSpeed
:浏览器在绘制文本时将着重考虑渲染速度,而不是易读性和几何精度。它会使字间距和连字无效。Gecko 默认开启该属性,Firefox 是默认 20px 以下开启该属性。optimizeLegibility
:浏览器在绘制文本时将着重考虑易读性,而不是渲染速度和几何精度。它会使字间距和连字有效。该属性值在移动设备上会造成比较明显的性能问题geometricPrecision
:浏览器在绘制文本时将着重考虑几何精度, 而不是渲染速度和易读性。字体的某些方面—比如字间距—不再线性缩放,所以该值可以使使用某些字体的文本看起来不错。
body { text-rendering: optimizeLegibility; }
-webkit-overflow-scrolling: touch
当手指从触摸屏上移开,会保持一段时间的滚动-webkit-overflow-scrolling: auto
当手指从触摸屏上移开,滚动会立即停止
这些属性只能在 Safari iOS 中使用:
body { -webkit-overflow-scrolling: touch; overflow-y: auto; }
相关资料:
创建一种效果,使文本看上去被"蚀刻"或雕刻到背景中。
- 使用
text-shadow
创建一个白色的影子偏移0px
水平和2px
从原始位置垂直。 - 为了使效果起作用,背景必须比阴影更暗。
- 文字颜色应略微褪色,使其看起来像是从背景上雕刻/雕刻出来的。
.etched-text { text-shadow: 0 2px white; font-size: 1.5rem; font-weight: bold; color: #b8bec5; }
- 单行文本溢出
.text-ellipsis { width: 250px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
- 多行文本溢出
.text-ellipsis { width: 250px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; }
- 定位 + 渐变
.truncate-text-multiline { position: relative; overflow: hidden; display: block; height: 109.2px; margin: 0 auto; font-size: 26px; line-height: 1.4; width: 400px; background: #f5f6f9; color: #333; } .truncate-text-multiline:after { content: ''; position: absolute; bottom: 0; right: 0; width: 150px; height: 36.4px; background: linear-gradient(to right, rgba(0, 0, 0, 0), #f5f6f9 50%); }
background
与linear-gradient
一起使用可为文本元素提供渐变背景。webkit-text-fill-color: transparent
用于透明颜色填充文本。webkit-background-clip: text
用于用文本剪切背景,用渐变背景作为颜色填充文本。
.gradient-text { background: linear-gradient(120deg, #fccb90 0%, #d57eeb 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
-webkit-text-stroke
为文本字符指定了文本宽读width
和文本颜色color
text-stroke-width
设置或检索对象中的文字的描边厚度text-stroke-color
设置或检索对象中的文字的描边颜色
.text { -webkit-text-stroke: 3px black; }
效果如下:
相关资料:
使用本机的操作系统字体来接近本机应用程序的感觉。
- 使用
font-family
定义字体列表。 - 浏览器会查找每个连续的字体,如果可能的话,会选择第一个字体,如果找不到字体(在系统上或 CSS 中定义),则会退回到下一个字体。
-apple-system
是 San Francisco,在 iOS 和 macOS(而不是 Chrome)上使用。BlinkMacSystemFont
是 San Francisco,在 macOS Chrome 上使用。'Segoe UI'
在 Windows 10 上使用。Roboto
在 Android 上使用。Oxygen-Sans
在带有 KDE 的 Linux 上使用。Ubuntu
用于 Ubuntu (所有变体)。Cantarell
在带有 GNOME Shell 的 Linux 上使用。'Helvetica Neue'
并Helvetica
在 macOS 10.10 及更低版本上使用。Arial
是所有操作系统广泛支持的字体。- 如果不支持其他字体,
sans-serif
是后备无衬线字体。
.system-font-stack { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', Helvetica, Arial, sans-serif; }
相关资料:
.paper { background: #fff; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15), 0 10px 0 -5px #eee, 0 10px 1px -4px rgba(0, 0, 0, 0.15), 0 20px 0 -10px #eee, 0 20px 1px -9px rgba(0, 0, 0, 0.15); padding: 30px; }
效果如下:
::-webkit-inner-spin-button
CSS 伪元素用于设置数字选择器<input>
元素的微调器按钮内部的样式。::-webkit outer spin button
设置外部样式-webkit-appearance
:改变按钮和其他控件的外观,使其类似于原生控件。::-webkit-inner-spin-button
、::-webkit outer spin button
和-webkit-appearance
都是不规范的属性,它们没有出现在 CSS 规范草案中。有些浏览器不支持或渲染效果不同。
这里我们使用 -webkit-appearance
,语法如下:
-webkit-appearance:none | button | button-bevel ....
从视觉上隐藏数字选择器 <input>
元素的微调器:
input[type='number']::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
正常情况下:
隐藏后:
input[type='text'], textarea { padding: 3px 0px 3px 3px; margin: 5px 1px 3px 0px; border: 1px solid #dddddd; outline: none; transition: all 0.3s ease-in-out; } input[type='text']:focus, textarea:focus { padding: 3px 0px 3px 3px; margin: 5px 1px 3px 0px; border: 1px solid rgba(81, 203, 238, 1); box-shadow: 0 0 5px rgba(81, 203, 238, 1); }
通过将控件或任何内容包裹在 <fieldset>
中并应用 disabled
属性来禁用整个表单或输入组
<style> [disabled] { display: none; } </style> <form name="form"> <label for="has-language"> <input type="checkbox" id="has-language" name="has-language" onChange="document.forms.form.language.disabled = !this.checked" /> Select language </label> <fieldset name="language" disabled> <legend>Language:</legend> <input type="text" name="HTML" placeholder="HTML" /> <input type="text" name="CSS" placeholder="CSS" /> <input type="text" name="JS" placeholder="JS" /> </fieldset> </form>
<section class="fieldset"> <h1>This is not a fieldset</h1> <p>Booyah!</p> </section>
CSS 如下:
.fieldset { position: relative; border: 1px solid #ddd; padding: 10px; } .fieldset h1 { position: absolute; top: 0; font-size: 18px; line-height: 1; margin: -9px 0 0; background: #fff; padding: 0 3px; }
效果如下:
input[type='file'] { -webkit-appearance: none; -webkit-rtl-ordering: left; padding: 10px; border: 1px solid #3e68ff; border-radius: 8px; text-align: left; } input[type='file']::-webkit-file-upload-button { -webkit-appearance: none; display: inline-flex; align-items: center; justify-content: center; padding: 0.25em 0.75em; margin: 0; float: right; border: none; background-color: transparent; cursor: pointer; min-width: 10ch; min-height: 44px; line-height: 1.1; background-color: #3e68ff; color: #fff; border-radius: 8px; box-shadow: 0 3px 5px rgba(0, 0, 0, 0.18); }
blockquote { background: #f9f9f9; border-left: 10px solid #ccc; margin: 1.5em 10px; padding: 1em 10px; quotes: '201円C''201円D''2018円''2019円'; } blockquote:before { color: #ccc; content: open-quote; font-size: 4em; line-height: 0.1em; margin-right: 0.25em; vertical-align: -0.4em; } blockquote p { display: inline; }
效果如下:
.triangle { width: 0; height: 0; border-top: 20px solid #9c27b0; border-left: 20px solid transparent; border-right: 20px solid transparent; }
效果如下:
显式设置每个单元格的宽度是使所有列具有相同宽度的简单方法。例如,下面的 CSS 声明将包含四列的表拆分为宽度相同的部分:
table td { width: 25%; }
但是,如果表的列数是动态的,则该方法不起作用。幸运的是,我们可以使用 table-layout
属性来实现这一点。不管表有多少列,它们的宽度都是相同的。
table { table-layout: fixed; }
table-layout: fixed
可以让每个格子保持等宽:
.calendar { table-layout: fixed; }
无痛的 table
布局。
仅使用一个属性将所有样式重置为默认值。
- 使用
all
属性将所有样式(继承或不继承)重置为其默认值。 - 注意,这不会影响
direction
和unicode-bidi
属性。
.reset-all-styles { all: initial; }
我将通过表单中的 <textarea>
字段获得的工作描述渲染出来,并将其存储在数据库中。
现在,这个描述没有被解释为 HTML,当我把它添加到页面中时,浏览器没有考虑到空格和换行符。
我想要这个:
但:
我们可以添加以下 CSS 解决这个问题:
.whitespace-pre-wrap { white-space: pre-wrap; }
我想在我的 HTML 页面上分离兄弟元素。
我的一个想法是将它们包装在 section
或 div
标签中,并在该元素的底部的顶部应用边距。
另一种方法是不触及整个 HTML 结构,而是放置一个标签作为分隔符。
所以,我使用了一个 hr
标签,它在语义上表示段落级标签之间的主题中断。
我以这种方式对其进行了样式设置,使其不可见但仍占用空间:
hr { margin-top: 20px; border: none; }
使用 mix-blend-mode: multiply
,从图像中剔除白色背景:
img { mix-blend-mode: multiply; }
效果如下:
pointer-events
允许您指定鼠标如何与其触摸的元素进行交互。
要禁用按钮上的默认指针事件,例如:
.button-disabled { opacity: 0.5; pointer-events: none; }
以下 CSS 为任何缺少 alt
属性或 alt
属性为空的 img
提供红色轮廓:
img:not([alt]), img[alt=''] { outline: 8px solid red; }
如果您使用的是 Visual Studio Code,则可以安装 webhint 扩展。当您将鼠标悬停在元素上时,它将自动检测问题并显示详细信息。
我们通常为颜色声明变量,主要在文件顶部,如下所示:
:root { --color-primary: #...; }
然后,可以使用 var
函数重新使用这些颜色:
.btn-primary { background-color: var(--color-primary); }
如果您使用的是 VS Code,则不必完全键入 var(...)
。相反,只需键入 --
,VS Code 就会显示现有的颜色变量。
我们可以一次性为 color
属性定义一个值,并将其与 currentColor
关键字一起重用,而不是在几个地方重复使用颜色。
/* ❌ */ div { color: #d1d5db; background-image: linear-gradient(to bottom, #d1d5db, #fff); } /* ✅ */ div { color: #d1d5db; background-image: linear-gradient(to bottom, currentColor, #fff); }
因为元素的 color
属性(如果未指定)是从其父元素继承的,所以我们可以在元素的子元素中使用 currentColor
关键字。
例如,假设我们希望链接的颜色与其容器(给定的 div
元素)相同:
/* 不好的做法:在三个地方声明相同的颜色 */ div { color: #fff; } div a { border-bottom: 1px solid #fff; color: #fff; text-decoration: none; } /* 好的做法 */ div { color: #fff; } div a { border-bottom: 1px solid currentColor; color: currentColor; text-decoration: none; }
我们经常在 camelCase 格式中使用 currentColor
关键字。但是,CSS 不区分大小写,这意味着currentColor
、CurrentColor
甚至 Currentcolor
都是有效的关键字,并且与 currentColor
具有相同的效果。
给 "默认" 链接定义样式:
a[href]:not([class]) { color: #008000; text-decoration: underline; }
通过 CMS 系统插入的链接,通常没有 class
属性,以上样式可以识别它们,而且不会影响其它样式。
在根元素设置基本字体大小后 (html { font-size: 100%; }
), 使用 em
设置文本元素的字体大小:
h2 { font-size: 2em; } p { font-size: 1em; }
然后设置模块的字体大小为 rem
:
article { font-size: 1.25rem; } aside .module { font-size: 0.9rem; }
现在,每个模块变得独立,更容易、灵活的样式便于维护。
不必为每一个 <p>
、<h*>
等元素逐一添加 line-height
,利用 CSS 继承性,直接在 body
元素上添加统一的初始行高:
body { line-height: 1.5; }
文本元素可以很容易地继承 body
的样式。
CSS 类名不能包含 :
字符。例如,不可能在 CSS 中声明以下类:
.lg:flex { }
但是,我们可以使用 \
字符来更正它:
.lg\:flex {
}
类名可以像往常一样在 HTML 中使用:
<div class="lg:flex">...</div>
在一些 CSS 框架(如 Tailwind)中,经常使用 \
来转义 CSS 类名。
没有理由不使用 SVG 图标:
.logo { background: url('logo.svg'); }
SVG 在所有分辨率下都可以良好缩放,并且支持所有 IE9 以后的浏览器,现在使用它替换您的 .png
、.jpg
或 .gif
文件。
注意: 针对仅有图标的按钮,如果 SVG 没有加载成功的话,以下样式对无障碍有所帮助:
.no-svg .icon-only::after { content: attr(aria-label); }
当用户打印网页时,他们将看不到实际的链接。如果一个链接同时显示文本和它的链接,它会更有用。
我们可以通过在 :after
元素中包含链接来实现:
@media print { a::after { content: ' (' attr(href) ') '; } }
在打印模式下,用户将看到包含在其内容之后的链接:
<!-- 正常模式--> <a href="https://getfrontend.tips">Front-End Tips</a> <!-- 打印模式--> <a href="https://getfrontend.tips">Front-End Tips (https://getfrontend.tips)</a>
如果您使用的是 Edge,需要隐藏 input
的 password
类型提供的密码显示按钮,可以使用下面的伪元素。
::-ms-reveal { display: none; }
粘性标题是一种常见的布局,可以在许多网站上看到。问题是它不能很好地处理锚链接。
假设我们有一个包含不同锚链接的目录。每个锚都会将用户带到页面中的特定 section
。
当用户单击定位点时,页面将滚动到目标 section
。但该 section
的某些部分显示在标题下,这对用户来说不是一个好的体验。
为了防止这种情况发生,我们希望在目标的顶部添加一个边距,但它仅在滚动时有效。此时,scroll-margin-top
就派上了用场。
header { height: 2rem; } section { scroll-margin-top: 2rem; }
创建自定义光标有两种常用方法:
- 使用图像
- 创建
canvas
元素并生成 base64 图像
这两种方法最终都通过将图像的 URL 设置为 cursor
属性来更改光标:
.custom-cursor { cursor: url(/path/to/image.png), auto; } /* 或者 */ .custom-cursor { cursor: url('data:image/png;base64,...'), auto; }
要创建自定义表情符号光标,我们可以使用内联 SVG 元素,该元素在中心显示表情符号,如下所示:
.custom-cursor { cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewport="0 0 48 48" style="fill:black;font-size:24px"><text y="50%">🚀</text></svg>') 16 0, auto; }
*, *::before, *::after { box-sizing: border-box; }
当与将所有元素边距减为零的重置规则或父规则一起使用时,这会将上边距应用于其他元素后面的所有元素。这是一种快速获得垂直节奏的方法。
* + * { margin-top: 1.5rem; }
如果你真的想更具选择性,那么我喜欢在以下特定情况下将其作为后代使用:
article * + h2 { margin-top: 4rem; }
这类似于堆栈的思想,但更针对标题元素,以便在内容节之间提供更多的喘息空间。
- 使用
:after
伪元素并应用content: ''
以使其影响布局。 - 使用
clear: both
做出明确的元素都过去左右浮动。 - 将该元素设置为
display: block
块级元素才能正常运行
.clearfix::after { content: ''; display: block; clear: both; }
注意:仅在用于
float
构建布局时,此选项才有用。考虑使用更现代的方法,例如flexbox
或grid
布局
.input { transition: 180ms box-shadow ease-in-out; } .input:focus { box-shadow: 0 0 0 3px hsla(245, 100%, calc(82%), 0.8); border-color: hsl(245, 100%, 42%); outline: 3px solid transparent; }
当 :focus-within
元素本身具有焦点或其任何后代具有焦点时,伪类将变为活动状态。
以下是一个不可编辑前缀的输入框示例。
当用户与 <input>
交互时,使用 :focus-within
伪类选择器为父元素设置样式。
.input-box:focus-within { border-color: plum; }
未聚焦状态:
聚焦状态:
实现分割线的方式有很多种,这里我们使用 flex
配合伪元素(::before
和 ::after
)实现:
.divider { display: flex; align-items: center; } .divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: #dcdfe6; } .divider::before { margin-right: 1rem; } .divider::after { margin-left: 1rem; }
另一种使用 grid
,左右两侧为水平线的标题可以构造为具有三列的网格:
.heading { display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 1rem; text-align: center; }
1fr auto 1fr
表示左侧和右侧列的宽度相同,它们将占用剩余的空间。
我们可以使用 ::before
和 ::after
伪元素分别表示标题的左侧和右侧:
.heading::before, .heading::after { align-self: center; border-top: 0.25rem double #e5e7eb; content: ''; }
更多方法:CSS 巧妙实现分隔线的几种方法
只需要一点 CSS 就可以美化破损的图片:
img { display: block; font-family: sans-serif; font-weight: 300; height: auto; line-height: 2; position: relative; text-align: center; width: 100%; }
以添加伪元素的法则来显示用户信息和 URL 的引用:
img::before { content: '很抱歉,下面的图像已损坏 :('; display: block; margin-bottom: 10px; } img::after { content: '(url: ' attr(src) ')'; display: block; font-size: 12px; }
了解更多关于这类样式的技巧,可以查阅 Styling Broken Images。
通常,我们希望为包含内容的元素设置样式。当元素完全没有子元素或文本时,该怎么办?您可以使用 :empty
选择器:
<p></p> <!-- 注意空白区 --> <p></p> <!-- 中间什么都没有 -->
p::before { font-family: 'FontAwesome'; content: '\f240'; } p:empty::before { content: '\f244'; } p { color: silver; } p:empty { color: red; }
通过使用 :empty
选择器,我们可以显示自定义占位符。
ul:empty::after { content: 'Empty'; }
如果希望占位符更灵活,而不是在 CSS 中硬编码,则可以从属性中获取占位符,例如 data-placeholder
:
ul:empty::after {
content: attr(data-placeholder);
}
如果列表包含空格或空子节点,则 :empty
选择器无效。
对于内容为空的链接,我们可以使用 href
属性替换内容:
a[href^='http']:empty:before { content: attr(href); }
如果要设置没有兄弟元素的样式,请使用 :only-child
伪类选择器
<ul> <li>child</li> </ul> <ul> <li>siblings</li> <li>siblings</li> </ul>
li:only-child { color: DeepPink; }
不要使用两个不同的选择器来指定样式,然后使用另一个来否定使用它。:not
选择器可选择除与所传递参数匹配的元素之外的所有元素
/* ❌ */ li { margin-left: 10px; } li:first-of-type { margin-left: 0; } /* ✅ 使用 :not() 要好很多 */ li:not(:first-of-type) { margin-left: 10px; }
使列表的每项都由逗号分隔:
ul > li:not(:last-child)::after { content: ','; }
因最后一项不加逗号,可以使用 :not()
伪类。
注意: 这一技巧对于无障碍,特别是屏幕阅读器而言并不理想。而且复制粘贴并不会带走 CSS 生成的内容,需要注意。
我们经常使用 :last-child
选择器取消应用最后一项的特定样式(例如 border
)。创建每个项目都有底部边框的导航通常如下所示:
li { border-bottom: 1px solid #e5e7eb; } /* 不向最后一项添加边框 */ li:last-child { border-bottom: none; }
使用 :not
伪类,我们可以通过一个 CSS 声明使代码更短、更易于维护:
/* 将边框添加到除最后一个项目外的所有项目 */ li:not(:last-child) { border-bottom: 1px solid #e5e7eb; }
另一种方法是使用 +
选择器:
li + li { border-top: 1px solid #e5e7eb; }
这是一个自定义用户样式表的不错的技巧。避免在加载页面时自动播放。如果没有静音,则不显示视频:
video[autoplay]:not([muted]) { display: none; }
:after
选择器的内容属性可用于分隔列表项:
/* 内联项 */ span:not(:last-child):after { content: ' • '; } /* items 列表 */ li:not(:last-child):after { content: ','; }
使用 ::placeholder
伪元素在 <input>
或 <textarea>
元素为占位符文本设置样式。大多数现代浏览器都支持此功能,但对于较旧的浏览器,将需要供应商前缀。
<input placeholder="CSS Placeholder" />
::placeholder { color: pink; }
使用 :placeholder-shown
伪类为当前显示占位符文本的输入设置样式
input:placeholder-shown { border-color: pink; }
在逛到张鑫旭的博客时,看到一篇关于 :placeholder-shown
的文章,里面示例的代码主要如下:
/* 默认placeholder颜色透明不可见 */ .input-fill:placeholder-shown::placeholder { color: transparent; } .input-fill-x { position: relative; } .input-label { position: absolute; left: 16px; top: 14px; pointer-events: none; } .input-fill:not(:placeholder-shown) ~ .input-label, .input-fill:focus ~ .input-label { transform: scale(0.75) translate(0, -32px); }
:placeholder-shown
实现占位符过渡动画 demo
使用 ::selection
伪选择器来选择其中的文本样式。
::selection { background: aquamarine; color: black; } .custom-text-selection::selection { background: deeppink; color: white; }
对于 Firefox,您将需要使用 ::-moz-selection
p::-moz-selection { background: deeppink; color: white; }
为具有可滚动溢出的元素自定义滚动条样式。
::-webkit-scrollbar
设置整个滚动条元素的样式。::-webkit-scrollbar-track
滚动条轨道(滚动条的背景)的样式。::-webkit-scrollbar-thumb
滚动条滑块(可拖动元素)的样式。::-webkit-scrollbar-button
设置滚动条上的按钮 (上下箭头)的样式。::-webkit-scrollbar-track-piece
设置滚动条没有滑块的轨道部分的样式。::-webkit-scrollbar-corner
设置当同时有垂直滚动条和水平滚动条时交汇的部分的样式。::-webkit-resizer
设置某些元素的 corner 部分的部分样式(如:textarea 的可拖动按钮)的样式。
/* 为所以的滚动条设置相同的样式 */ ::-webkit-scrollbar { width: 8px; background: transparent; } ::-webkit-scrollbar-track { background: #e0e4f6; border-radius: 12px; } ::-webkit-scrollbar-thumb { background: #666e8f; border-radius: 12px; }
仅在单独地方设置滚动条样式:
.box::-webkit-scrollbar { width: 8px; background: transparent; } .box::-webkit-scrollbar-track { background: #e0e4f6; border-radius: 12px; } .box::-webkit-scrollbar-thumb { background: #666e8f; border-radius: 12px; }
相关资料:
- Scrollbar Shenanigans
- Strut Your Stuff With a Custom Scrollbar
- scrollbar
- The story of the custom scrollbar using CSS
::first-line
伪元素选择器选择换行之前文本的首行。::first-letter
伪元素选择器应用于元素中文本的首字母。:first-child
伪类选择器仅选择第一段
p::first-line { color: plum; }
p::first-letter { color: plum; font-size: 40px; }
p:first-child { color: plum; }
使第一段的第一个字母大于文本的其余部分。
- 使用
:first-child
选择器仅选择第一段。 - 使用
::first-letter
伪元素为段落的第一个元素设置样式。
p:first-child::first-letter { color: plum; float: left; margin: 0 8px 0 4px; font-size: 3rem; font-weight: bold; line-height: 1; }
有些情况下,我们希望在生成的 HTML 中填充全文,但只显示第一个字母。其余的字符将在视觉上隐藏。例如,当我们必须支持更小的屏幕时,它非常有用。
这里的技巧是为元素设置零字体大小,而第一个字母的字体大小是正常的。
.element { font-size: 0; } .element::first-letter { font-size: 1.5rem; }
使用 :nth-child(odd)
或 :nth-child(even)
伪类选择器将不同 background-color
的元素应用于根据其在同级组中的位置匹配的元素。
li:nth-child(odd) { background-color: purple; } li:nth-child(even) { background: plum; }
使用负的 nth-child
可以选择 1 至 n 个元素。
在以下示例中,前三项将添加下划线。第二到第五项的范围为蓝色。
li:nth-child(-n + 3) { text-decoration: underline; } li:nth-child(n + 2):nth-child(-n + 5) { color: #2563eb; }
我们先隐藏所有的 li
标签,然后选择第 1 至第 3 个元素并显示出来
li { display: none; } li:nth-child(-n + 3) { display: block; }
选择除前 3 个之外的所有项目,并隐藏它们
li:not(:nth-child(-n + 3)) { display: none; }
同样地,nth-last-child
会选择最后几个子项。
/* 在最后两项中添加 decorative */ li:nth-last-child(-n + 2) { text-decoration-line: line-through; }
- 使用
transition
设置不透明度更改的动画。 - 使用
:hover
和:not
伪类选择器将所有元素的不透明度更改为 0.5,但鼠标停留的元素除外。
li { display: inline-block; padding: 0 16px; transition: opacity 0.3s; } .sibling-fade:hover li:not(:hover) { opacity: 0.5; }
:hover
可以配合动画和其他选择器做出很多效果,找时间在写一些例子,顺便加深印象
::marker
伪元素代表一个列表项的标记框 <li>
。标记通常是一个项目符号或数字。
ul li::marker { color: plum; font-size: 1.5em; }
效果如下:
相关资料:
CSS Lists, Markers, And Counters
这里的自定义列表也使用到了 ::marker
伪元素,这里有两种实现。
- 通过
attr()
用于获取标签上的自定义属性data-*
中的值,并赋予content
属性
ul li::marker { content: attr(data-icon); font-size: 1.25em; }
- 使用
counter
属性将任何元素转换为编号列表,并赋值给content
。
ol li::marker { content: counter(list-item); font-family: 'Indie Flower'; font-size: 1.5em; color: purple; }
效果如下:
- CSS 伪类
:invalid
表示任意内容未通过验证的<input>
或其他<form>
元素。 - CSS 伪类
:valid
表示内容验证正确的<input>
或其他<form>
元素。
<form> <div> <label for="url_input">Enter a URL: </label> <input type="url" id="url_input" /> </div> </form>
/* 当校验错误时 */ input:invalid { background-color: pink; } form:invalid { border: 2px solid pink; padding: 10px; } /* 当校验成功时 */ input:valid { background-color: #ddffdd; } form:valid { border: 2px solid #ddffdd; padding: 10px; }
当校验错误时:
当校验成功时:
:checked
伪类选择器表示任何处于选中状态的 radio
,checkbox
或 select
元素中的 option
。
option:checked { color: coral; }
:default
伪类选择器只能作用在表单元素上,表示默认状态的表单元素。
:default
默认应用到有 checked 属性的的标签上。当你切换或选择其他选项时,该选择器不会跟随着应用到你选择的标签上。(它是固定的,不响应的)
示例(默认推荐):
input:default + label:after { content: ' (推荐)'; color: coral; }
将 list-style-type
属性设置为以下值将为有序列表 ( ol
) 的项追加零编号:
ol { list-style-type: decimal-leading-zero; }
然而,它只对指数小于 10 的项目有效。这意味着,如果我们的列表中有 100 多个项目,那么它们的前缀如下:
01. Item 02. Item ... 09. Item 10. Item ... 99. Item 100. Item ...
为了解决这个问题,我们可以使用 CSS 计数器。每项保存计数器的当前值,该值在下一项中递增 1:
ol { counter-reset: items; list-style-type: none; } li { counter-increment: items; }
要使用关联计数器值作为项的前缀,请使用 ::before
伪元素。
li:before { content: '00' counter(items) '. '; } li:nth-child(n + 10)::before { content: '0' counter(items) '. '; } li:nth-child(n + 100)::before { content: counter(items) '. '; }
:nth-child(n+10)
选择器指示索引大于或等于 10 的项。它将覆盖应用于 li::before
元素的样式。以同样的方式,:nth-child(n+100)
覆盖了 :nth-child(n+10)
的样式。
我们通常使用圆形或方形来设置列表项的样式,如下所示:
li { list-style-type: circle; }
您知道列表样式类型属性也接受字符吗。这意味着我们可以使用表情符号或 Unicode 字符:
li { list-style-type: '☀️'; } /* 或 */ li { list-style-type: '2600円'; }
这个名字可能比较陌生,不过通用选择器(*
)和相邻兄弟选择器(+
)一起使用,效果非凡:
* + * { margin-top: 1.5em; }
在此示例中,文档流中的所有的相邻兄弟元素都将设置 margin-top: 1.5em
的样式。
更多 "形似猫头鹰" 的选择器,可参考 A List Apart 上面 Heydon Pickering 的文章
:is
伪类选择器为与参数中列出的选择器匹配的任何元素应用样式。
而不是编写单独的选择器:
header a:hover, nav a:hover, footer a:hover { text-decoration: underline; }
我们可以将它们合并为一个,如下所示:
:is(header, nav, footer) a:hover { text-decoration: underline; }
在响应式布局中,字体大小应需要根据不同的视口进行调整。你可以计算字体大小根据视口高度和宽度,这时需要用到 :root
:
:root { font-size: calc(1vw + 1vh + 0.5vmin); }
现在,您可以使用 root em
body { font: 1rem/1.6 sans-serif; }
当 <a>
元素没有文本内容,但有 href
属性的时候,显示它的 href
属性:
a[href^='http']:empty::before { content: attr(href); }
利用相邻兄弟选择器(+
),在用作间距的换行符(br
)上设置 display: none
,有助于防止 CMS 用户使用额外的换行符。
br + br { display: none; }
这是一个常见的场景,我们想把一个标题分成多行。例如,标题在大屏幕上连续显示。但在小屏幕上,它应该分成不同的部分。
在不使用 br
标签的情况下,我们可以从各种内联 span
元素构建标题。
<h2> <span class="primary">Eet, sleep, code</span> <span>Travel around the world</span> </h2>
通过使用 ::after
伪元素,我们可以在第一个行内元素之后添加换行符:
.primary::after { content: '\A'; white-space: pre; }
其中 \A
表示换行符。
- 使用线性渐变(
linear-gradient
)和径向渐变(radial-gradient
)设置阴影区域 - 通过添加
background-attachment: local
使背景相对于元素的内容定位。
.scroll-shadows { background: linear-gradient(white 30%, rgba(255, 255, 255, 0)) center top, linear-gradient( rgba(255, 255, 255, 0), white 70% ) center bottom, radial-gradient( farthest-side at 50% 0, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0) ) center top, radial-gradient( farthest-side at 50% 100%, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0) ) center bottom; background-repeat: no-repeat; background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px; background-attachment: local, local, scroll, scroll; }
相关资料: