运动路径模块第1级

W3C 工作草案,

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2024/WD-motion-1-20241105/
最新发布版本:
https://www.w3.org/TR/motion-1/
编者草案:
https://drafts.fxtf.org/motion-1/
历史:
https://www.w3.org/standards/history/motion-1/
测试套件:
https://github.com/web-platform-tests/wpt/tree/master/css/motion
https://wpt.fyi/results/css/motion/
反馈:
GitHub
规范内反馈
编者:
(Adobe Inc.)
(Igalia)
Tab Atkins-Bittner (Google)
前任编者:
(Google)
(then Google)
问题跟踪:
GitHub 问题
建议为此规范进行编辑:
GitHub 编辑器

摘要

运动路径允许作者定位任何图形对象,并使其沿着作者指定的路径进行动画处理。

本文档的状态

本节描述了本文档在发布时的状态。W3C 当前出版物的列表以及本技术报告的最新修订版可以在 W3C 技术报告索引 https://www.w3.org/TR/ 中找到。

作为工作草案发布并不意味着 W3C 及其成员的认可。这是一份草案文件,可能随时被其他文件更新、替换或废弃。将本文档引用为正在进行的工作以外的内容是不合适的。

讨论本规范首选 GitHub Issues。 提交问题时,请在标题中包含文本“motion”, 最好是这样: “[motion] …评论摘要…”。 所有问题和评论都会存档, 并且还有一个历史存档

本文档由 CSS 工作组作为工作草案发布,采用推荐标准流程

本文档由一个在 W3C 专利政策下运作的小组制定。 W3C 维护一个与该小组交付成果相关的任何专利披露的公开列表;该页面还包括披露专利的说明。任何实际知晓某项专利包含其认为是必要权利要求(Essential Claim(s))的个人,必须根据 W3C 专利政策第 6 节披露该信息。

本文档受 2023 年 11 月 3 日 W3C 流程文档的约束。

1. 介绍

本节不具有规范性。

transform 属性及其相关属性允许盒模型相对于其布局位置进行任意重新定位(以及旋转、缩放等),而不会破坏页面上任何其他元素的布局。这些位置可以使用 CSS 进行动画或过渡,但只能以相对简单的方式进行:将盒模型从其起始位置沿直线移动到其结束位置。

本规范引入了 offset 缩写属性及其相关的一系列完整属性,它们定义了一个偏移变换:一种将元素上的特定点 (offset-anchor) 对齐到路径 (offset-pathoffset-distance) 上的偏移位置,并可选地将其旋转以跟随路径方向 (offset-rotate) 的变换。

这允许许多强大的新变换可能性,例如使用极坐标(使用 ray() 函数)而不是 translate() 函数使用的标准矩形坐标进行定位,或者使元素沿定义的路径进行动画处理,从而可以轻松定义复杂而美观的二维空间过渡。

例如,下图显示了一条弯曲的路径(用虚线表示),以及一个飞机图形定位在路径上的各个点。飞机在路径上的每个位置都面向路径的方向。
示例路径

飞机显示在不同的 offset-distance 值处:0%50%100%

1.1. 模块交互

本规范定义了可以应用于元素的其他类型的变换(参见 [css-transforms-1])。

CSS Transforms 2 § 6 当前变换矩阵中所述,本文档定义的变换在各个变换属性(translate/rotate/scale,在 [css-transforms-2] 中定义)之后,并在 transform 属性(在 [css-transforms-1] 中定义)之前分层。

1.2.

本规范遵循 [CSS21] 中的 CSS 属性定义约定<basic-shape> 类型在 CSS Shapes Module Level 1 [CSS-SHAPES] 中定义。 <coord-box> 类型在 CSS Box Model Module Level 3 [CSS-BOX-3] 中定义。未在这些规范中定义的值类型在 CSS Values and Units Module Level 3 [CSS3VAL] 中定义。

除了在其定义中列出的特定于属性的值之外,本规范中定义的所有属性还接受 CSS 范围内的关键字,例如 initialinherit 作为其属性值 [CSS3VAL]。为便于阅读,此处未明确重复。

2. 运动路径

2.1. 定义路径:offset-path 属性

名称: offset-path
值: none | <offset-path> || <coord-box>
初始值: none
适用于: 可变换元素
继承性:
百分比: 不适用
计算值: 如指定
规范顺序: 按语法
动画类型: 按计算值
媒体: 视觉

指定偏移路径,即盒模型定位所依据的几何路径。

<offset-path> = <ray()> | <url> | <basic-shape>
    

值的含义如下:

none

元素没有偏移变换

<offset-path> || <coord-box>

元素具有偏移变换, 由某个偏移路径定义。 有关如何计算偏移变换的详细信息,请参见 § 2.7 计算偏移变换

具有transform 的所有常见效果均适用 (例如创建堆叠上下文等)。 有关详细信息,请参见 CSS Transforms 1 § 3 变换渲染模型

如果省略 <offset-path>, 则默认为 inset(0 round X), 其中 X 是为此元素建立包含块的元素上的 border-radius 的值。 如果省略 <coord-box>, 则默认为 border-box

有关每个组件的解释,请参见特定值(如下)。

