CSS 逻辑属性,滚动捕捉,包含的属性和属性值 17

92 阅读11分钟

逻辑属性 (Logical Properties)滚动捕捉 (Scroll Snap)包含 (Containment) 这些是相对较新或更高级的 CSS 特性,用于提升布局的灵活性、滚动体验和渲染性能。


一、 CSS 逻辑属性和值 (Logical Properties and Values)

逻辑属性和值提供了一种不依赖于物理方向(左/右/上/下)而是基于书写模式 (writing-mode)、方向 (direction) 和文本方向 (text-orientation) 来定义布局和样式的方式。这使得创建适应不同语言(如从右到左的阿拉伯语、垂直书写的日语)的布局更加容易和健壮。

核心思想: 用 start/end 替代 left/right,用 block/inline 替代 width/height 或 top/bottom。

主要逻辑属性 (列举常用,实际更多):

  1. 边距 (Margin):

    • margin-block-start: 块轴起点外边距 (类似 margin-top for horizontal-tb)。
    • margin-block-end: 块轴终点外边距 (类似 margin-bottom)。
    • margin-inline-start: 内联轴起点外边距 (类似 margin-left for LTR, margin-right for RTL)。
    • margin-inline-end: 内联轴终点外边距 (类似 margin-right for LTR, margin-left for RTL)。
    • margin-block: margin-block-start 和 margin-block-end 的简写。
    • margin-inline: margin-inline-start 和 margin-inline-end 的简写。
    • 值: <length>, <percentage>, auto。
  2. 内边距 (Padding):

    • padding-block-start, padding-block-end, padding-inline-start, padding-inline-end, padding-block, padding-inline。
    • 值: <length>, <percentage>
  3. 边框 (Border):

    • 宽度: border-block-start-width, border-block-end-width, border-inline-start-width, border-inline-end-width, border-block-width, border-inline-width。
    • 样式: border-block-start-style, ..., border-inline-style。
    • 颜色: border-block-start-color, ..., border-inline-color。
    • 简写: border-block-start, border-block-end, border-inline-start, border-inline-end, border-block, border-inline。
    • 值: 同物理边框属性。
  4. 圆角 (Border Radius):

    • border-start-start-radius: 块轴起点与内联轴起点相交的角 (类似 border-top-left-radius for horizontal-tb, LTR)。
    • border-start-end-radius: 块轴起点与内联轴终点相交的角 (类似 border-top-right-radius)。
    • border-end-start-radius: 块轴终点与内联轴起点相交的角 (类似 border-bottom-left-radius)。
    • border-end-end-radius: 块轴终点与内联轴终点相交的角 (类似 border-bottom-right-radius)。
    • 值: <length>, <percentage>
  5. 尺寸 (Sizing):

    • inline-size: 内联轴方向的尺寸 (类似 width for horizontal-tb)。
    • min-inline-size, max-inline-size。
    • block-size: 块轴方向的尺寸 (类似 height for horizontal-tb)。
    • min-block-size, max-block-size。
    • 值: <length>, <percentage>, auto, min-content, max-content, fit-content(...)。
  6. 定位偏移 (Inset Properties):

    • inset-block-start: 块轴起点的偏移 (类似 top)。
    • inset-block-end: 块轴终点的偏移 (类似 bottom)。
    • inset-inline-start: 内联轴起点的偏移 (类似 left for LTR)。
    • inset-inline-end: 内联轴终点的偏移 (类似 right for LTR)。
    • inset-block: inset-block-start 和 inset-block-end 的简写。
    • inset-inline: inset-inline-start 和 inset-inline-end 的简写。
    • inset: 四个方向偏移的简写。
    • 值: <length>, <percentage>, auto。
  7. 浮动与清除 (Float & Clear):

    • float: inline-start, inline-end (替代 left, right)。
    • clear: inline-start, inline-end (替代 left, right)。
  8. 文本对齐 (Text Align):

    • text-align: start, end (替代 left, right)。

逻辑值 (用于某些物理属性):

  • caption-side: block-start, block-end, inline-start, inline-end。
  • resize: block, inline。

示例:

