CSS offset-anchor Property

The offset-anchor property defines the specific point on an element that is fixed to the motion path it is following.

selector { offset-anchor: [ auto | <position> ]; }
auto The anchor point defaults to the value of the transform-origin property.
<position> Defines the x and y coordinates of the anchor point using keywords like center, lengths, or percentages.

Code Examples

A basic example showing a red square following a curved path with its center fixed as the anchor point.

<div style="width: 100%; height: 300px; border: 1px solid #444444; position: relative;">
  <div style="width: 40px; height: 40px; background: #ff0000; offset-path: path('M 0 150 C 100 0, 300 0, 400 150'); offset-anchor: center; animation: travel 4s infinite linear;"></div>
</div>
<style>
  @keyframes travel {
    from { offset-distance: 0%; }
    to { offset-distance: 100%; }
  }
</style>

An advanced example using JavaScript to toggle the anchor point from the top-left corner to the center while the element is animating.

<div id="scene" style="width: 100%; height: 400px; background: #111111; display: flex; align-items: center; justify-content: center;">
  <div id="box" style="width: 80px; height: 80px; background: #00ff00; offset-path: path('M 0 200 L 400 200'); offset-anchor: 0% 0%; animation: move 3s infinite;"></div>
  <button onclick="shiftAnchor()" style="position: absolute; top: 10px;">Change Anchor</button>
</div>
<script>
  function shiftAnchor() {
    const box = document.getElementById("box");
    box.style.offsetAnchor = "50% 50%";
    box.style.background = "#0000ff";
  }
</script>
<style>
  @keyframes move {
    0% { offset-distance: 0%; }
    100% { offset-distance: 100%; }
  }
</style>

Pro Tip

You can use offset-anchor to create more realistic mechanical movements. For example, if you are animating a car, setting the anchor toward the front (like the front axle) makes the rotation look much more natural as it follows a curved path compared to just pivoting from the dead center.

Deep Dive

Think of offset-anchor like a thumb tack holding a photo to a map. If you move that photo along a drawn line using the "offset-path" property, the anchor is exactly where that tack is stuck through the photo. If the tack is in the top-left corner, the corner follows the line. If it is in the center, the photo stays centered on the line as it moves. It uses the same coordinate logic as "background-position", allowing you to pin any part of your element—the edge, the center, or even a spot outside the element—to the motion track. By default, it looks at your "transform-origin", but explicitly setting it gives you total control over the pivot point during animations.

Best Practices

Always define an explicit offset-anchor when your element has a complex shape or if you need it to be perfectly centered on a path. Using percentage values like "50% 50%" is usually the safest bet for responsive designs because it ensures the anchor stays relative to the element size even if the element grows or shrinks.

Common Pitfalls

The biggest mistake is trying to use offset-anchor without an "offset-path". If there is no path for the element to follow, this property has no visible effect. Another point of confusion is that the default "auto" value relies on "transform-origin", which might not be what you want if you have already transformed the element for other reasons.

Accessibility

Since this property is primarily used for motion, be aware that moving elements can cause issues for users with vestibular disorders. Always wrap high-motion animations in a "prefers-reduced-motion" media query to disable or simplify the movement for those users.

Dev Data Table: offset-anchor property

default auto
animatable yes
inherited no
experimental no
year_intro 2016
year_standard 2023
js_syntax_1 element.style.offsetAnchor = "50% 50%";
js_syntax_2 element.style.setProperty("offset-anchor", "top center");
js_note When manipulating this property via JavaScript, ensure the element also has an offset-path defined to see any visual movement.
browsers { "Chrome": 116, "Edge": 116, "Firefox": 114, "Safari": 17.2, "Opera": 102, "Chrome Android": 116, "Safari on iOS": 17.2, "Samsung Internet": 24, "Opera Mobile": 78 }
results render here...