<ray()>

偏移路径是一条从原点以某个角度延伸的线。 有关详细信息,请参见 § 2.1.1 ray() 函数

<coord-box> 为射线提供参考框

<url>

指向 SVG 形状元素的 URL 引用。 偏移路径是所引用元素的等效路径[SVG2]

如果 URL 未引用形状元素(因为它引用了不同的元素, 或解析为非 SVG 文档, 或根本无法解析, 等等) 则其行为类似于 path("m 0 0")(一个 <basic-shape>)。

<coord-box> 定义了形状元素的视口和用户坐标系, 原点(0,0 点)位于左上角, 单位大小为 1px

<basic-shape>

偏移路径<basic-shape> 函数的等效路径

对于所有 <basic-shape>, 如果它们接受 at <position> 参数 但该参数被省略, 并且元素通过 offset-position 定义了偏移起始位置, 则它使用指定的偏移起始位置作为该参数。 否则,它将按照每个函数的指定进行默认。

<coord-box><basic-shape> 提供了 [=<basic-shape>/参考框=]。

<coord-box>

定义 <offset-path> 调整大小所依据的框。

在 CSS 上下文中, 被引用的框 来自为此元素建立包含块的元素。

在 SVG 上下文中, 所有值的行为都类似于 view-box

测试

2.1.1. ray() 函数

ray() 函数将偏移路径定义为从某个点以某个定义的角度发出的一条直线:

ray() = ray( <angle> && <ray-size>? && contain? && [at <position>]? )

    <ray-size> = closest-side | closest-corner | farthest-side | farthest-corner | sides
    

其参数为:

<angle>

偏移路径是一个单独的线段, 它从偏移起始位置开始,并沿指定的 <angle> 定义的方向延伸。 (其长度由其他参数确定。) 与渐变函数一样,<angle> 值被解释为方位角, 0deg 指向上方, 正角度表示顺时针旋转。

<ray-size>

指定偏移路径的长度(offset-distance: 0%offset-distance: 100% 点之间的距离), 相对于包含框。

如果未指定 <ray-size>,则默认为 closest-side

注意:对于 sides, 距离取决于指定的 <angle>; 对于所有其他值, 无论 <angle> 如何,距离都是恒定的。

各个关键字是:

closest-side

从射线的起点 到包含框最近一侧的距离。

closest-corner

从射线的起点 到包含框最近一个角的距离。

farthest-side

从射线的起点 到包含框最远一侧的距离。

farthest-corner

从射线的起点 到包含框最远一个角的距离。

sides

从射线的起点 到偏移路径包含框边界相交点的距离。

如果射线的起点 在包含框的边界上, 或完全在其边界之外, 则距离为零。

注意:对于 closest-sideclosest-corner, 如果射线的起点边/角上, 则该边/角为最近的。 (换句话说,距离为零。)

注意:对于 closest-sidefarthest-side, 如果射线的起点完全在包含框之外, 则包含框的边缘被认为延伸到无穷远。

contain

偏移路径的长度会减小, 以便即使在 offset-distance: 100% 时,元素也保持在包含框内。

具体来说,路径的长度会减小 元素边框盒宽度的一半或高度的一半, 以较大者为准, 并向下取整到零。

此行为针对特定情况进行了优化——元素的宽度和高度相等或几乎相等; 元素要么通过 border-radius 完全变圆,要么角与其外观无关; ray() 使用 closest-side 定位; 并且 offset-anchor 设置为 center

在这些条件下, 这对于诸如将元素定位在圆形钟面边缘周围的情况很常见, 这确保每个元素 在 offset-distance: 100% 时都相当紧密地贴合钟面的内边缘。

在其他条件下,这将表现得类似,但可能不会给出那么理想的结果。

at <position>

指定射线的原点, 即射线开始的位置 (0% 位置)。 它通过使用 <position> 在盒子的包含框内定位一个 0x0 对象区域来解析。

如果省略,它将使用元素的偏移起始位置, 由 offset-position 给出。

如果元素也没有偏移起始位置, 则其行为类似于 at center

注意:ray() 目前只能用作偏移路径。 如果它将来扩展到其他用途, 其对 offset-position 的使用将仅限于当它是 偏移路径时, 类似于其他 <basic-shape> 函数。

测试

所有这些示例都需要重写。

以下是一些示例。第一个示例显示盒子的某些部分位于偏移路径之外。
<style>
    body {
    transform-style: preserve-3d;
    width: 200px;
    height: 200px;
    }
    .box {
    width: 50px;
    height: 50px;
    offset-position: 50% 50%;
    offset-distance: 100%;
    offset-rotate: 0deg;
    }
    #redBox {
    background-color: red;
    offset-path: ray(45deg closest-side);
    }
    #blueBox {
    background-color: blue;
    offset-path: ray(180deg closest-side);
    }
</style>
<body>
    <div class="box" id="redBox"></div>
    <div class="box" id="blueBox"></div>
</body>
未包含定位的盒子图像
offset-path 不含 contain

在第二个示例中,为每个盒子的 offset-path 值指定了 contain 以避免溢出。

<style>
    body {
    transform-style: preserve-3d;
    width: 200px;
    height: 200px;
    }
    .box {
    width: 50px;
    height: 50px;
    offset-position: 50% 50%;
    offset-distance: 100%;
    offset-rotate: 0deg;
    }
    #redBox {
    background-color: red;
    offset-path: ray(45deg closest-side contain);
    }
    #blueBox {
    background-color: blue;
    offset-path: ray(180deg closest-side contain);
    }
</style>
<body>
    <div class="box" id="redBox"></div>
    <div class="box" id="blueBox"></div>
</body>
包含定位的盒子图像
offset-path 带有 contain

在第三个示例中,路径大小增加以便可以包含盒子。 使用的偏移距离为负。

<style>
    body {
    transform-style: preserve-3d;
    width: 250px;
    height: 250px;
    }
    .box {
    width: 60%;
    height: 10%;

    offset-position: 20% 20%;
    offset-distance: 0%;
    offset-rotate: 0deg;
    offset-anchor: 200% -300%;
    }
    #blueBox {
    background-color: blue;
    offset-path: ray(-90deg closest-side contain);
    }
</style>
<body>
    <div class="box" id="blueBox"></div>
</body>
路径大小增加的图像
offset-path 路径大小增加

在第四个示例中,初始位置在包含块之外。

<style>
    #container {
    transform-style: preserve-3d;
    width: 200px;
    height: 200px;
    }
    .box {
    width: 20%;
    height: 20%;
    offset-position: 140% 70%;
    offset-distance: 100%;
    }
    #redBox {
    background-color: red;
    offset-path: ray(-90deg sides);
    }
    #blueBox {
    background-color: blue;
    offset-path: ray(180deg closest-side);
    }
</style>
<div id="container">
    <div class="box" id="redBox"></div>
    <div class="box" id="blueBox"></div>
</div>
初始位置在包含块之外的图像
初始位置在包含块之外

2.1.2. <basic-shape> 定位示例

此示例使用具有隐式中心位置的圆。
<style>
    body {
    width: 323px;
    height: 131px;
    margin: 0px;
    border: 2px solid black;
    padding: 8px;
    transform-style: preserve-3d;
    }
    .item {
    width:  90px;
    height: 40px;
    background-color: violet;
    }
    #middle {
    offset-position: auto;
    offset-path: circle(60%) margin-box;
    offset-distance: 25%;
    offset-anchor: left top;
    }
</style>
<body>
    <div class="item"></div>
    <div class="item" id="middle"></div>
    <div class="item"></div>
</body>
由正常流确定的圆心
圆心由正常流确定。

2.1.3. <coord-box> 定位示例

此示例显示 <coord-box> 偏移路径如何与 border-radius 结合使用。
<style>
    body {
    width: 500px;
    height: 300px;
    border-radius: 80px;
    border: dashed aqua;
    margin: 0;
    }
    #blueBox {
    width: 40px;
    height: 20px;
    background-color: blue;
    offset-path: margin-box;
    }
</style>
<body>
    <div id="blueBox"></div>
</body>
带 border-radius 的 geometry-box 示例图像
初始位置是顶部水平线的左端。

2.2. 路径上的位置:offset-distance 属性

名称: offset-distance
值: <length-percentage>
初始值: 0
适用于: 可变换元素
继承:
百分比: 相对于偏移路径长度
计算值: 计算的 <length-percentage>
规范顺序: 按语法
动画类型: 按计算值
媒体: 视觉

指定偏移位置偏移路径上的位置。

<length-percentage>

偏移位置是沿元素偏移路径的指定距离的点。 有关如何计算沿路径的距离的详细信息,请参见 § 2.2.1 计算沿路径的计算距离

百分比相对于偏移路径的总长度。

测试

注意:通过对 offset-distance 进行动画处理, 元素可以轻松地描绘出复杂的路径。

如果元素没有偏移路径, 则此属性不起作用。

2.2.1. 计算沿路径的计算距离

处理沿偏移路径的距离的方式因偏移路径的性质而异:

要确定给定偏移路径偏移距离已用偏移距离

  1. 总长度偏移路径及其所有子路径的总长度。

  2. 偏移距离转换为像素,其中 100% 转换为总长度

  3. 如果偏移路径是无界射线:

    已用偏移距离等于偏移距离

    否则,如果偏移路径是带有 contain 的 <angle> 路径:

    已用偏移距离等于偏移距离,并进行钳制,以使盒子完全位于路径内。

    如果偏移路径是任何其他未闭合区间:

    已用偏移距离等于偏移距离,并钳制在 0 和路径总长度之间。

    否则偏移路径是闭合循环:

    已用偏移距离等于偏移距离对路径总长度取模。如果路径总长度为 0, 则已用偏移距离也为 0。

    注意:“模”在此处使用传统的数学定义, 其中输出始终为非负数。

此示例显示沿未闭合区间放置的盒子。
<style>
    .item {
    width: 100px;
    height: 40px;
    offset-position: 0% 0%;
    offset-path: path('m 0 0 h 200 v 150');
    }
    #box1 {
    background-color: red;
    offset-distance: -280%;
    }
    #box2 {
    background-color: green;
    offset-distance: 190%;
    }
</style>
<body>
    <div class="item" id="box1"></div>
    <div class="item" id="box2"></div>
</body>
沿未闭合区间放置盒子的示例
沿未闭合区间放置盒子的示例
此示例显示沿闭合区间放置的盒子。
<style>
    .item {
    width: 100px;
    height: 40px;
    offset-position: 0% 0%;
    offset-path: path('m 0 0 h 200 v 150 z');
    }
    #box1 {
    background-color: red;
    offset-distance: -280%;
    }
    #box2 {
    background-color: green;
    offset-distance: 190%;
    }
</style>
<body>
    <div class="item" id="box1"></div>
    <div class="item" id="box2"></div>
</body>
沿闭合区间放置盒子的示例
沿闭合区间放置盒子的示例
此示例显示了如何使用 offset-pathoffset-distance 在极坐标系内对齐盒子。
<style>
    body {
    transform-style: preserve-3d;
    width: 300px;
    height: 300px;
    border: dashed gray;
    border-radius: 50%;
    }
    .circleBox {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 40px;
    height: 40px;
    background-color: red;
    border-radius: 50%;
    }
    #circle1 {
    offset-path: ray(0deg farthest-side);
    offset-distance: 50%;
    }
    #circle2 {
    offset-path: ray(90deg farthest-side);
    offset-distance: 20%;
    }
    #circle3 {
    offset-path: ray(225deg farthest-side);
    offset-distance: 100%;
    }
</style>
<body>
    <div class="circleBox" id="circle1"></div>
    <div class="circleBox" id="circle2"></div>
    <div class="circleBox" id="circle3"></div>
</body>
三个盒子定位到极坐标的图像
在极坐标中定位盒子的示例

2.3. 路径的起点:offset-position 属性

名称: offset-position
值: normal | auto | <position>
初始值: normal
适用于: 可转换元素
继承:
百分比: 参照包含块的大小
计算值: normalauto 关键字,或计算的 <position>
规范顺序: 按语法
动画类型: 按计算值
媒体: 视觉

指定 <offset-path> 函数在未指定其自身起始位置时使用的偏移起始位置

值的定义如下:

normal

元素没有偏移起始位置

auto

偏移起始位置是盒子的左上角。

注意:这是元素自身盒子的左上角, 而不是其包含块的左上角! 这与指定 top left 完全不同。 例如,它旨在允许 path() 相对于 元素自身位置开始。

<position>

偏移起始位置是使用 <position> 在盒子的包含块内定位 0x0 对象区域的结果。

Tests
此示例显示如何使用 offset-position 定位盒子。
<style>
        #wrap {
        position: relative;
        width: 300px;
        height: 300px;
        border: 1px solid black;
        }

        #box {
        width: 100px;
        height: 100px;
        background-color: green;
        position: absolute;
        top: 100px;
        left: 80px;
        offset-position: auto;
        offset-anchor: center;
        offset-path: ray(45deg);
        }
    </style>
    <body>
        <div id="wrap">
        <div id="box"></div>
        </div>
    </body>
    
offset-position: auto 的图像
auto 赋予 offset-position 时的示例
此示例显示了与 transform 属性以及单个变换属性 (rotate) 的交互。 运动路径变换是将 (left, top) 移动到 offset-position 的垂直平移。
<style>
        #wrap {
        transform-style: preserve-3d;
        width: 400px;
        height: 350px;
        }
        .item {
        position: absolute;
        left: 200px;
        top: 0px;
        offset-position: 200px 100px; /* 平移 0px,100px */
        offset-anchor: left top;
        transform-origin: left top;
        width: 130px;
        height: 80px;
        border-top-right-radius: 23px;
        }
        #box1 {
        background-color: tomato;
        offset-position: auto;
        }
        #box2 {
        background-color: green;
        }
        #box3 {
        background-color: navy;
        rotate: 90deg; /* 在运动路径变换之前应用 */
        }
        #box4 {
        background-color: gold;
        transform: rotate(90deg); /* 在运动路径变换之后应用 */
        }
    </style>
    <body>
        <div id="wrap">
        <div class="item" id="box1"></div>
        <div class="item" id="box2"></div>
        <div class="item" id="box3"></div>
        <div class="item" id="box4"></div>
        </div>
    </body>
    
运动路径和其他变换交互时的示例
运动路径和其他变换交互时的示例
此示例使用 position static,因此 offset-position 从正常流位置生成平移。通过使用 scale 放大这些平移,正常流围绕 offset-position 旋转 180 度,并且盒子彼此炸开。
<style>
        #wrap {
        transform-style: preserve-3d;
        width: 500px;
        height: 250px;
        line-height: 0px;
        }
        span {
        position: static;
        display: inline-block;
        width: 100px;
        height: 50px;
        border-top-right-radius: 23px;
        scale: 2.5 2.5; /* 在运动路径变换之前应用 */
        offset-position: center;
        transform: scale(0.4); /* 在运动路径变换之后应用 */
        }
        #box1 {
        background-color: tomato;
        }
        #box2 {
        background-color: green;
        }
        #box3 {
        background-color: navy;
        }
        #box4 {
        background-color: gold;
        }
    </style>
    <body>
        <div id="wrap">
        <div>
            <span id="box1"></span><span id="box2"></span>
        </div>
        <div>
            <span id="box3"></span><span id="box4"></span>
        </div>
        </div>
    </body>
    