.element {
  /* 物理属性 */
  /* margin-top: 10px; */
  /* margin-left: 15px; */
  /* width: 300px; */

  /* 对应的逻辑属性 (假设是水平从左到右书写模式) */
  margin-block-start: 10px;
  margin-inline-start: 15px;
  inline-size: 300px;
  border-start-start-radius: 5px; /* 左上角圆角 */
}
    

二、 CSS 滚动捕捉 (Scroll Snap)

滚动捕捉允许你在用户滚动停止时,将滚动容器的视口(或元素)捕捉到预定义的捕捉点上,常用于创建类似轮播图 (Carousel) 或全屏滚动的效果。

应用于滚动容器 (Scroll Container) 的属性:

  1. scroll-snap-type

    • 作用: 启用滚动捕捉,并定义捕捉的严格程度和轴向。

    • 值:

      • none: (默认值) 禁用滚动捕捉。

      • 轴向:

        • x: 只在水平轴捕捉。
        • y: 只在垂直轴捕捉。
        • block: 只在块轴捕捉。
        • inline: 只在内联轴捕捉。
        • both: 在水平和垂直轴都捕捉。
      • 严格程度 (可选,与轴向组合):

        • mandatory: 强制捕捉。浏览器必须自动捕捉到某个捕捉点。
        • proximity: 接近捕捉。只有当滚动停止位置足够接近某个捕捉点时,浏览器会捕捉过去。
    • 示例: scroll-snap-type: x mandatory; (水平强制捕捉), scroll-snap-type: y proximity; (垂直接近捕捉), scroll-snap-type: block mandatory;

  2. scroll-padding (简写属性)

    • 作用: 在滚动容器的视口(滚动的“窗口”)边缘设置内边距。这个区域会被视为“无效区域”,捕捉点不会与这个区域对齐。常用于避免捕捉到的内容被固定的页眉/页脚遮挡。
    • 值: <length>, <percentage>。语法同 padding。
    • 相关具体属性: scroll-padding-top, scroll-padding-right, scroll-padding-bottom, scroll-padding-left, 以及对应的逻辑属性 scroll-padding-block-start, scroll-padding-block-end, scroll-padding-inline-start, scroll-padding-inline-end。
    • 示例: scroll-padding-top: 60px; (顶部留出 60px 不捕捉)
  3. scroll-margin (简写属性,应用于捕捉元素)

    • 作用: (这个属性应用于滚动项/捕捉元素,而不是容器,但与滚动捕捉密切相关) 在捕捉元素的外部设置外边距。这个边距定义了有效的捕捉区域。
    • 值: 。语法同 margin。
    • 相关具体属性: scroll-margin-top, ..., scroll-margin-inline-end。
    • 示例: scroll-margin-top: 10px; (让捕捉位置比元素顶部高 10px)

应用于滚动项/捕捉元素 (Scroll Snap Children/Items) 的属性:

  1. scroll-snap-align

    • 作用: 指定该元素哪个点应该与滚动容器的捕捉区域对齐。

    • 值:

      • none: (默认值) 不作为捕捉点。
      • start: 元素的起始边缘对齐容器的起始边缘。
      • end: 元素的结束边缘对齐容器的结束边缘。
      • center: 元素的中心点对齐容器的中心点。
      • 可以提供一或两个值(第一个用于块轴,第二个用于内联轴)。如果只提供一个,双轴都使用该值。
    • 示例: scroll-snap-align: center; (水平垂直都居中对齐), scroll-snap-align: start end; (垂直顶部对齐,水平右对齐 - 假设是水平 LTR)

  2. scroll-snap-stop

    • 作用: 控制浏览器是否必须停在当前捕捉点,即使滚动速度很快也应该停下,而不是可能跳过它。

    • 值:

      • normal: (默认值) 浏览器可以根据滚动速度跳过捕捉点。
      • always: 浏览器必须停在第一个遇到的捕捉点上。
    • 示例: scroll-snap-stop: always;

示例:

