What Are Transform(ation)s?
Transformations, in their strictest and broadest mathematical sense, are mathematical operations that map a set of items X onto another set, Y. In geometric terms, this means that we can apply a mathematical operation on a set of objects in space to map them onto a new space geometry.In layman's terms, we can take an object and apply what we call transformation groups. These are ordered lists of operations (called transforms) that we can use to move, scale, reflect, rotate and skew objects. Sounds simple enough, right?
But before we jump right into the whole business of object manipulation, we need to look into how these transformation groups work, exactly. As mentioned, transformation groups are an ordered set of transformation operations, the implication being that the order of transformations matters and gives different results depending on the ordering of those operations. This is because transformations take into account every object's geometric properties, including its current position.
Understanding the Transformation Origin
As an example, let's take a look at a very simple example. Say we have a rectangle of size 2×2 centered around the origin, (0,0):If we decide to scale the object by a factor of 2 and then move the object 1 unit to the right and 0.5 units upwards, we get the following result:
The result is exactly what we expected – the square is now 4×4 units in size and its center moved to the point (1, 0.5). But what if we reversed the order of the operations? Let's find out:
The result is correct, but it seems somewhat counter-intuitive – the center of the rectangle now lies at (2, 1) instead of (1, 0.5) as in the previous example. The reason behind this change in position is that transformations are dependent on the transformation origin and apply to all properties of the object, including its position. If the object is offset in relation to the transformation origin, its position gets transformed along with all the other properties. In our case, the x and y components of the object position were scaled by a factor of 2 as well.
If this seems a bit limiting or complicated, don't fret; although the transform origin is centered at (0,0) by default, we can change that by specifying it explicitly. Take the following example where we rotate a rectangle centered around (2,2) by 30 degrees clock-wise:
Because the object was offset from the origin, the whole rectangle rotated around the origin. If we wanted to rotate the object around, say, its top left corner, we could move the transformation origin to that point and then rotate the object:
There's a slight catch to this technique, though. You can only specify a single transformation group with a single transformation origin; this means that while you can specify an alternative origin, it cannot be changed while applying individual transformations within the group. The alternative is moving the object into position around the origin, applying the transformations and then moving the object back into place.
Screen space vs. Euclidean space
The more astute among you might have probably noticed that I've used the classical Euclidean space in place of screen space to explain transformations. In reality, dealing with computer graphics (and, of course, web pages) entails a shift in the way the coordinate system is positioned.As a convenience, the origin lies in the top left corner of every window and the y-axis points downwards so that every pixel on the screen can be described in terms of positive integers.
TILT!
Having covered the mathematical aspects of transformations, let's take a look at how we can apply them to elements using CSS.A word of caution before we proceed, though; since we're using features of CSS not yet present in every browser, we'll need to use vendor-spefic prefixes in addition to the standards-based CSS properties. See the Points of Interest section for ways of bypassing the redundancy of specifying cross-browser CSS transforms.
Transformation origin
To specify the transformation origin, we use thetransform-origin
CSS property:
- -moz-transform-origin: 50% 50%;
- -webkit-transform-origin: 50% 50%;
- -ms-transform-origin: 50% 50%;
- -o-transform-origin: 50% 50%;
- transform-origin: 50% 50%;
Transformation groups
To specify a transformation group, we use thetransform
CSS property and specify a list of transforms to apply, in order:
- -moz-transform:
> > ...;
- -webkit-transform:
> > ...;
- -ms-transform:
> > ...;
- -o-transform:
> > ...;
- transform:
> > ...;
Translation
To apply translation to an object, we use thetranslate
, translateX
and translateY
keywords:
- -moz-transform: translate(tx[, ty]) | translateX(tx) | translateY(ty);
- -webkit-transform: translate(tx[, ty]) | translateX(tx) | translateY(ty);
- -ms-transform: translate(tx[, ty]) | translateX(tx) | translateY(ty);
- -o-transform: translate(tx[, ty]) | translateX(tx) | translateY(ty);
- transform: translate(tx[, ty]) | translateX(tx) | translateY(ty);
tx
denotes a horizontal offset and ty
vertical. The following example shows how to move an image 60 pixels to the right and 20 pixels down:
- -moz-transform: translate(60px, 20px);
- -webkit-transform: translate(60px, 20px);
- -ms-transform: translate(60px, 20px);
- -o-transform: translate(60px, 20px);
- transform: translate(60px, 20px);
Scaling
To scale an object, we use thescale
, scaleX
and scaleY
keywords:
- -moz-transform: scale(sx[, sy]) | scaleX(sx) | scaleY(sy);
- -webkit-transform: scale(sx[, sy]) | scaleX(sx) | scaleY(sy);
- -ms-transform: scale(sx[, sy]) | scaleX(sx) | scaleY(sy);
- -o-transform: scale(sx[, sy]) | scaleX(sx) | scaleY(sy);
- transform: scale(sx[, sy]) | scaleX(sx) | scaleY(sy);
scale
keyword
and only specify a single argument, it will perform a uniform scale
(ie. will scale proportionally in both directions). Negative numbers
will scale and mirror the object across the respective axis.Here's an example of scaling down an object to 80% of its size towards to top right corner:
- /* set the origin to the top right corner */
- -moz-transform-origin: 100% 0;
- -webkit-transform-origin: 100% 0;
- -ms-transform-origin: 100% 0;
- -o-transform-origin: 100% 0;
- transform-origin: 100% 0;
-
- /* scale it down to 80% */
- -moz-transform: scale(0.8);
- -webkit-transform: scale(0.8);
- -ms-transform: scale(0.8);
- -o-transform: scale(0.8);
- transform: scale(0.8);
scaleY
value:
- /* set the origin to the middle of the element (default) */
- -moz-transform-origin: 50% 50%;
- -webkit-transform-origin: 50% 50%;
- -ms-transform-origin: 50% 50%;
- -o-transform-origin: 50% 50%;
- transform-origin: 50% 50%;
-
- /* vertical flip across the middle of the image */
- -moz-transform: scaleY(-1);
- -webkit-transform: scaleY(-1);
- -ms-transform: scaleY(-1);
- -o-transform: scaleY(-1);
- transform: scaleY(-1);
Rotation
To rotate an object, we use therotate
keyword:
- -moz-transform: rotate(
>);
- -webkit-transform: rotate(
>);
- -ms-transform: rotate(
>);
- -o-transform: rotate(
>);
- transform: rotate(
>);
- /* move the origin to the bottom right corner */
- -moz-transform-origin: 100% 100%;
- -webkit-transform-origin: 100% 100%;
- -ms-transform-origin: 100% 100%;
- -o-transform-origin: 100% 100%;
- transform-origin: 100% 100%;
-
- /* rotate 30 degrees clockwise */
- -moz-transform: rotate(30deg);
- -webkit-transform: rotate(30deg);
- -ms-transform: rotate(30deg);
- -o-transform: rotate(30deg);
- transform: rotate(30deg);
Skewing
To skew an object, we use theskew
, skewX
and skewY
keywords:
- -moz-transform: skew(
>[, >]) | skewX(>) | skewY(>);
- -webkit-transform: skew(
>[, >]) | skewX(>) | skewY(>);
- -ms-transform: skew(
>[, >]) | skewX(>) | skewY(>);
- -o-transform: skew(
>[, >]) | skewX(>) | skewY(>);
- transform: skew(
>[, >]) | skewX(>) | skewY(>);
skewX
and skewY
would affect the x and y axes respectively, they actually denote the direction in which the object is skewed.Let's look at an example:
- /* we fix the origin in the top left corner */
- -moz-transform-origin: 0 0;
- -webkit-transform-origin: 0 0;
- -ms-transform-origin: 0 0;
- -o-transform-origin: 0 0;
- transform-origin: 0 0;
-
- /* skew the object horizontally by 20 degress clockwise */
- -moz-transform: skewX(-20deg);
- -webkit-transform: skewX(-20deg);
- -ms-transform: skewX(-20deg);
- -o-transform: skewX(-20deg);
- transform: skewX(-20deg);
skewX
,
it will make the object lean to the right. Same goes for skewing
vertically, but this time, a positive angle denotes a clockwise
rotation:
- /* we fix the origin in the top left corner */
- -moz-transform-origin: 0 0;
- -webkit-transform-origin: 0 0;
- -ms-transform-origin: 0 0;
- -o-transform-origin: 0 0;
- transform-origin: 0 0;
-
- /* skew the object vertically by 20 degress anti-clockwise */
- -moz-transform: skewY(-20deg);
- -webkit-transform: skewY(-20deg);
- -ms-transform: skewY(-20deg);
- -o-transform: skewY(-20deg);
- transform: skewY(-20deg);
What actually happens is that after an object is skewed (the respective axis being rotated), the browser automatically adds a rotation that realigns the chosen axis (negatively equal to the skewing angle), effectively rotating the other axis. So basically, you are rotating the x axis by the given amount when performing a
skewX
transformation, but it is immediately followed by arotate(-angle)
operation which realigns the x axis.Still not sure which direction is which? Trial and error is usually the go-to method in this case. ;)
Farewell Horizon, We Knew Thee Well
Now that we've mastered the individual transforms, let's look into the techniques of using transform groups to achieve certain effects.A common technique to use with CSS transforms is the hover-tilt and hover-grow on buttons to communicate active elements and invite users to click on them. It is simply a composite transform that uses rotation and scaling to achieve the desired effect. Let's put a button in a box and apply the transforms:
- button {
- padding: 1em 2em;
- }
-
- button:hover {
- -moz-transform: rotate(3deg) scale(1.05);
- -webkit-transform: rotate(3deg) scale(1.05);
- -ms-transform: rotate(3deg) scale(1.05);
- -o-transform: rotate(3deg) scale(1.05);
- transform: rotate(3deg) scale(1.05);
- }
Transforms can even be combined with nested elements, each having their own set of transformation groups. A more elaborate example would be using a wrapping element around the button to rotate the wrapper in the opposite direction:
- .wrapper {
- margin: 5px;
- padding: 5px;
- background: red;
- }
-
- .wrapper:hover {
- -moz-transform: rotate(-3deg) scale(1.05);
- -webkit-transform: rotate(-3deg) scale(1.05);
- -ms-transform: rotate(-3deg) scale(1.05);
- -o-transform: rotate(-3deg) scale(1.05);
- transform: rotate(-3deg) scale(1.05);
- }
-
- .wrapper button {
- padding: 5px 10px;
- }
-
- .wrapper button:hover {
- -moz-transform: rotate(6deg) scale(1.05);
- -webkit-transform: rotate(6deg) scale(1.05);
- -ms-transform: rotate(6deg) scale(1.05);
- -o-transform: rotate(6deg) scale(1.05);
- transform: rotate(6deg) scale(1.05);
- }
2D transformations vs. 3D transformations
So at this point, you might be asking yourself what's stopping you from using a combination of these transforms to create a 3D transformation? Well, if you're content with using just orthographic projection, then you can use a combination of skewed objects to position and transform objects. If you're looking for true linear perspective (or any other non-linear projection), then you're out of luck.You see, skewing only changes the angle between the two axes, while a third dimension coupled with perspective adds another dimension which affects the distance between two points when projected on a plane – in other words, the farther away you are from an object, the smaller it seems. That's something that cannot be accurately reproducted using only 2D transformations.
If you're interested in 3D transformations, there are currently two options available: true 3D transforms using a syntax similar the 2D transform CSS properties or WebGL. Neither are currently supported in major stable browsers, so usage is limited to the latest and greatest browsers, and also out of the scope of this article.
If you're looking for an introduction, you can read about it on the Webkit blog that explains the first implementation of the emerging 3D transforms.
So, Where Can I Get Some?
Obviously, 2D transforms are something of a novelty among browsers; even though IE6 supported DXtransform through their proprietary filter CSS property, none of the other browsers implemented similar functionality until about 2 years ago, and even then it took a while for the other to pick up on it. The recent surge in browser development, though, caused all the major browser vendors to implement 2D transforms in their upcoming and current releases, some of them even using hardware acceleration to do the job.Currently, the browsers supporting said transforms include the following flock:
Browser | Since | Implementing |
---|---|---|
Internet Explorer | 5.5 |
|
9.0 |
| |
Firefox (Gecko) | 3.5 (1.9.1) |
|
Opera | 10.5 |
|
Safari (WebKit) | 3.1 (525) |
|
Chrome | 1.0 |
|
iOS | all versions | -webkit-transform (using WebKit engine) |
Points of Interest
Performance
With the browser support matrix you might be tempted to just go ahead and start sprinkling transforms left and right all over your sites. Technically, that is doable, but true cross-browser CSS transforms are costly, performance-wise.For browsers that do not support hardware accelerated 2D transforms (practically every currently stable browser on Windows and Linux, for example), all of the transforms are performed on the CPU, with Firefox pre-4.0 and Internet Explorer pre-9 being the prime examples of slow rendering engines. While both execute transformations correctly, they do suffer a performance penalty, which is most noticeable on IE (this problem was addressed with IE9's direct DOM hardware rendering acceleration). Sites which contain many transforms will degrade performance and on IE might cause
z-index
stacking problems.Rendering
The other caveat to be aware of relates to Chrome on various platforms – the edges of rotated and skewed images (but not other DOM elements) tend to be jagged instead of antialiased on Windows. This problem is even worse on Linux, since any rotated text is not antialiased and parts of letters can appear disconnected and broken, rendering most small font sizes unreadable when transformed.Think of the childr… I mean, users!
If you're still set on using CSS transforms (and you should be!), you can still provide alternative presentations and graceful degradation for users that don't have 2D CSS transform capabilities using Modernizr. With it, you can detect features of the browser and use pure CSS to style alternative presentations or even hide elements that would otherwise appear out of order. The examples nested withiniframe
s
in this article use it to present alternative presentations and notices
to users whose browser does not support the W3C-like syntax of CSS
transforms – try IE8-or an older version of, say, an order version of Camino or Konqueror.Also, if you dislike having to write multiple versions of CSS attributes, you might want to consider using cssSandpaper which generate all the different vendor-specific and standard syntaxes so they work cross-browser. In addition, it also translates the W3C syntax into DirectX filters to make transforms work even with Internet Explorer 5.5!
Understanding CSS3 2D Transforms
Reviewed by JohnBlogger
on
1:22 PM
Rating:
No comments: