Transform

offset-path

offset-path sets the path to place an element on, such as a curve, a straight line, or a circle. Where on the path it sits is set by offset-distance, and animating offset-distance moves the element along the path.

Syntax

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

Preview

Presets
Drag the bottom-right corner to resize

Code

.box > :nth-child(2) {
  offset-distance: 30%;
  offset-path: path("M 20 80 C 80 0 160 160 220 80");
}

Controls

offset-pathpath("M 20 80 C 80 0 160 160 220 80")
offset-path
Shape
Shape
Path data (written like the SVG d attribute, in px from the top-left of the box)

About

Writing the value

  • none: the initial value. There is no path, and the element stays where it is.
  • path("…"): draws the path the same way as the d attribute of an SVG path element. Write commands such as M (move to), L (line), Q and C (curves), A (arc), and Z (close back to the start), each followed by numbers in px.
  • ray(angle length contain): a straight line from the starting position. The angle is measured clockwise with 0deg pointing up. The length is one of closest-side (when left out; up to the nearest side), closest-corner, farthest-side, farthest-corner, and sides (until the line hits a side of the box in that direction), measured against the parent box (the containing block). With contain, the line gets shorter so the element stays inside the box even at the end of the path. The starting position is set by offset-position; with its initial value normal, it is the center of the parent box.
  • circle(radius): a circular path. Like the start of ray(), its center is the center of the parent box, and it runs clockwise from the rightmost point. The radius is a length, closest-side (when left out), or farthest-side.

You cannot pick them here, but other shape functions such as inset() and polygon(), and url(#id) pointing at an SVG shape, work too. You can also add which area of the parent box sizes the path, such as border-box.

The preview places the item 30% of the way along the path (offset-distance: 30%) and draws the path with gray dots. With the initial offset-rotate: auto, the arrow points in the direction the path runs.

When to use it

Use it to move icons or decorations along a curve, by animating offset-distance from 0% to 100% with @keyframes. Combining ray() with offset-distance also places elements at a set angle and distance from the center, like the numbers on a clock face.

Watch out

  • In the spec, path() coordinates are measured from the top-left of the parent box. Chrome measures them from the top-left of the element's own original position, so unless the element sits at the top-left of its parent box, the position differs between browsers. The preview puts the item at the top-left of the box, so both give the same position.
  • With offset-path, the element moves to the start of the path even when offset-distance is 0, and turns to follow the path. Like transform, it also creates a stacking context.
  • path() works from Chrome and Edge 64, Firefox 72, and Safari 16; ray() from Chrome and Edge 116, Firefox 122, and Safari 16; circle() from Chrome and Edge 116, Firefox 122, and Safari 18.

Comments