.scroll-container {
  overflow-x: auto; /* 允许水平滚动 */
  scroll-snap-type: x mandatory; /* 水平强制捕捉 */
  scroll-padding-left: 20px; /* 左侧留 20px 不捕捉 */
  display: flex; /* 使用 Flexbox 排列子元素 */
}
.scroll-item {
  flex: 0 0 80%; /* 每个项目占容器 80% 宽度 */
  height: 200px;
  scroll-snap-align: start; /* 项目的左边缘与容器左边缘对齐 */
  /* scroll-margin-left: 10px; */ /* 可以微调捕捉位置 */
  /* scroll-snap-stop: always; */
}
    

三、 CSS 包含 (Containment)

contain 属性允许开发者向浏览器明确指示一个元素的子树(该元素及其所有后代)是相对独立的,并且其内部的某些变化不会影响到外部布局或渲染。这可以帮助浏览器进行性能优化,因为它可能只需要重新计算或重新绘制这个被包含的子树,而不是整个页面。

  1. contain

    • 作用: 应用一个或多个包含类型到元素。

    • 值:

      • none: (默认值) 不应用任何包含。
      • size: 尺寸包含。元素的尺寸计算不依赖其内容(通常需要显式设置尺寸)。浏览器可以跳过对其子元素的布局计算来确定其大小。
      • layout: 布局包含。该元素的内部布局完全不影响其外部任何东西。外部布局变化也不影响内部。元素会创建一个独立的格式化上下文(类似 display: flow-root),并且行为类似定位元素的包含块。
      • style: 样式包含。(效果较弱,应用场景有限)影响计数器和引号的作用范围。保证 contain: style 元素的样式变化不会影响到包含它的元素之外(除了该元素本身)。
      • paint: 绘制包含。该元素的后代绝对不会绘制到其边界之外。如果元素在屏幕外或不可见,其后代也保证不可见。浏览器可以优化绘制,只绘制可见部分。
      • strict: 等同于 contain: size layout paint;。提供最强的包含,但要求也最严格(通常需要显式设置尺寸)。
      • content: 等同于 contain: layout paint;。一个常用的折中方案,提供布局和绘制优化,但不需要严格的尺寸限制。
    • 示例:

      • .widget { contain: content; } (常用:优化布局和绘制)
      • .offscreen-element { contain: paint; } (优化屏幕外元素的绘制)
      • .fixed-size-component { contain: strict; width: 300px; height: 200px; } (最强优化,需固定尺寸)

总结:

  • 逻辑属性 提供了基于书写模式的布局方式,增强了国际化适应性。
  • 滚动捕捉 允许创建更流畅、更可控的滚动交互体验。
  • 包含 (contain) 是一种性能优化手段,通过告知浏览器元素的独立性来减少渲染和布局的计算范围。

案例 逻辑属性

    <!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 滚动捕捉演示</title>
<style>
  body {
    font-family: sans-serif;
    margin: 0;
  }

  .gallery-container {
    display: flex; /* 让子元素水平排列 */
    overflow-x: scroll; /* 允许水平滚动 */
    width: 100%;
    height: 300px; /* 给容器一个高度 */
    border: 3px solid #ccc;

    /* --- 滚动捕捉核心属性 --- */
    scroll-snap-type: x mandatory; /* 水平强制捕捉 */

    /* 可选:添加滚动内边距,防止内容贴边 */
    /* scroll-padding-inline-start: 10px; */
    /* scroll-padding-inline-end: 10px; */

    /* 为了更好的视觉效果,隐藏滚动条(可选) */
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none;  /* IE and Edge */
  }
  .gallery-container::-webkit-scrollbar { /* Chrome, Safari, Opera */
    display: none;
  }


  .gallery-item {
    flex: 0 0 100%; /* 每个项目占据容器100%宽度,不收缩不放大 */
    /* 或者使用 inline-size: 100%; */
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2em;
    color: white;

    /* --- 滚动项核心属性 --- */
    scroll-snap-align: start; /* 项目的起始边缘对齐容器的起始边缘 */
    /* 尝试修改为 center 或 end 看看效果 */

    /* 可选:强制在第二项停止 */
    /* &:nth-child(2) {
      scroll-snap-stop: always;
    } */

     /* 可选:给第三项添加滚动外边距,看看捕捉位置的变化 */
    /* &:nth-child(3) {
        scroll-margin-inline-start: 50px;
    } */
  }

  /* 不同背景色区分项目 */
  .gallery-item:nth-child(1) { background-color: dodgerblue; }
  .gallery-item:nth-child(2) { background-color: orange; }
  .gallery-item:nth-child(3) { background-color: mediumseagreen; }
  .gallery-item:nth-child(4) { background-color: tomato; }
  .gallery-item:nth-child(5) { background-color: slateblue; }