运动路径和缩放交互时的示例
运动路径和缩放交互时的示例
在此示例中,每个 offset-position 值都被忽略,因为 offset-path 是一个 <geometry-box>,但其他偏移属性组合起来的效果等同于 offset-position 'right bottom'。
<style>
        #wrap {
        transform-style: preserve-3d;
        width: 540px;
        height: 420px;
        }
        .item {
        position: absolute;
        width: 90px;
        height: 70px;
        border-top-right-radius: 23px;
        scale: 0.8 0.8; /* 在运动路径变换之前应用 */
        offset-path: padding-box;
        offset-distance: 50%;
        offset-rotate: 0deg;
        offset-anchor: right bottom;
        transform: scale(1.25); /* 在运动路径变换之后应用 */
        }
        #box1 {
        background-color: tomato;
        position: static;
        offset-position: auto; /* 忽略 */
        }
        #box2 {
        background-color: green;
        right: 0px;
        top: 0px;
        offset-position: 23% 45%; /* 忽略 */
        }
        #box3 {
        background-color: navy;
        left: 0px;
        bottom: 0px;
        offset-position: 34% 56px; /* 忽略 */
        }
        #box4 {
        background-color: gold;
        right: 0px;
        bottom: 0px;
        offset-position: 45px 67px; /* 忽略 */
        }
    </style>
    <body>
        <div id="wrap">
        <div class="item" id="box1"></div>
        <div class="item" id="box2"></div>
        <div class="item" id="box3"></div>
        <div class="item" id="box4"></div>
        </div>
    </body>
    
offset-position 被忽略时的示例
offset-position 被忽略时的示例

2.4. 元素的锚点:offset-anchor 属性

名称: offset-anchor
值: auto | <position>
初始值: auto
适用于: 可转换元素
继承:
百分比: 相对于元素参考框的宽度和高度
计算值: auto 关键字或计算的 <position>
规范顺序: 按语法
动画类型: 按计算值
媒体: 视觉

定义元素的偏移锚点——与偏移位置沿偏移路径对齐的点。

值的含义如下:

auto

锚点transform-origin 指示的点相同。

具体来说,transform-origin计算值被解析为相对于元素参考框<position>

<position>

锚点是解析 <position> 相对于元素参考框的结果。

测试

此问题针对哪个盒子进行解析,正在 问题 503 中讨论。

以下说明如何设置盒子的锚点
#plane {
        offset-anchor: center;
    }
    

形状中间的红点表示形状的锚点

带有锚点的形状
平面形状中间的红点表示形状的锚点
此示例显示了具有不同锚点的四个盒子的对齐方式。
<style>
        body {
        transform-style: preserve-3d;
        width: 300px;
        height: 300px;
        border: 2px solid gray;
        border-radius: 50%;
        }
        .box {
        width: 50px;
        height: 50px;
        background-color: orange;
        offset-position: 50% 50%;
        offset-distance: 100%;
        offset-rotate: 0deg;
        }
        #item1 {
        offset-path: ray(45deg closest-side);
        offset-anchor: right top;
        }
        #item2 {
        offset-path: ray(135deg closest-side);
        offset-anchor: right bottom;
        }
        #item3 {
        offset-path: ray(225deg closest-side);
        offset-anchor: left bottom;
        }
        #item4 {
        offset-path: ray(315deg closest-side);
        offset-anchor: left top;
        }
    </style>
    <body>
        <div class="box" id="item1"></div>
        <div class="box" id="item2"></div>
        <div class="box" id="item3"></div>
        <div class="box" id="item4"></div>
    </body>
    
offset-anchor 示例
offset-anchor 示例
此示例显示了在其 offset-position 居中的盒子。
<style>
        body {
        width: 500px;
        height: 500px;
        }
        .box {
        background-color: mediumpurple;
        offset-path: none;
        offset-anchor: center;
        }
        #item1 {
        offset-position: 90% 20%;
        width: 60%;
        height: 20%;
        }
        #item2 {
        offset-position: 100% 100%;
        width: 30%;
        height: 10%;
        }
        #item3 {
        offset-position: 50% 100%;
        width: 20%;
        height: 60%;
        }
        #item4 {
        offset-position: 0% 100%;
        width: 30%;
        height: 90%;
        }
    </style>
    <body>
        <div class="box" id="item1"></div>
        <div class="box" id="item2"></div>
        <div class="box" id="item3"></div>
        <div class="box" id="item4"></div>
    </body>
    
