发布于

现代CSS新特性实战:Container Queries、CSS Layers与未来布局

作者

现代CSS新特性实战:Container Queries、CSS Layers与未来布局

现代CSS正在快速发展,新特性为我们提供了更强大的布局和样式控制能力。本文将深入探讨这些前沿特性的实战应用。

Container Queries容器查询

基础概念与语法

/* 容器查询基础语法 */
.card-container {
  container-type: inline-size; /* 或 size, normal */
  container-name: card; /* 可选的容器名称 */
}

/* 简写语法 */
.card-container {
  container: card / inline-size;
}

/* 基于容器宽度的查询 */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: 1rem;
  }
  
  .card__image {
    aspect-ratio: 16/9;
  }
  
  .card__content {
    padding: 1.5rem;
  }
}

@container card (min-width: 600px) {
  .card {
    grid-template-columns: 1fr 3fr;
  }
  
  .card__title {
    font-size: 1.5rem;
  }
}

/* 基于容器高度的查询 */
.sidebar {
  container-type: size;
  container-name: sidebar;
}

@container sidebar (min-height: 500px) {
  .sidebar__nav {
    flex-direction: column;
  }
  
  .sidebar__item {
    margin-bottom: 1rem;
  }
}

/* 复杂的容器查询条件 */
@container card (min-width: 300px) and (max-width: 600px) {
  .card {
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
}

@container (orientation: landscape) {
  .media-player {
    aspect-ratio: 16/9;
  }
}

@container (orientation: portrait) {
  .media-player {
    aspect-ratio: 9/16;
  }
}

实战应用案例

/* 响应式卡片组件 */
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1rem;
  padding: 1rem;
}

.product-card {
  container-type: inline-size;
  container-name: product-card;
  background: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* 小尺寸容器:垂直布局 */
@container product-card (max-width: 299px) {
  .product-card__content {
    padding: 1rem;
  }
  
  .product-card__image {
    width: 100%;
    height: 200px;
    object-fit: cover;
  }
  
  .product-card__title {
    font-size: 1rem;
    margin-bottom: 0.5rem;
  }
  
  .product-card__price {
    font-size: 1.2rem;
    font-weight: bold;
    color: #e74c3c;
  }
  
  .product-card__actions {
    margin-top: 1rem;
  }
  
  .product-card__button {
    width: 100%;
    padding: 0.75rem;
    font-size: 0.9rem;
  }
}

/* 中等尺寸容器:水平布局 */
@container product-card (min-width: 300px) and (max-width: 499px) {
  .product-card {
    display: grid;
    grid-template-columns: 120px 1fr;
    gap: 1rem;
  }
  
  .product-card__image {
    width: 120px;
    height: 120px;
    object-fit: cover;
  }
  
  .product-card__content {
    padding: 1rem 1rem 1rem 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  
  .product-card__title {
    font-size: 1.1rem;
    margin-bottom: 0.5rem;
  }
  
  .product-card__description {
    font-size: 0.9rem;
    color: #666;
    margin-bottom: 0.5rem;
  }
  
  .product-card__button {
    align-self: flex-start;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
  }
}

/* 大尺寸容器:增强布局 */
@container product-card (min-width: 500px) {
  .product-card {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 1.5rem;
  }
  
  .product-card__image {
    width: 200px;
    height: 200px;
    object-fit: cover;
  }
  
  .product-card__content {
    padding: 1.5rem 1.5rem 1.5rem 0;
  }
  
  .product-card__title {
    font-size: 1.3rem;
    margin-bottom: 0.75rem;
  }
  
  .product-card__description {
    font-size: 1rem;
    line-height: 1.5;
    margin-bottom: 1rem;
  }
  
  .product-card__features {
    display: block;
    margin-bottom: 1rem;
  }
  
  .product-card__feature {
    display: inline-block;
    background: #f8f9fa;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-size: 0.8rem;
    margin-right: 0.5rem;
    margin-bottom: 0.25rem;
  }
  
  .product-card__actions {
    display: flex;
    gap: 0.5rem;
  }
  
  .product-card__button {
    padding: 0.75rem 1.5rem;
    font-size: 1rem;
  }
}

/* 导航组件的容器查询 */
.navigation {
  container-type: inline-size;
  container-name: navigation;
}

@container navigation (max-width: 767px) {
  .nav__menu {
    display: none;
  }
  
  .nav__toggle {
    display: block;
  }
  
  .nav__menu.is-open {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: white;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
}

@container navigation (min-width: 768px) {
  .nav__menu {
    display: flex;
    gap: 2rem;
  }
  
  .nav__toggle {
    display: none;
  }
}

CSS Layers层叠层

基础语法与概念

/* 定义层叠层 */
@layer reset, base, components, utilities;

/* 重置样式层 */
@layer reset {
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  
  ul, ol {
    list-style: none;
  }
  
  a {
    text-decoration: none;
    color: inherit;
  }
}

/* 基础样式层 */
@layer base {
  body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    line-height: 1.6;
    color: #333;
  }
  
  h1, h2, h3, h4, h5, h6 {
    font-weight: 600;
    line-height: 1.2;
  }
  
  p {
    margin-bottom: 1rem;
  }
}

/* 组件样式层 */
@layer components {
  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 1.5rem;
    border: none;
    border-radius: 6px;
    font-size: 1rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
  }
  
  .button--primary {
    background-color: #007bff;
    color: white;
  }
  
  .button--primary:hover {
    background-color: #0056b3;
  }
  
  .card {
    background: white;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    overflow: hidden;
  }
  
  .card__header {
    padding: 1.5rem;
    border-bottom: 1px solid #e9ecef;
  }
  
  .card__body {
    padding: 1.5rem;
  }
}

/* 工具类样式层 */
@layer utilities {
  .text-center { text-align: center; }
  .text-left { text-align: left; }
  .text-right { text-align: right; }
  
  .mt-1 { margin-top: 0.25rem; }
  .mt-2 { margin-top: 0.5rem; }
  .mt-3 { margin-top: 1rem; }
  .mt-4 { margin-top: 1.5rem; }
  
  .hidden { display: none; }
  .block { display: block; }
  .flex { display: flex; }
  .grid { display: grid; }
}

/* 嵌套层 */
@layer components {
  @layer layout {
    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 0 1rem;
    }
    
    .grid {
      display: grid;
      gap: 1rem;
    }
  }
  
  @layer forms {
    .form-group {
      margin-bottom: 1rem;
    }
    
    .form-label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 500;
    }
    
    .form-input {
      width: 100%;
      padding: 0.75rem;
      border: 1px solid #ddd;
      border-radius: 4px;
      font-size: 1rem;
    }
    
    .form-input:focus {
      outline: none;
      border-color: #007bff;
      box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
    }
  }
}

