Thursday, September 13, 2012

CSS3 Transforms and Aligning DOM Elements

In a previous post, I did some experimenting to determine how using CSS3 transform rotations interacted with jQuery and DOM positioning. Based on those tests, I decided to move on to determining how to precisely align these elements to other elements on the page. The first observation I made when working on that test was that CSS3 transforms occur in a completely separate coordinate space than the DOM coordinate space. The ramifications of this behavior is that transforms can occur independently of other DOM positioning without affecting each other.

For instance, consider the following transform of two different elements. Both the red box and the blue box are rotated using the CSS3 transform rotate function. The black axis is the DOM axis and the red/blue axis are the transform axis for each box respectively. In this case, the origin of the transform is set to top/left. You can see that the two boxes are aligned so their top/left corners are at the (0,0) point of the transform axis. This point also corrisponds to the (0,0) point of the DOM axis since it also uses the top/left as the origin point.

However, you can change the origin point in the transform space to any other point on the element. In the following example, the bottom/right is the origin and the same rotation as above is performed. Notice the difference in the position of the elements relative to the position of the transform axis relative and the transform axises relative to the DOM axis.

Notice that the top/left corner in the DOM of both the first example and the second example are the same. When I realized that, it become evident that using the same point of origin in my transforms as the DOM would make position much easier.

Going back to using top/left origins, we can continue to investigate aligning the two elements relative to each other. By default, they are aligned at the top/left corner - but what if we want to align the top/middle of the red box with the bottom/left of the blue box. I've added those point in the image below.

There are several ways to align these points. I've created a series of tests in my sandbox to illustrate the approach and provide working code that will accomplish it.

The problem the different axis present is that DOM positioning occurs relative to the DOM axis. The transformed elements retain their original DOM top/left point on the DOM axis regardless of where the transformed element visually appears on the page. This is because the transform axis is independent of the DOM axis. This is a great feature as long as you are aware of its impact on the other CSS positioning styles. If you rely on absolute positioning and utilize transforms to manipulate elements, you will have to account for it either in the DOM positioning or the transform positioning.

This is where the examples lead - the last two lines show two different methods to handling positioning transformed elements. You can either calculate the transform that is occurring via the CSS yourself and account for it in the DOM positioning or you can use additional transform functions to manipulate the position of the element inside the transform coordinate space so the element is positioned properly relative to the DOM space.

The method you use is based entirely on what you're trying to accomplish. From my perspective, I'd say if the transform is basically static, then use the latter approach. If you need to animate or dynamically move the element around a path, than the former may be a better approach so you can pre-calculate the transforms to optimize the motion.