offset-anchor: center 示例
'offset-anchor: center' 示例
此示例显示 offset-anchor 如何计算其 offset-position。
<style>
        body {
        width: 500px;
        height: 500px;
        }
        .box {
        background-color: mediumpurple;
        offset-path: none;
        offset-anchor: auto;
        }
        #item1 {
        offset-position: 90% 20%;
        width: 60%;
        height: 20%;
        }
        #item2 {
        offset-position: 100% 100%;
        width: 30%;
        height: 10%;
        }
        #item3 {
        offset-position: 50% 100%;
        width: 20%;
        height: 60%;
        }
        #item4 {
        offset-position: 0% 100%;
        width: 30%;
        height: 90%;
        }
    </style>
    <body>
        <div class="box" id="item1"></div>
        <div class="box" id="item2"></div>
        <div class="box" id="item3"></div>
        <div class="box" id="item4"></div>
    </body>
    
offset-anchor: auto 示例
'offset-anchor: auto' 示例

2.5. 旋转以匹配路径:offset-rotate 属性

名称: offset-rotate
值: [ auto | reverse ] || <angle>
初始值: auto
适用于: 可变形元素
继承:
百分比: 不适用
计算值: 计算的 <angle> 值,可选地以 auto 开头
规范顺序: 按语法
动画类型: 按计算值
媒体: 视觉

定义偏移变换的旋转分量, 可能基于偏移路径偏移位置处的方向。 值的含义如下:

auto <angle>?

偏移变换将具有一个旋转分量, 该分量等于偏移路径偏移位置处的方向与正 X 轴方向(即指向右侧的线)之间的差值。 有关如何计算此值的详细信息,请参见 SVG 的路径方向

如果使用 <angle> 指定, 则该角度将添加到旋转分量中。

注意:换句话说, 如果偏移路径向右移动,则 auto 不会添加任何旋转。 当它偏离正右方时, 旋转会匹配。 通过将 auto<angle> 结合使用, 您可以调整“起始”旋转。

reverse <angle>?

auto 相同, 但在旋转中额外增加了 180deg

<angle>

单独指定时, 会向偏移变换添加指定角度的旋转分量。 (也就是说,offset-rotate: 45deg; 类似于 transform: rotate(45deg); 它只是被排序为偏移变换的一部分。)

测试
以下示例使用平面形状。形状中间的红点表示形状的锚点。未设置偏移属性时,形状不会沿路径平移或旋转。
无偏移的路径
路径起点的黑色平面,未设置偏移属性。

当形状的锚点沿路径放置在不同位置且 offset-rotate0deg 时,形状不旋转。

无旋转的路径
蓝色虚线路径上不同位置的黑色平面,无旋转变换。

如果 offset-rotate 属性设置为 auto,并且形状的锚点沿路径放置在不同位置,则形状会根据当前位置的梯度进行旋转,并朝向该位置路径的方向。

自动旋转的路径
蓝色虚线路径上不同位置的黑色平面,沿路径方向旋转。

在此示例中,offset-rotate 属性设置为 reverse。平面在路径上的每个位置都朝向与路径相反的方向。

反向自动旋转的路径
蓝色虚线路径上不同位置的黑色平面,沿与路径相反的方向旋转。

最后一个示例将 offset-rotate 属性设置为 -45deg。 形状逆时针旋转 45 度一次,并在路径上的每个位置保持该旋转。

固定旋转的路径
蓝色虚线路径上不同位置的黑色平面,按固定角度旋转。
此示例显示 autoreverse<angle> 结合使用时的效果。 <angle> 的计算值会添加到 autoreverse 的计算值上。
<style>
        body {
        width: 300px;
        height: 300px;
        margin: 0px;
        border: solid gray;
        border-radius: 50%;
        }
        .circle {
        offset-position: 150px 150px;
        offset-distance: 86%;
        width: 42px;
        height: 42px;
        background-color: mediumpurple;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        }
        #item1 {
        offset-path: ray(0deg closest-side);
        offset-rotate: auto 90deg;
        }
        #item2 {
        offset-path: ray(45deg closest-side);
        offset-rotate: auto 90deg;
        }
        #item3 {
        offset-path: ray(135deg closest-side);
        offset-rotate: auto -90deg;
        }
        #item4 {
        offset-path: ray(180deg closest-side);
        offset-rotate: auto -90deg;
        }
        #item5 {
        offset-path: ray(225deg closest-side);
        offset-rotate: reverse 90deg;
        }
        #item6 {
        offset-path: ray(-45deg closest-side);
        offset-rotate: reverse -90deg;
        }
    </style>
    <body>
        <div class="circle" id="item1">1</div>
        <div class="circle" id="item2">2</div>
        <div class="circle" id="item3">3</div>
        <div class="circle" id="item4">4</div>
        <div class="circle" id="item5">5</div>
        <div class="circle" id="item6">6</div>
    </body>
    
offset-rotate 示例图像
盒子根据 auto 的值和一个固定角度进行旋转。

2.6. offset 简写

名称: offset
取值: [ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]?
初始值: 参见独立属性
适用于: 可变形元素
继承性: 参见独立属性
百分比: 参见独立属性
计算值: 参见独立属性
动画类型: 参见独立属性
规范顺序: 按语法
测试

这是一个用于设置 offset-positionoffset-pathoffset-distanceoffset-rotateoffset-anchor 的简写属性。省略的值将设置为其初始值。

2.7. 计算偏移变换

偏移变换是一个二维变换, 先平移后旋转:

3. <basic-shape> 的等效路径