/* 匿名层 */
@layer {
  .special-component {
    /* 这些样式在匿名层中 */
    background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
    color: white;
    padding: 2rem;
    border-radius: 12px;
  }
}

/* 导入外部样式到指定层 */
@import url('normalize.css') layer(reset);
@import url('components.css') layer(components);

主题系统实现

/* 主题系统使用CSS Layers */
@layer themes, components, utilities;

/* 默认主题 */
@layer themes {
  :root {
    --color-primary: #007bff;
    --color-primary-hover: #0056b3;
    --color-secondary: #6c757d;
    --color-success: #28a745;
    --color-danger: #dc3545;
    --color-warning: #ffc107;
    --color-info: #17a2b8;
    
    --color-text: #212529;
    --color-text-muted: #6c757d;
    --color-background: #ffffff;
    --color-surface: #f8f9fa;
    --color-border: #dee2e6;
    
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    
    --border-radius: 6px;
    --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }
}

/* 暗色主题 */
@layer themes {
  [data-theme="dark"] {
    --color-primary: #0d6efd;
    --color-primary-hover: #0b5ed7;
    --color-secondary: #6c757d;
    --color-success: #198754;
    --color-danger: #dc3545;
    --color-warning: #fd7e14;
    --color-info: #0dcaf0;
    
    --color-text: #ffffff;
    --color-text-muted: #adb5bd;
    --color-background: #121212;
    --color-surface: #1e1e1e;
    --color-border: #343a40;
    
    --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  }
}

/* 高对比度主题 */
@layer themes {
  [data-theme="high-contrast"] {
    --color-primary: #0000ff;
    --color-primary-hover: #0000cc;
    --color-text: #000000;
    --color-background: #ffffff;
    --color-border: #000000;
    --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  }
  
  [data-theme="high-contrast"] * {
    border-width: 2px !important;
  }
}

/* 组件使用主题变量 */
@layer components {
  .button {
    background-color: var(--color-primary);
    color: var(--color-background);
    border: 1px solid var(--color-primary);
    border-radius: var(--border-radius);
    padding: var(--spacing-sm) var(--spacing-md);
    font-size: var(--font-size-base);
    box-shadow: var(--box-shadow);
  }
  
  .button:hover {
    background-color: var(--color-primary-hover);
  }
  
  .card {
    background-color: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius);
    box-shadow: var(--box-shadow);
  }
  
  .input {
    background-color: var(--color-background);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius);
    padding: var(--spacing-sm);
    font-size: var(--font-size-base);
  }
  
  .input:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 2px rgba(var(--color-primary), 0.25);
  }
}

