ray()
Baseline 2022
Newly available
Since September 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
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
/* 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%
and100%
, 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 theat
keyword. If omitted, the value used is theoffset-position
value of the element. If omitted and the element doesn't have anoffset-position
value, the value used for the ray's starting position isoffset-position: normal
, which places the element at the center (or50% 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:
- The element is initially positioned by moving the element's
offset-anchor
point to the element's offset starting position. By default, the ray's starting position is determined by theoffset-position
value. Ifoffset-position
is explicitly specified asnormal
(or omitted and allowed to default tonormal
), the element is positioned at thecenter
(or50% 50%
) of its containing block. Specifyingoffset-position: auto
sets the starting position at thetop left
corner (or0 0
) of the element's position. - The element is initially rotated such that its inline axis — its direction of text flow — aligns with the angle specified by
ray()
. For example, with theray()
angle of0deg
, which lies on the y-axis pointing up, the element's inline axis is rotated to be vertical to match the ray's angle. The element maintains this rotation throughout its path. To customize this behavior, use theoffset-rotate
property, which allows you to specify a different rotation angle or direction for the element, enabling more precise control over its appearance as it follows the path. For example, settingoffset-rotate: 0deg
will remove any rotation applied byray()
, aligning back the element's inline axis with the direction of text flow.
Formal syntax
<ray()> =
ray( <angle> &&
<ray-size>? &&
contain? &&
[ at <position> ]? )
<ray-size> =
closest-side |
closest-corner |
farthest-side |
farthest-corner |
sides
<position> =
[ left | center | right | top | bottom | <length-percentage> ] |
[ left | center | right ] && [ top | center | bottom ] |
[ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ] |
[ [ left | right ] <length-percentage> ] && [ [ top | bottom ] <length-percentage> ]
<length-percentage> =
<length> |
<percentage>
Examples
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
.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
-
box1
gets initially positioned such that its anchor point (its center) is at the default offset starting position (50% 50%
of the containing block).box1
is also rotated to orient it towards the0deg
angle of the ray. This will now be the starting point of the path. You can observe the change in position and rotation of the box by comparing it to the fadedbox0
on the left. The box is rotated to match the0deg
angle along y-axis, pointing up. The box rotation is evident from the orientation of the number inside the box. -
In
box2
, a greater positive angle of150deg
is applied to the ray to show how the ray angle works. Starting from the top-left corner, the box is rotated in a clockwise direction to reach the specified angle of150deg
. -
box2
andbox3
have the sameoffset-path
values. Inbox3
, anoffset-rotate
of0deg
is also applied to the element. As a result, the element will remain rotated at this specific angle all along the ray's path, and the element will not rotate in the direction of the path. Notice inbox3
that the ray path is at150deg
, but the box orientation will not change along the path because ofoffset-rotate
. Also note that theoffset-path
property ofbox3
does not specify a starting<position>
, so the ray's starting position is derived from the element'soffset-position
, which in this case istop 20% left 40%
. -
The
offset-position
ofbox4
is set to top-left corner (0 0
) of the containing block, and as a result, the element's anchor point and the offset starting position coincide. The ray angle of0deg
is applied to the element at this starting point. -
In
box5
, theoffset-path
property specifies theat <position>
value, which places the box at thebottom
andright
edge of the element's containing block and60deg
is applied to the ray's angle.
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
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
Specification |
---|
Motion Path Module Level 1 # ray-function |
Browser compatibility
BCD tables only load in the browser