[css-shapes] 给出的 <basic-shape> 定义将每个函数定义为生成一个形状——一个具有轮廓、内部和外部的二维图形。

本规范 invece 使用 <basic-shape> 生成一条路径——一条具有起点、终点和方向的线, 它恰好描绘出特定形状的轮廓。 构成路径的细节由 SVG 定义。 [SVG2]

所有 <basic-shape> 值的等效路径是:

<path()>
<shape()>

路径是已定义的路径。 [SVG11]

<circle()>
<ellipse()>

路径是圆形/椭圆形的轮廓。 它从圆形/椭圆的最右点开始, 然后由四个圆弧组成, 每个圆弧构成圆形/椭圆的四分之一, 顺时针进行, 最后以完成段的闭合路径操作结束。

rect()
inset()
xywh()

路径是(可能为圆角的)矩形的轮廓, 由四个或八个段组成 (取决于是否指定了圆角), 并以完成段的闭合路径操作结束。 它从顶部直边的左端开始, 紧邻任何圆角的右侧, 并向右(顺时针)继续。

<polygon()>

路径是多边形的轮廓, 由连接每个坐标对到下一个坐标对的直线段组成, 最后将最后一个连接回第一个, 并使用完成段的闭合路径操作。

对于所有这些, 路径上任意一点的方向 由 SVG 定义; 请参阅 SVG 2 § 9.4 路径方向性

注意:所有这些都旨在匹配为类似的 SVG 形状元素定义的“等效路径”。

注意:此列表应与 [css-shapes] 中定义的 <basic-shape> 函数的完整集合保持同步。 如果缺少任何内容, 则应将其视为规范错误。 此列表将来可能会移至 Shapes, 但目前仍保留在此处, 因为此规范是此信息的唯一使用者。

4. 隐私注意事项

本规范未引入新的隐私注意事项。

5. 安全注意事项

本规范未引入新的安全注意事项。

变更

本节内容不具约束力。

2018年12月18日 工作草案以来的变更

2015年4月9日首次公开发布工作草案以来的变更

致谢

感谢 fantasai、 Hyojin Song 以及 CSS 工作组所有其他成员 的审阅、评论和指正。

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语的组合来表达。本文档规范部分中的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”和“OPTIONAL”应按照 RFC 2119 中的描述进行解释。但是,为了便于阅读,这些词在本规范中不大写显示。

本规范的所有文本均为规范性文本,明确标记为非规范性的章节、示例和注释除外。[RFC2119]

本规范中的示例以“例如”一词开头,或使用 class="example" 与规范性文本分开,如下所示:

这是一个信息性示例的例子。

信息性注释以“注意”一词开头,并使用 class="note" 与规范性文本分开,如下所示:

注意,这是一个信息性注释。

建议是规范性章节,其样式旨在引起特别注意,并使用 <strong class="advisement"> 与其他规范性文本分开,如下所示:用户代理必须提供可访问的替代方案。

测试

与本规范内容相关的测试可以记录在像这样的“测试”块中。任何此类块都是非规范性的。


一致性类别

本规范的一致性针对三个一致性类别进行定义:

样式表
一个 CSS 样式表
渲染器
一个用户代理,它解释样式表的语义并渲染使用它们的文档。
创作工具
一个用户代理,它编写样式表。

如果样式表的所有使用本模块中定义的语法的语句都根据通用 CSS 语法和本模块中定义的每个特性的各个语法有效,则该样式表符合本规范。

如果渲染器除了按照相应规范的定义解释样式表外,还通过正确解析并相应地渲染文档来支持本规范定义的所有特性,则该渲染器符合本规范。但是,由于设备限制导致用户代理无法正确渲染文档,并不会使该用户代理不符合规范。(例如,用户代理不需要在单色监视器上渲染颜色。)

如果创作工具编写的样式表在语法上根据通用 CSS 语法和本模块中每个特性的各个语法正确,并且满足本模块中描述的样式表的所有其他一致性要求,则该创作工具符合本规范。

部分实现

为了使作者能够利用向前兼容的解析规则来分配回退值,CSS 渲染器必须将任何它们没有可用支持级别的 @ 规则、属性、属性值、关键字和其他语法结构视为无效(并酌情忽略)。特别是,用户代理不得在单个多值属性声明中选择性地忽略不支持的组件值并支持支持的值:如果任何值被视为无效(不支持的值必须如此),CSS 要求忽略整个声明。

不稳定和专有特性的实现

为避免与未来稳定的 CSS 特性发生冲突,CSSWG 建议在实现不稳定特性和 CSS 的专有扩展遵循最佳实践

非实验性实现

一旦规范达到候选推荐阶段,非实验性实现就成为可能,实现者应发布他们可以证明根据规范正确实现的任何 CR 级别特性的无前缀实现。

为了建立和维护 CSS 在不同实现之间的互操作性,CSS 工作组要求非实验性 CSS 渲染器在发布任何 CSS 特性的无前缀实现之前,向 W3C 提交一份实现报告(以及必要时,用于该实现报告的测试用例)。提交给 W3C 的测试用例将由 CSS 工作组进行审查和更正。

