Before we go too much further, there are some things you should know about how the transform property affects layout. When you apply the transform property to an element and its value is other than none , three things happen:
- the element becomes a containing block for child elements
- it establishes a new stacking context for the element and its children
- it imposes a local coordinate system within the element’s bounding box
Let’s look at these concepts individually. transform Creates a Containing Block
When an element is positioned—that is, when the value of the position property is something other static —it’s drawn relative to a containing block. A containing block is the closest positioned ancestor or, failing that, the root element (such as <htmL> or <svg> ) of a document.
Consider the example pictured below.
In this image, the child rectangle has a position value of absolute . Its right and bottom properties are both set to 0 . Its parent element has a position value of relative . Because the parent in this case is positioned, it becomes a containing block for the child. If the parent rectangle were not positioned, this child element would instead be drawn at the bottom right of the browser window.
Transforms work similarly. Setting the value of transform to something other than none turns the transformed element into a containing block. Positioned children of a transformed element are positioned relative to that element, as seen below.
In the image above, the parent element isn’t positioned. The transform property is what’s creating this containing block. A child element with position: absolute is nested within an element with transform: skewX(-15deg) .
transform Creates a New Stacking Context
A transform also creates a new stacking context for the element it’s applied to. As you may recall from Chapter 5, “Layouts”, elements within a stacking context are painted from back to front, as follows:
- child-stacking contexts with a negative stack level (for example, positioned z-index:-1 )
- nonpositioned elements
- child-stacking contexts with a stack level of 0 (for example, positioned and z-index:0; or z-index: auto; )
- child-stacking contexts with positive stack levels (for example, z-index: 1 ), which sit at the top of the stack
Setting the value of transform to something other than none makes the element’s stack level 0 . Transformed elements are stacked in front of non-positioned elements. The z- index values of each child element are relative to the parent. Let’s update our example from Chapter 5 to see how this works:
<div id=”b” style=”transform: scale(2) translate(25%, 15%);”>
<div id=”c” style=”position:relative; z-index: 1″>
<div id=”d” style=”position:absolute; z-index: -1″>
In this case, div#d sits at the bottom of the stack, and div#a sits above it (as pictured below). But div#b comes next because the transform property forces its z-index value to be 0 instead of auto . With z-index: 1 , div#c sits at the top of the stack.
Three-dimensional transforms add additional complexity. An element shifted along the Z-axis may render on a different plane from its container. Elements may also intersect with other elements across layers. Still, the basic rules of the stacking order apply.
Transformed elements may also overlap other elements on the page and prevent them from receiving mouse, touch, or pointer events. Applying pointer-events: none to the transformed element solves this issue.
Browsers apply transforms after elements have been sized and positioned. Unlike floated elements, transformed elements aren’t removed from the normal flow.
Because transforms are applied after the layout has been calculated, they don’t affect document layout. Transformed child elements may overflow the parent element’s bounding box, but they don’t affect the position of other elements on the page. They also don’t affect the HTMLELement.offsetLeft or HTMLELement.offsetTop DOM properties of an element. Using these properties to detect the rendered position of an element will give you inaccurate results.
Transforms do, however, affect client rectangle values and visual rendering of elements. To determine the rendered left and top positions of an element, use the HTMLELement.getCLientRects() or HTMLELement.getBoundingCLientRect() DOM methods (for example, document.getELementById(‘#targetEL’).getCLientRects() ). Because they don’t force the browser to recalculate page layout, transforms typically perform better than properties such as Left and height when animated.
transform Creates a Local Coordinate System
You may recall from geometry class that the Cartesian coordinate system is a way of specifying points in a plane. You may also recall that a plane is a flat, two-dimensional surface that extends infinitely along the horizontal and vertical axes. These axes are also known as the X-axis and Y-axis.
Point values along the X-axis increase as you move from left to right, and decrease from right to left. Y-axis point values decrease as you move up from the origin, and decrease as you move down. The X- and Y-axes are perpendicular to each other. Where they cross is known as the origin, and the coordinates of its location are always (0,0), as illustrated below.
A three-dimensional coordinate system also has a Z-axis. This axis is perpendicular to both the X- and Y-axes, as well as the screen (see the image below). The point at which the Z-axis crosses the X- and Y-axes is also known as the origin. Its coordinates are (0,0,0).
A rendered HTML document is also a coordinate system. The top-left corner is the origin, with coordinates of (0,0) or (0,0,0). Values increase along the X-axis as you move right. However, unlike the Cartesian system mentioned above, values along the Y-axis increase as you move down the screen or page. Z-axis values increase as elements move towards the viewer and decrease as they move away from the viewer.
Setting the value of transform to a value besides none creates a local coordinate system for the selected elements. The origin-point (0,0) or (0,0,0)—in this local coordinate system sits at the center of the element’s bounding box. We can change the position of the origin, however, by using the transform-origin property. Points within the element’s bounding box are transformed relative to this local origin.
The transform-origin Property
The transform-origin property accepts up to three values, one for each of the X, Y, and Z positions—for example, transform-origin: 300px 300px for a 2D transformation, or transform-origin: 0 0 200px for a 3D transformation.
If one value is specified, the second value is assumed to be center , and the third value is assumed to be 0px .
Both the X- and Y-coordinates may be percentages, lengths, or positioning keywords. Positioning keywords are Left , center , right , top , and bottom . The Z position, however, must be a length. In other words, transform-origin: left bottom 200px works, but transform-origin: left bottom 20% doesn’t.
Setting transform-origin moves the (0,0) point of the local coordinate system to a new location within the element’s bounding box. This, of course, modifies the transformation, sometimes radically. The image below shows a transform-origin point of 50% 50% and one at 0px 0px .
Now that you know a little more about how transforms affect document layout, let’s dig into the transform functions. This is how we make the magic. Transforms let us rotate, flip, skew, and scale elements. When combined with animations and transitions, we can create slick motion graphic effects.
Transforms can be grouped into two categories: 2D and 3D. Each group contains functions for rotating, skewing, scaling, and translating. 2D functions are concerned with transformations of points along the X- and Y-axes. 3D functions add the third dimension of depth and affect points along the Z-axis.
Source: Brown Tiffany B (2021), CSS , SitePoint; 3rd edition.