CSS 容器查询完全指南
·
CSS 容器查询完全指南
引言
CSS 容器查询(Container Queries)是 CSS 规范中的一项革命性特性,它允许开发者根据容器的尺寸而非视口尺寸来应用样式。本文将深入探讨容器查询的各种用法和高级技巧。
基础概念回顾
容器查询 vs 媒体查询
| 特性 | 媒体查询 | 容器查询 |
|---|---|---|
| 基于 | 视口尺寸 | 容器尺寸 |
| 语法 | @media | @container |
| 作用范围 | 全局 | 局部 |
基本语法
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}
高级技巧一:容器类型
size 容器
.container {
container-type: size;
}
inline-size 容器
.container {
container-type: inline-size;
}
block-size 容器
.container {
container-type: block-size;
}
高级技巧二:命名容器
定义命名容器
.card-container {
container-type: inline-size;
container-name: card;
}
使用命名容器
@container card (min-width: 400px) {
.card {
flex-direction: row;
}
}
组合使用
@container card (min-width: 400px) and (max-width: 600px) {
.card {
padding: 1.5rem;
}
}
高级技巧三:容器查询单位
cqw - 容器查询宽度单位
@container (min-width: 400px) {
.title {
font-size: 5cqw;
}
}
cqh - 容器查询高度单位
@container (min-height: 300px) {
.content {
font-size: 3cqh;
}
}
cqi - 容器查询内联轴单位
@container (min-inline-size: 400px) {
.item {
width: 25cqi;
}
}
cqb - 容器查询块轴单位
@container (min-block-size: 300px) {
.item {
height: 25cqb;
}
}
cqmin 和 cqmax
@container (min-width: 400px) {
.box {
padding: cqmin(10px, 5%);
}
}
高级技巧四:嵌套容器查询
基础嵌套
.outer {
container-type: inline-size;
container-name: outer;
}
.inner {
container-type: inline-size;
container-name: inner;
}
@container outer (min-width: 600px) {
.card {
background: blue;
}
@container inner (min-width: 300px) {
.title {
font-size: 1.5rem;
}
}
}
多层嵌套
.level-1 {
container-type: inline-size;
container-name: level1;
}
.level-2 {
container-type: inline-size;
container-name: level2;
}
.level-3 {
container-type: inline-size;
container-name: level3;
}
@container level1 (min-width: 800px) {
@container level2 (min-width: 600px) {
@container level3 (min-width: 400px) {
.content {
color: red;
}
}
}
}
高级技巧五:容器查询与 Flexbox/Grid
响应式 Flexbox
.card-container {
container-type: inline-size;
container-name: cardContainer;
display: flex;
gap: 1rem;
}
@container cardContainer (max-width: 500px) {
.card-container {
flex-direction: column;
}
}
响应式 Grid
.grid-container {
container-type: inline-size;
container-name: gridContainer;
display: grid;
grid-template-columns: repeat(4, 1fr);
}
@container gridContainer (max-width: 800px) {
.grid-container {
grid-template-columns: repeat(2, 1fr);
}
}
@container gridContainer (max-width: 400px) {
.grid-container {
grid-template-columns: 1fr;
}
}
实战案例:响应式卡片组件
.card {
container-type: inline-size;
container-name: card;
padding: 1rem;
border-radius: 8px;
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.card-header {
margin-bottom: 1rem;
}
.card-title {
font-size: 1rem;
font-weight: bold;
}
.card-content {
font-size: 0.875rem;
color: #666;
}
.card-actions {
margin-top: 1rem;
display: flex;
gap: 0.5rem;
}
@container card (min-width: 300px) {
.card {
padding: 1.5rem;
}
.card-title {
font-size: 1.25rem;
}
.card-content {
font-size: 1rem;
}
}
@container card (min-width: 400px) {
.card {
display: flex;
gap: 1.5rem;
}
.card-header {
flex-shrink: 0;
width: 150px;
}
.card-body {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.card-actions {
justify-content: flex-end;
}
}
实战案例:响应式导航栏
.navbar {
container-type: inline-size;
container-name: navbar;
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
background: #333;
color: white;
}
.logo {
font-size: 1.25rem;
font-weight: bold;
}
.nav-links {
display: none;
gap: 1.5rem;
}
.nav-links a {
color: white;
text-decoration: none;
}
.mobile-menu {
display: block;
cursor: pointer;
}
@container navbar (min-width: 600px) {
.nav-links {
display: flex;
}
.mobile-menu {
display: none;
}
}
实战案例:响应式表单
.form-container {
container-type: inline-size;
container-name: formContainer;
padding: 1rem;
}
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
}
.form-actions {
display: flex;
gap: 0.5rem;
}
@container formContainer (min-width: 500px) {
.form-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.form-actions {
justify-content: flex-end;
}
}
@container formContainer (min-width: 700px) {
.form-row {
grid-template-columns: repeat(3, 1fr);
}
}
常见问题与解决方案
Q1:浏览器兼容性如何?
A:现代浏览器都支持容器查询:
- Chrome 105+
- Firefox 110+
- Safari 16+
- Edge 105+
Q2:如何优雅降级?
A:使用 @supports 检测:
.card {
padding: 1rem;
}
@supports (container-type: inline-size) {
.card {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
padding: 1.5rem;
}
}
}
Q3:容器查询与媒体查询冲突吗?
A:不冲突,可以结合使用:
@media (min-width: 1024px) {
.container {
display: flex;
gap: 2rem;
}
}
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}
最佳实践
1. 使用 inline-size 优先
/* 推荐 */
.container {
container-type: inline-size;
}
/* 不推荐 */
.container {
container-type: size;
}
2. 命名容器
/* 推荐 */
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
/* 样式 */
}
/* 不推荐 */
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
/* 样式 */
}
3. 结合 CSS Grid
.grid {
container-type: inline-size;
container-name: grid;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
@container grid (min-width: 600px) {
.grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
}
总结
CSS 容器查询是响应式设计的重大进步。通过本文的学习,你应该能够:
- 理解容器查询的概念和优势
- 使用不同类型的容器查询
- 应用容器查询单位
- 实现嵌套容器查询
- 构建响应式组件
掌握这些技巧,能够帮助你创建更加灵活和可复用的组件。
更多推荐
所有评论(0)