logo
post image

How to Move an Element in a Circular Path with CSS Offset-Path (Motion Path)

In the tutorial How to Move an Element in a Circular Path with CSS we saw how an element can be moved along a circular path by animating the CSS transform property.

A second way of animating an element along a circular path is through CSS Motion Path. Motion Path is one the latest offerings of CSS, allows us to animate an element along a specified path (path is set through code).

Motion Path or Offset-Path in CSS is offered through 6 properties :

  1. offset-path : Defining a path along which an element is animated
  2. offset-distance : Defining the position of the element along the path
  3. offset-position : Defining the starting point of the element along the path
  4. offset-anchor : Defining the anchor point of the element (the point in the element that moves along the path)
  5. offset-rotate : Defining the orientation of the element as it moves along the path
  6. offset : Basically a shorthand for the above 5 properties

As of Jan 2017, only Chrome has implemented some of the offset propertiesoffset-path (partial), offset-distance & offset-rotation.

Demo - Moving Along a Circe by 120 Degrees from the Starting Point

How Circular Motion is Achieved

Firstly a circular path has to be defined in offset-path. Then the element can be moved in that path by animating the offset-distance property. Animating the property can be done through CSS transition, CSS animation or with the new Web Animations API. This tutorial covers animating with Web Animation API.

Step 1 : Defining a SVG Circular Path

Note that the circular path along which the element animates will be relative to its parent element.

Assume the circular path has a radius of 200px. This means that to accommodate the circle, parent must be 400px in width & height.
Also assume that the starting point of the path will be the topmost position of the circle. This path in SVG can be defined as :

M200,0 A200,200 0 1,1 200,400 A200,200 0 1,1 200,0

The path has been constructed using 2 SVG elliptical arcs :

  1. The parent container of the element has height and width equal to 400px. The origin (0,0) of the parent element is its top left corner. The drawn path will use this co-ordinate system.
  2. Move (starting point) to (200,0). Draw an elliptical arc with (200, 200) as radius. Set a valid value for large-arc-flag and sweep-flag so that the arc finishes at (200,400). (See Arcs for more information on SVG elliptical arcs)
  3. Now from this point (200,400) draw another elliptical arc with (200, 200) as radius. Finish the complete circle by setting the end point as the starting point (200,0).

The CSS properties of the child & parent would be like :

#parent {
	width: 400px;
	height: 400px;
	border: 1px solid rgba(0,0,0,0.1);
	border-radius: 50%;
}

#child {
	width: 100px;
	height: 100px;
	offset-path: path("M200,0 A200,200 0 1,1 200,400 A200,200 0 1,1 200,0");
	offset-rotation: 0deg;
}

Please note that above circle is the parent, and not the path defined. The parent has been given a border and a 50% border-radius so that it looks circular. In this case the path and the boundary of the parent matches.

Step 2 : Circular Motion by Animating Offset-Distance

Now that the path is set we can move the element in a circular path by animating the offset-distance property.

Assume that we have to move the element by 120 degrees. 120 degrees means 33.33% of the total distance in the path (120/360).

$("#button").on('click', function() {
	document.getElementById("child").animate([
			{ offsetDistance: 0 },
			{ offsetDistance: '33.33%' }
		], 
		{
			duration: 700,
			easing: 'linear',
			iterations: 1,
			fill: 'forwards'
		}
	);
});

This is how we can achieve circular motion.

There are Better Ways of Defining a Circular Path

SVG paths are difficult to create. But in case of a circular path, there is a simpler option to pass in the offset-path property. But unfortunately it has not been implemented in any browser as of now.

#child {
	offset-path: margin-box;
}

Setting offset-path : margin-box would essentially define the path as the margin boundary of the parent. If parent is circular in shape, the path would be circular too !

Unlike a SVG path, you can achieve responsiveness for mobile devices through this method.