有关提交测试用例和实现报告的更多信息,请访问 CSS 工作组网站 https://www.w3.org/Style/CSS/Test/。问题应发送至 public-css-testsuite@w3.org 邮件列表。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性参考文献

[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS 背景与边框模块第 3 级。2024 年 3 月 11 日。CR。URL:https://www.w3.org/TR/css-backgrounds-3/
[CSS-BOX-3]
Elika Etemad. CSS 盒模型模块第 3 级。2024 年 4 月 11 日。REC。URL:https://www.w3.org/TR/css-box-3/
[CSS-BOX-4]
Elika Etemad. CSS 盒模型模块第 4 级。2024 年 8 月 4 日。WD。URL:https://www.w3.org/TR/css-box-4/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠与继承第 5 级。2022 年 1 月 13 日。CR。URL:https://www.w3.org/TR/css-cascade-5/
[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin. CSS 包含模块第 2 级。2022 年 9 月 17 日。WD。URL:https://www.w3.org/TR/css-contain-2/
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS 显示模块第 3 级。2023 年 3 月 30 日。CR。URL:https://www.w3.org/TR/css-display-3/
[CSS-IMAGES-4]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS 图像模块第 4 级。2023 年 2 月 17 日。WD。URL:https://www.w3.org/TR/css-images-4/
[CSS-SHAPES]
Rossen Atanassov; Alan Stearns. CSS 形状模块第 1 级。2022 年 11 月 15 日。CR。URL:https://www.w3.org/TR/css-shapes-1/
[CSS-SHAPES-2]
CSS 形状模块第 2 级。编辑草案。URL:https://drafts.csswg.org/css-shapes-2/
[CSS-TRANSFORMS-1]
Simon Fraser; 等。CSS 变换模块第 1 级。2019 年 2 月 14 日。CR。URL:https://www.w3.org/TR/css-transforms-1/
[CSS-TRANSFORMS-2]
Tab Atkins Jr.; 等。CSS 变换模块第 2 级。2021 年 11 月 9 日。WD。URL:https://www.w3.org/TR/css-transforms-2/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块第 4 级。2024 年 3 月 12 日。WD。URL:https://www.w3.org/TR/css-values-4/
[CSS-VALUES-5]
Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. CSS 值与单位模块第 5 级。2024 年 9 月 17 日。WD。URL:https://www.w3.org/TR/css-values-5/
[CSS21]
Bert Bos; 等。层叠样式表第 2 级修订版 1 (CSS 2.1) 规范。2011 年 6 月 7 日。REC。URL:https://www.w3.org/TR/CSS21/
[CSS3VAL]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块第 3 级。2024 年 3 月 22 日。CR。URL:https://www.w3.org/TR/css-values-3/
[RFC2119]
S. Bradner. RFC 中用于指示需求级别的关键词。1997 年 3 月。最佳当前实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[SVG11]
Erik Dahlström; 等。可缩放矢量图形 (SVG) 1.1 (第二版)。2011 年 8 月 16 日。REC。URL:https://www.w3.org/TR/SVG11/
[SVG2]
Amelia Bellamy-Royds; 等。可缩放矢量图形 (SVG) 2。2018 年 10 月 4 日。CR。URL:https://www.w3.org/TR/SVG2/

信息性参考文献

[CSS-MASKING-1]
Dirk Schulze; Brian Birtles; Tab Atkins Jr.. CSS 遮罩模块第 1 级。2021 年 8 月 5 日。CR。URL:https://www.w3.org/TR/css-masking-1/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS 定位布局模块第 3 级。2024 年 8 月 10 日。WD。URL:https://www.w3.org/TR/css-position-3/
[CSS-ROUND-DISPLAY-1]
Jihye Hong. CSS 圆形显示第 1 级。2016 年 12 月 22 日。WD。URL:https://www.w3.org/TR/css-round-display-1/
[MOTION-1]
Dirk Schulze; 等。运动路径模块第 1 级。2018 年 12 月 18 日。WD。URL:https://www.w3.org/TR/motion-1/

属性索引

名称 初始值 适用于 继承 百分比 动画类型 规范顺序 计算值 媒体
offset [ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]? 见独立属性 可变形元素 见独立属性 见独立属性 见独立属性 根据语法 见独立属性
offset-anchor auto | <position> auto 可变形元素 相对于元素参考框的宽度和高度 通过计算值 根据语法 auto 关键字或计算的 <position> 视觉
offset-distance <length-percentage> 0 可变形元素 相对于偏移路径长度 通过计算值 根据语法 计算的 <length-percentage> 值 视觉
offset-path none | <offset-path> || <coord-box> none 可变形元素 不适用 通过计算值 根据语法 按指定 视觉
offset-position normal | auto | <position> normal 可变形元素 参考包含块的大小 通过计算值 根据语法 normal 或 auto 关键字,或计算的 <position> 视觉
offset-rotate [ auto | reverse ] || <angle> auto 可变形元素 不适用 通过计算值 根据语法 计算的 <angle> 值,可选地前面有 auto 视觉

问题索引

所有这些示例都需要重写。
这个问题针对哪个盒子进行解析,正在 问题 503 中讨论。