</style>
</head>
<body>

  <div class="gallery-container">
    <div class="gallery-item">项目 1</div>
    <div class="gallery-item">项目 2</div>
    <div class="gallery-item">项目 3</div>
    <div class="gallery-item">项目 4</div>
    <div class="gallery-item">项目 5</div>
  </div>

  <p style="padding: 20px;">尝试在上面的区域左右滑动或滚动。</p>

</body>
</html>
    
# 案例 滚动捕捉
    <!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 滚动捕捉演示 (修订版)</title>
<style>
  body {
    font-family: sans-serif;
    margin: 0;
    background-color: #f0f0f0;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
    box-sizing: border-box;
    min-height: 100vh; /* 确保页面有足够高度,避免页面滚动干扰测试 */
  }

  h1 {
    margin-bottom: 20px;
    color: #333;
  }

  p.instructions {
    margin-bottom: 30px;
    color: #555;
    text-align: center;
    max-width: 600px;
    background-color: #fff;
    padding: 10px;
    border-radius: 4px;
    border: 1px solid #ddd;
  }

  .gallery-container {
    display: flex;
    overflow-x: auto; /* 必须有滚动 */
    width: 80%;
    max-width: 500px; /* 缩小一点宽度,确保在多数屏幕上需要滚动 */
    height: 300px;
    border: 2px solid #aaa; /* 加粗边框更明显 */
    border-radius: 8px;
    background-color: white;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);

    /* --- 滚动捕捉 --- */
    scroll-snap-type: x mandatory; /* 水平强制捕捉 */

    /* --- 让捕捉动作更平滑可见 --- */
    scroll-behavior: smooth; /* 重要:使捕捉滚动平滑 */

    /* --- 隐藏滚动条 (可选) --- */
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .gallery-container::-webkit-scrollbar {
    display: none;
  }

  .gallery-item {
    flex: 0 0 100%; /* 每个项目宽度为容器宽度 */
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 1.5em;
    font-weight: bold;
    color: white;
    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
    box-sizing: border-box;
    border-right: 1px dashed rgba(255, 255, 255, 0.3);

    /* --- 滚动捕捉对齐点 --- */
    scroll-snap-align: start; /* !!! 改为 start 对齐 !!! */
    /* 项目的起始边缘 (左) 对齐容器的起始边缘 (左) */
  }

  .gallery-item:last-child {
    border-right: none;
  }

  /* 背景色 */
  .gallery-item:nth-child(1) { background-color: #007bff; }
  .gallery-item:nth-child(2) { background-color: #6f42c1; }
  .gallery-item:nth-child(3) { background-color: #28a745; }
  .gallery-item:nth-child(4) { background-color: #dc3545; }
  .gallery-item:nth-child(5) { background-color: #ffc107; color: #333; text-shadow: none;}
  .gallery-item:nth-child(6) { background-color: #17a2b8; }

</style>
</head>
<body>

  <h1>CSS 滚动捕捉 (Scroll Snap) - 修订版</h1>
  <p class="instructions">
    <strong>测试方法:</strong>请将鼠标光标或手指放在下方的 **彩色方块区域内**,然后 **水平拖动** 或 **水平滚动** (鼠标滚轮或触摸板)。<br>
    当你 **松开鼠标/手指停止滚动** 时,容器应该会 **自动平滑地滚动**,使得下一个或上一个项目的 **左边缘** 对齐容器的 **左边缘**。
  </p>

  <div class="gallery-container">
    <div class="gallery-item">项目 1</div>
    <div class="gallery-item">项目 2</div>
    <div class="gallery-item">项目 3</div>
    <div class="gallery-item">项目 4</div>
    <div class="gallery-item">项目 5</div>
    <div class="gallery-item">项目 6</div>
  </div>

</body>
</html>