ray() CSS function

The ray() CSS function defines the offset-path line segment that an animated element can follow. The line segment is referred to as "ray". The ray begins from an offset-position and extends in the direction of the specified angle. The length of a ray can be constrained by specifying a size and using the contain keyword.

Syntax

css
/* all parameters specified */
offset-path: ray(50deg closest-corner contain at 100px 20px);

/* two parameters specified, order does not matter */
offset-path: ray(contain 200deg);

/* only one parameter specified */
offset-path: ray(45deg);

Parameters

The parameters can be specified in any order.

<angle>

Specifies the direction in which the line segment extends from the offset starting position. The angle 0deg lies on the y-axis pointing up, and positive angles increase in the clockwise direction.

<size>

Specifies the length of the line segment, which is the distance between offset-distance 0% and 100%, relative to the containing box. This is an optional parameter (closest-side is used if no <size> is specified). It accepts one of the following keyword values:

closest-side: Distance between the ray's starting point and the closest side of the containing block of the element. If the ray's starting point lies on an edge of the containing block, the length of the line segment is zero. If the ray's starting point is outside the containing block, the edge of the containing block is considered to extend to infinity. This is the default value.

closest-corner: Distance between the ray's starting point and the closest corner in the element's containing block. If the ray's starting point lies on a corner of the containing block, the length of the line segment is zero.

farthest-side: Distance between the ray's starting point and the farthest side of the containing block of the element. If the ray's starting point is outside the containing block, the edge of the containing block is considered to extend to infinity.

farthest-corner: Distance between the ray's starting point and the farthest corner in the element's containing block.

sides: Distance between the ray's starting point and the point where the line segment intersects the containing block's boundary. If the starting point is on or outside the containing block's boundary, the length of the line segment is zero.

contain

Reduces the length of the line segment so that the element stays within the containing block even at offset-distance: 100%. Specifically, the segment's length is reduced by half the width or half the height of the element's border box, whichever is greater, and never less than zero. This is an optional parameter.

at <position>

Specifies the point where the ray begins and where the element is placed in its containing block. This is an optional parameter. If included, the <position> value must be preceded by the at keyword. If omitted, the value used is the offset-position value of the element. If omitted and the element doesn't have an offset-position value, the value used for the ray's starting position is offset-position: normal, which places the element at the center (or 50% 50%) of the containing block.

Description

The ray() function positions an element along a path by specifying its location in a two-dimensional space through an angle and a distance from a reference point (polar coordinates). This feature makes the ray() function useful for creating 2D spatial transitions. For comparison, this approach differs from the method of specifying a point by its horizontal and vertical distances from a fixed origin (rectangular coordinates), which is used by the translate() function, and from moving an element along a defined path through animation.

As ray() works in 2D space, it's important to consider both the initial position and orientation of the element. When the ray() function is applied as the offset-path value on an element, here's how you can control these aspects:

Formal syntax

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

<ray-size> =
<radial-extent> |
sides

<position> =
<position-one> |
<position-two> |
<position-four>

<radial-extent> =
closest-corner |
closest-side |
farthest-corner |
farthest-side

<position-one> =
left |
center |
right |
top |
bottom |
x-start |
x-end |
y-start |
y-end |
block-start |
block-end |
inline-start |
inline-end |
<length-percentage>

<position-two> =
[ left | center | right | x-start | x-end ] && [ top | center | bottom | y-start | y-end ] |
[ left | center | right | x-start | x-end | <length-percentage> ] [ top | center | bottom | y-start | y-end | <length-percentage> ] |
[ block-start | center | block-end ] && [ inline-start | center | inline-end ] |
[ start | center | end ]{2}

<position-four> =
[ [ left | right | x-start | x-end ] <length-percentage> ] && [ [ top | bottom | y-start | y-end ] <length-percentage> ] |
[ [ block-start | block-end ] <length-percentage> ] && [ [ inline-start | inline-end ] <length-percentage> ] |
[ [ start | end ] <length-percentage> ]{2}

<length-percentage> =
<length> |
<percentage>

Examples

undefined

Defining the angle and starting position for a ray

This example shows how to work with an element's starting position and how the element's orientation is impacted by the specified ray angle.

CSS

css
.box {
  background-color: palegreen;
  border-top: 4px solid black;
  opacity: 20%;
}

.box:first-of-type {
  position: absolute;
}

.box1 {
  offset-path: ray(0deg);
}

.box2 {
  offset-path: ray(150deg);
}

.box3 {
  offset-rotate: 0deg;
  offset-position: 20% 40%;
  offset-path: ray(150deg);
}

.box4 {
  offset-position: 0 0;
  offset-path: ray(0deg);
}

.box5 {
  offset-path: ray(60deg closest-side at bottom right);
}

Similar to transform-origin, the default anchor point is at the center of an element. This anchor point can be modified using the offset-anchor property.

In this example, various offset-path: ray() values are applied to the boxes numbered 1 to 5. The "containing block" of each box is depicted with a dashed border. A faded box in the upper left corner shows each box's default position without any offset-position or offset-path applied, allowing for a side-by-side comparison. The top of each box is highlighted with a solid border to illustrate variations in ray starting points and orientations. After positioning at the ray's starting point, a box aligns with the direction of the specified ray angle. If offset-position is not specified, the default offset starting position of the ray is the center (or 50% 50%) of the box's containing block.

Result

Animating an element along the ray

In this example, the first shape is shown as a reference for its position and orientation. A ray motion path is applied on the other shapes.

CSS

css
body {
  display: grid;
  grid-template-columns: 200px 100px;
  gap: 40px;
  margin-left: 40px;
}

.container {
  transform-style: preserve-3d;
  width: 150px;
  height: 100px;
  border: 2px dotted green;
}

.shape {
  width: 40px;
  height: 40px;
  background: #2bc4a2;
  margin: 5px;
  text-align: center;
  line-height: 40px;
  clip-path: polygon(0% 0%, 70% 0%, 100% 50%, 70% 100%, 0% 100%, 30% 50%);
  animation: move 5000ms infinite alternate ease-in-out;
}

.shape2 {
  offset-path: ray(120deg sides contain);
}

.shape3 {
  offset-rotate: 0deg;
  offset-path: ray(120deg sides contain);
}

.shape4 {
  offset-position: auto;
  offset-path: ray(120deg closest-corner);
}

.shape5 {
  offset-position: auto;
  offset-path: ray(120deg farthest-corner);
}

@keyframes move {
  0%,
  20% {
    offset-distance: 0%;
  }
  80%,
  100% {
    offset-distance: 100%;
  }
}

Result

In the first two samples where offset-path is applied, notice the orientation of the shape without offset-rotate and with offset-rotate. Both these samples use the default offset-position value normal, and therefore, the path motion starts from 50% 50%. The last two offset-path samples show the impact of corner <size> values: closest-corner and farthest-corner. The closest-corner value creates a very short offset-path because the shape is already at the corner (offset-position: auto). The farthest-corner value creates the longest offset-path, going from the top-left corner of the containing block to the bottom-right corner.

Specifications

See also