现代 CSS 引入了许多新特性和功能,提升了网页设计的灵活性和表现力。本文将介绍一些现代 CSS 的重要特性,包括容器查询、:has()
伪类、选择器嵌套、滚动驱动动画、CSS 锚点定位、作用域样式、级联层、颜色函数、文本优化等。
容器查询
传统的 @media
查询基于视口大小,而容器查询允许组件根据其父容器的大小自适应样式,实现真正的组件级响应式设计。
基础用法
.card-container {
container-name: card;
container-type: inline-size;
}
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
容器类型
类型 | 说明 |
---|---|
size | 可查询容器的块级和内联尺寸 |
inline-size | 仅可查询内联尺寸(推荐,性能更好) |
normal | 不是查询容器 |
查询条件
尺寸查询支持以下条件:
条件 | 说明 |
---|---|
width / height
| 宽度 / 高度 |
inline-size / block-size
| 内联大小 / 块级大小 |
aspect-ratio | 宽高比 |
orientation | 方向(landscape / portrait ) |
样式查询(实验性)可以查询容器的 CSS 自定义属性:
@container style(--theme: dark) {
.element {
background: #1a1a1a;
color: white;
}
}
<div class="card-container">
<div class="card">
<div class="card-image">🖼️</div>
<div class="card-content">
<h3>响应式卡片</h3>
<p>拖拽右下角调整容器大小,观察布局变化</p>
</div>
</div>
</div>
.card-container {
container-name: card;
container-type: inline-size;
border: 2px dashed #999;
padding: 20px;
resize: horizontal;
overflow: auto;
min-width: 200px;
max-width: 100%;
}
.card {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.card-image {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
height: 150px;
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
}
.card-content {
padding: 20px;
}
.card-content h3 {
margin: 0 0 10px 0;
color: #333;
}
.card-content p {
margin: 0;
color: #666;
font-size: 0.9rem;
}
/* 当容器宽度 >= 400px 时,切换为横向布局 */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 150px 1fr;
}
.card-image {
height: auto;
}
}
容器查询示例
:has()
关系伪类
:has()
被称为”父选择器”,可以根据元素的后代或兄弟元素来选择该元素。
/* 选择包含图片的卡片 */
.card:has(img) {
padding: 0;
}
/* 选择没有子元素的段落 */
p:not(:has(*)) {
text-indent: 2em;
}
/* 选择后面紧跟特定元素的元素 */
h2:has(+ p) {
margin-bottom: 0.5em;
}
<div class="demo-container">
<div class="card">
<h3>普通卡片</h3>
<p>这是一个没有特殊内容的卡片</p>
</div>
<div class="card">
<h3>包含图标的卡片</h3>
<span class="icon">⭐</span>
<p>这个卡片包含星标图标</p>
</div>
<div class="card">
<h3>包含按钮的卡片</h3>
<p>这个卡片包含操作按钮</p>
<button>点击</button>
</div>
</div>
.demo-container {
display: grid;
gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.card {
background: #f5f5f5;
padding: 20px;
border-radius: 8px;
border: 2px solid transparent;
transition: all 0.3s;
}
.card h3 {
margin: 0 0 10px 0;
color: #333;
}
.card p {
margin: 0;
color: #666;
}
/* 包含图标的卡片显示金色边框 */
.card:has(.icon) {
border-color: #ffd700;
background: linear-gradient(135deg, #fff9e6 0%, #fff 100%);
}
/* 包含按钮的卡片显示蓝色边框 */
.card:has(button) {
border-color: #4a90e2;
background: linear-gradient(135deg, #e6f2ff 0%, #fff 100%);
}
.icon {
font-size: 2rem;
display: block;
margin: 10px 0;
}
button {
margin-top: 10px;
padding: 8px 16px;
background: #4a90e2;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
:has() 伪类示例
CSS 嵌套
CSS 原生支持选择器嵌套,无需预处理器即可编写更简洁的代码。
.parent {
color: blue;
/* 使用 & 引用父选择器 */
&:hover {
color: red;
}
/* 嵌套子选择器 */
.child {
font-size: 14px;
}
/* 复合选择器 */
&.active {
font-weight: bold;
}
}
<nav class="menu">
<ul>
<li><a href="#" class="active">首页</a></li>
<li><a href="#">关于</a></li>
<li>
<a href="#">服务</a>
<ul class="submenu">
<li><a href="#">设计</a></li>
<li><a href="#">开发</a></li>
</ul>
</li>
</ul>
</nav>
.menu {
background: #2c3e50;
padding: 10px;
border-radius: 8px;
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
gap: 5px;
li {
position: relative;
a {
display: block;
padding: 10px 20px;
color: white;
text-decoration: none;
border-radius: 4px;
transition: background 0.3s;
&:hover {
background: rgba(255,255,255,0.1);
}
&.active {
background: #3498db;
}
}
&:hover .submenu {
display: block;
}
}
}
.submenu {
display: none;
position: absolute;
top: 100%;
left: 0;
background: #34495e;
min-width: 150px;
border-radius: 4px;
margin-top: 5px;
flex-direction: column;
li {
width: 100%;
}
}
}
CSS 嵌套示例
滚动驱动动画
基于滚动位置触发和控制动画,无需 JavaScript。
animation-timeline
使用 scroll()
或 view()
函数定义滚动时间线:
/* 基于滚动容器 */
.element {
animation: fade-in linear;
animation-timeline: scroll(root block);
}
/* 基于视口可见性 */
.element {
animation: slide-in linear;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
animation-range
定义动画的触发范围:
-
entry
:元素进入滚动容器时 -
exit
:元素离开滚动容器时 -
contain
:元素完全在滚动容器内时 -
cover
:元素覆盖滚动容器时
<div class="scroll-container">
<div class="scroll-spacer"></div>
<div class="reveal-card" style="--delay: 0">
<h3>卡片 1</h3>
<p>向下滚动查看动画效果</p>
</div>
<div class="reveal-card" style="--delay: 0.1">
<h3>卡片 2</h3>
<p>每个卡片独立触发动画</p>
</div>
<div class="reveal-card" style="--delay: 0.2">
<h3>卡片 3</h3>
<p>基于视口位置自动播放</p>
</div>
<div class="scroll-spacer"></div>
</div>
.scroll-container {
height: 400px;
overflow-y: scroll;
background: linear-gradient(to bottom, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
padding: 40px 20px;
border-radius: 8px;
}
.scroll-spacer {
height: 200px;
}
.reveal-card {
background: white;
padding: 30px;
margin: 30px 0;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
animation: reveal-up linear both;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
.reveal-card h3 {
margin: 0 0 10px 0;
color: #2c3e50;
}
.reveal-card p {
margin: 0;
color: #7f8c8d;
}
@keyframes reveal-up {
from {
opacity: 0;
transform: translateY(100px) scale(0.9);
filter: blur(10px);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
filter: blur(0);
}
}
滚动驱动动画示例
CSS 锚点定位
将元素精确定位到另一个元素的位置,无需 JavaScript。
/* 定义锚点 */
.button {
anchor-name: --my-button;
}
/* 相对锚点定位 */
.tooltip {
position: absolute;
position-anchor: --my-button;
bottom: anchor(top);
left: anchor(center);
translate: -50% 0;
}
<div class="anchor-demo">
<button class="anchor-button">悬停显示提示</button>
<div class="tooltip">这是一个提示框</div>
</div>
.anchor-demo {
padding: 100px 20px;
text-align: center;
min-height: 200px;
position: relative;
}
.anchor-button {
anchor-name: --my-button;
padding: 12px 24px;
background: #3498db;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
transition: background 0.3s;
}
.anchor-button:hover {
background: #2980b9;
}
.tooltip {
position: absolute;
position-anchor: --my-button;
bottom: anchor(top);
left: anchor(center);
translate: -50% -10px;
background: #2c3e50;
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 14px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
translate: -50% 0;
border: 6px solid transparent;
border-top-color: #2c3e50;
}
.anchor-button:hover + .tooltip {
opacity: 1;
}
锚点定位示例
@scope 作用域规则
限制 CSS 规则的作用范围,避免样式污染。
@scope (.component) to (.boundary) {
h2 {
color: blue;
}
p {
font-size: 14px;
}
}
<article class="scoped-article">
<h2>文章标题(蓝色)</h2>
<p>这段文字在作用域内,字号为 14px</p>
<div class="scope-boundary">
<h2>内部标题(不受影响)</h2>
<p>这段文字在边界外,使用默认样式</p>
</div>
</article>
<h2>外部标题(不受影响)</h2>
@scope (.scoped-article) to (.scope-boundary) {
h2 {
color: #3498db;
font-size: 24px;
}
p {
font-size: 14px;
color: #555;
line-height: 1.6;
}
}
.scoped-article {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
}
.scope-boundary {
background: white;
padding: 15px;
margin-top: 15px;
border-left: 3px solid #e74c3c;
}
@scope 示例
@layer 级联层
控制样式的优先级顺序,更好地管理复杂样式。
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; }
}
@layer base {
body { font-family: sans-serif; }
}
@layer components {
.button { padding: 10px 20px; }
}
<div class="layer-demo">
<button class="btn">基础按钮</button>
<button class="btn btn-primary">主要按钮</button>
<button class="btn btn-utility">工具按钮</button>
</div>
@layer base, theme, utilities;
@layer base {
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
background: #ecf0f1;
color: #2c3e50;
}
}
@layer theme {
.btn-primary {
background: #3498db;
color: white;
}
}
@layer utilities {
.btn-utility {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
color: white !important;
font-weight: bold;
}
}
.layer-demo {
display: flex;
gap: 10px;
padding: 20px;
}
@layer 示例
color-mix() 颜色混合
混合两种颜色生成新颜色。
.element {
background: color-mix(in srgb, #ff0000 60%, #0000ff 40%);
}
<div class="color-demo">
<div class="color-box" style="background: #e74c3c">
<span>红色</span>
</div>
<div class="color-box" style="background: #3498db">
<span>蓝色</span>
</div>
<div class="color-box" style="background: color-mix(in srgb, #e74c3c 50%, #3498db 50%)">
<span>混合 50/50</span>
</div>
<div class="color-box" style="background: color-mix(in srgb, #e74c3c 70%, #3498db 30%)">
<span>混合 70/30</span>
</div>
</div>
.color-demo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 15px;
padding: 20px;
}
.color-box {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
color: white;
font-weight: bold;
text-align: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.color-box span {
padding: 10px;
background: rgba(0,0,0,0.2);
border-radius: 4px;
}
color-mix() 示例
相对颜色语法
基于现有颜色创建变体。
.element {
--base: #3498db;
background: rgb(from var(--base) r g b / 0.5);
border-color: hsl(from var(--base) h s calc(l - 10%));
}
<div class="relative-color-demo">
<div class="color-item original">原始颜色</div>
<div class="color-item lighter">更亮 20%</div>
<div class="color-item darker">更暗 20%</div>
<div class="color-item transparent">半透明</div>
</div>
.relative-color-demo {
--base-color: #3498db;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
padding: 20px;
}
.color-item {
padding: 30px 20px;
text-align: center;
color: white;
font-weight: bold;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.original {
background: var(--base-color);
}
.lighter {
background: hsl(from var(--base-color) h s calc(l + 20%));
}
.darker {
background: hsl(from var(--base-color) h s calc(l - 20%));
}
.transparent {
background: rgb(from var(--base-color) r g b / 0.5);
}
相对颜色示例
text-wrap 文本换行
优化文本布局,避免孤行等问题。
值 | 说明 |
---|---|
wrap | 正常换行 |
nowrap | 不换行 |
balance | 平衡行长度 |
pretty | 优化排版,避免孤字 |
stable | 编辑时保持稳定 |
<div class="text-wrap-demo">
<div class="text-box">
<h4>normal(默认)</h4>
<p style="text-wrap: wrap">
这是一段很长的文本内容,用于演示不同的文本换行效果。注意观察最后一行的单词分布。
</p>
</div>
<div class="text-box">
<h4>balance(平衡)</h4>
<p style="text-wrap: balance">
这是一段很长的文本内容,用于演示不同的文本换行效果。注意观察最后一行的单词分布。
</p>
</div>
<div class="text-box">
<h4>pretty(美化)</h4>
<p style="text-wrap: pretty">
这是一段很长的文本内容,用于演示不同的文本换行效果。注意观察最后一行的单词分布。
</p>
</div>
</div>
.text-wrap-demo {
display: grid;
gap: 20px;
padding: 20px;
}
.text-box {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
max-width: 400px;
}
.text-box h4 {
margin: 0 0 10px 0;
color: #2c3e50;
font-size: 16px;
}
.text-box p {
margin: 0;
line-height: 1.6;
color: #555;
}
text-wrap 示例
subgrid 子网格
子网格继承父网格的轨道定义。
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.child {
display: grid;
grid-template-columns: subgrid;
grid-column: span 3;
}
<div class="grid-parent">
<div class="grid-header">
<div>列 1</div>
<div>列 2</div>
<div>列 3</div>
</div>
<div class="grid-item">A1</div>
<div class="grid-item">A2</div>
<div class="grid-item">A3</div>
</div>
.grid-parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
}
.grid-header {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
background: #3498db;
color: white;
font-weight: bold;
border-radius: 4px;
overflow: hidden;
}
.grid-header > div {
padding: 15px;
text-align: center;
border-right: 1px solid rgba(255,255,255,0.2);
}
.grid-header > div:last-child {
border-right: none;
}
.grid-item {
background: white;
padding: 20px;
text-align: center;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
subgrid 示例
field-sizing 字段大小
控制表单字段根据内容自动调整大小。
textarea {
field-sizing: content;
min-height: 3lh;
max-height: 10lh;
}
<div class="form-demo">
<label>自动调整高度的文本框:</label>
<textarea
placeholder="输入内容会自动增长高度..."
style="field-sizing: content"></textarea>
</div>
.form-demo {
padding: 20px;
max-width: 500px;
}
.form-demo label {
display: block;
margin-bottom: 10px;
font-weight: bold;
color: #2c3e50;
}
.form-demo textarea {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 14px;
font-family: inherit;
resize: none;
min-height: 60px;
max-height: 200px;
transition: border-color 0.3s;
}
.form-demo textarea:focus {
outline: none;
border-color: #3498db;
}
field-sizing 示例
Comments