CSS Subgrid子网格

基础语法与应用

/* Subgrid基础语法 */
.main-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, auto);
  gap: 1rem;
}

.sub-container {
  grid-column: 2 / 4;
  grid-row: 1 / 3;
  
  /* 使用subgrid继承父网格的列轨道 */
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
  gap: inherit; /* 继承父网格的gap */
}

/* 实际应用案例:卡片网格 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2rem;
  padding: 2rem;
}

.card {
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.card__image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.card__content {
  padding: 1.5rem;
  
  /* 使用subgrid对齐内容 */
  display: grid;
  grid-template-rows: subgrid;
  grid-row: 2 / 4;
}

.card__title {
  font-size: 1.25rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.card__description {
  color: #666;
  line-height: 1.6;
  margin-bottom: 1rem;
}

.card__actions {
  margin-top: auto;
  display: flex;
  gap: 0.5rem;
}

/* 复杂布局:文章列表 */
.article-list {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 2rem;
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem;
}

.article {
  grid-column: span 12;
  
  display: grid;
  grid-template-columns: subgrid;
  gap: inherit;
  
  padding: 2rem 0;
  border-bottom: 1px solid #e5e5e5;
}

.article__image {
  grid-column: span 4;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: 8px;
}

.article__content {
  grid-column: span 8;
  
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  gap: 1rem;
}

.article__meta {
  display: flex;
  gap: 1rem;
  font-size: 0.875rem;
  color: #666;
}

.article__title {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.3;
}

.article__excerpt {
  color: #666;
  line-height: 1.6;
}

.article__actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .article {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
  }
  
  .article__image {
    grid-column: 1;
    grid-row: 1;
  }
  
  .article__content {
    grid-column: 1;
    grid-row: 2;
  }
}

现代CSS布局技巧

CSS Grid高级应用

/* 自适应网格布局 */
.auto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 2rem;
}

/* 内在网格 */
.intrinsic-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  gap: 1rem;
}

/* 砌体布局 */
.masonry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  grid-template-rows: masonry; /* 实验性特性 */
  gap: 1rem;
}

/* 降级方案 */
@supports not (grid-template-rows: masonry) {
  .masonry-grid {
    columns: 250px;
    column-gap: 1rem;
  }
  
  .masonry-grid > * {
    break-inside: avoid;
    margin-bottom: 1rem;
  }
}

/* 复杂的网格区域 */
.complex-layout {
  display: grid;
  grid-template-areas:
    "header header header"
    "sidebar main aside"
    "footer footer footer";
  grid-template-columns: 250px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  gap: 1rem;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }

/* 响应式网格区域 */
@media (max-width: 768px) {
  .complex-layout {
    grid-template-areas:
      "header"
      "main"
      "sidebar"
      "aside"
      "footer";
    grid-template-columns: 1fr;
  }
}

/* 网格线命名 */
.named-lines {
  display: grid;
  grid-template-columns: 
    [full-start] 1fr 
    [content-start] minmax(0, 800px) 
    [content-end] 1fr 
    [full-end];
  gap: 2rem;
}

.full-width {
  grid-column: full;
}

.content-width {
  grid-column: content;
}

现代Flexbox技巧

/* 自动边距技巧 */
.flex-container {
  display: flex;
  gap: 1rem;
}

.flex-item:last-child {
  margin-left: auto; /* 推到右边 */
}

/* Flexbox网格 */
.flex-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin: -0.5rem; /* 抵消gap */
}

.flex-grid > * {
  flex: 1 1 calc(33.333% - 1rem);
  min-width: 250px;
}

/* 等高列 */
.equal-height-columns {
  display: flex;
  gap: 2rem;
}

.column {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.column__content {
  flex: 1;
}

.column__footer {
  margin-top: auto;
}

/* 居中技巧 */
.center-content {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

/* 粘性页脚 */
.page-layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.main-content {
  flex: 1;
}

.footer {
  margin-top: auto;
}

总结

现代CSS新特性的核心要点:

  1. Container Queries:基于容器尺寸的响应式设计
  2. CSS Layers:更好的样式组织和层叠控制
  3. CSS Subgrid:继承父网格的轨道定义
  4. 现代布局:Grid和Flexbox的高级应用
  5. 主题系统:CSS自定义属性与层叠层结合

这些现代CSS特性为我们提供了更强大、更灵活的样式控制能力,让响应式设计和组件化开发变得更加高效和优雅。