CSS Transition: -moz and -webkit vs CSS3
The Second Browser War of mid to late 2000s was long and bloody, but now it’s over. Even some guerrilla groups are still skulking in the trees of Internet, we’ll talk about them a little bit later.
Finally this war made Internet really better and clear, but it also left a number of deplorable consequences that we continue feeling today. In particular, it’s a big uncertainty among the web developers about the standards they should or shouldn’t use in the different situations. “Will the code I just wrote work properly in all the most popular browsers or not?” Not only junior, but even an experienced developer not always can answer this question without a full-scale testing.
CSS properties’ animation is the classic example of such a case. When and where to use –moz-transition (-webkit-transition, -ms-transition, -o-transition, etc.) or just transition separately, together or instead? To find a correct answer to all these questions we need to examine this issue in details.
Cascading Style Sheets standard evolution
The first official CSS specification was CSS level 1, published by W3C in December 1996. Very soon, in May 1998, CSS standard was extended to level 2 and the team began working on the new version, CSS 3. Today, after 15 years, this work is still not fully completed. With time, the specification was divided into several separate documents called "modules", some of which already became the standards while the others are still drafts.
In the meantime, the browser vendors kept developing of the new features in their own way and invent their own private standards, frustrating the web developer’s community more and more. In order to facilitate the use of these private extensions, one day they agreed on an intermediate standard called "known vendor prefixes": -moz for Mozilla (Gecko), -webkit for Apple Safari and Google Chrome, -ms for Microsoft Internet Explorer, -o for Opera, etc. Since this time the usual Cascading Style Sheet became looking like this one:
Backward compatibility: css -moz-transition, css -webkit-transition and css –o-transition
The –moz-transition property, which is shorthand for a set of individual components of the transition, is a Mozilla (Gecko) vendor-specific property, supported by Firefox. It allows you to set all the transition parameters in one line of code in the following format:
in the same way, -webkit-transition property is supported by Google Chrome and Safari browsers, and -o-transition is supported by Opera.
The values of property, duration, timing function and delay are the placeholders of the following individual properties’ values:
-moz-transition-property -webkit-transition-property -o-transition-property | specifies the name or names of the CSS properties to which transitions should be applied |
-moz-transition-duration -webkit-transition-duration -o-transition-duration | specifies the duration over which transitions should occur in seconds or milliseconds |
-moz-transition-timing-function -webkit-transition-timing-function -o-transition-timing-function | specifies a function to define how intermediate values for properties are computed. There are 5 supported functions: "ease", "linear", "ease-out", "ease-in-out" and "cubic-bezier" |
-moz-transition-delay -webkit-transition-delay -o-transition-delay | defines how long to wait between the time a property is changed and the transition actually begins, in seconds or milliseconds |
-moz-transition-property
-webkit-transition-property
-o-transition-property
specifies the name or names of the CSS properties to which transitions should be applied
-moz-transition-duration
-webkit-transition-duration
-o-transition-duration
specifies the duration over which transitions should occur in seconds or milliseconds
-moz-transition-timing-function
-webkit-transition-timing-function
-o-transition-timing-function
specifies a function to define how intermediate values for properties are computed. There are 5 supported functions: "ease", "linear", "ease-out", "ease-in-out" and "cubic-bezier"
-moz-transition-delay
-webkit-transition-delay
-o-transition-delay
defines how long to wait between the time a property is changed and the transition actually begins, in seconds or milliseconds
The transition-property may be an exact property name like "background-color", a comma separated list of property names like “width, height, color, background-color” or just "all". Refer the last draft of CSS Transition by W3C for the full list of animatable properties.
Example of –moz-transition use looks like the following:
In this case, when the background color of an element changes (for example using JavaScript), the change will be animated during two seconds using easy-in-out function and the animation will start after the one-second delay.
The new approach: cross-browser CSS3 transition
It’s a time for good news: finally, all the most popular browsers’ vendors came to agreement to use the same transition property without vendor prefix as defined in CSS3 standard and by the fall of 2013 the support for it was realized in the browsers. The following table shows the versions transitions property is fully supported from:
IE | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|
10.0 | 24.0 | 29.0 | 6.1 | 17.0 |
IE - 10.0
Firefox - 24.0
Chrome - 19.0
Safari - 6.1
Opera - 17.0
Although it’s still recommended to keep -moz-transition, -webkit-transition and -o-transition in the Cascading Style Sheets for the backward compatibility, in the future development we can breathe a sigh of relief and start using the one, single CSS transition with no restrictions.
The format of CSS3 transition properties is fairly similar to the described above. Like -moz-transition, -webkit-transition and –o-transition, the transition property is shorthand for a set of individual components of the transition:
The parameters are exactly the same as the corresponding parameters described above. So, to translate the previous example from browser-specific to cross-browser CSS3 version all we need is just to remove all the vendor-specific prefixes:
CSS transition using hover pseudo class
The most commonly CSS transitions are used with hover pseudo class. This approach allows making many beautiful user interface element with no JavaScript or jQuery code. The following two examples show how it can be done.
CSS transition button example
Let’s make a button. Instead of using the standard <input type=button> we’ll use an anchor element providing us with much more accurate control over its look and feel. In our example it will be just a link button. Of course, if you want to make a button with any other functionality you should add "onclick" event handler.
First of all we write the class for our button in the Cascading Style Sheet:
- font-sizemedium;
- padding8px 16px 8px 16px;
- text-decorationnone;
- border-radius4px;
- color#FFF;
- background-color#22b14c;
- transitionall .4s ease-in-out
Pay attention on the transition property. To ensure the animation smoothness we set the transition-property parameters to "all". The animation duration is .4s with easy-in-out function and without a delay.
Then we define how the button’s property should change when the mouse overs on it:
- background-color#ff9900
Finally, we put an anchor with our "button" class into HTML:
and that’s all. We can see our button in action:
Transition menu example
In the same manner we can make a site navigation menu. To make our menu horizontal we can use an unordered list with floating items. Again, first of all we should define the set of CSS classes. The class "menu" will be applied on the whole list:
- list-stylenone;
- padding0
Then we add classes for list items and anchors inside the menu:
- floatleft;
- padding0 2px 0 2px
- padding10px 20px 10px 20px;
- text-decorationnone;
- color#FFF;
- background-color#22b14c;
- transitionall .5s ease-in-out
and of course the hover pseudo class for the menu items when the mouse overs on them:
- background-color#ff9900
Finally, we put the menu code into the HTML:
- lia href#Homeali
- lia href#Productali
- lia href#Aboutali
and our menu is ready:
Transition with images
Hover pseudo class is very useful on desktops, but it’s meaningless on touch-driven devices like tablet or mobile. So, the Cheshire cat laugh in the following example will appear and disappear on the button clicks. In the HTML we’ll put two buttons named 'Show' and 'Hide' and the image, placed inside a div with black background color:
- img idthelaugh classlaugh-image srccheshircatlaugh.gif
Then we provide a CSS class for our image:
- opacity0;
- transitionopacity 1s linear
Initially its opacity is set to 0, so the image is hidden. The class also defines the ‘transition’ parameters. Pay attention that the ‘transition-property’ here is set specifically to ‘opacity’. Since an only one property of the image element is going to be changed, it’s unnecessary to use ‘all’ as in the two previous examples.
Now let’s write some code. I made in using jQuery, but it stands to reason that it could be done by a plain JavaScript as well.
- 'Show' button handler
- $("#showlaugh").click(function (e) {
- $("#thelaugh").css("opacity", "1");
- });
- 'Hide' button handler
- $("#hidelaugh").click(function (e) {
- $("#thelaugh").css("opacity", "0");
- });
The code is very simple and contains two button handlers. On the 'Show' button click we set the image 'opacity' style to 1, so the laugh appears. On the 'Hide' button click we set the opacity to 0, so the laugh disappears. That’s all:
Advanced control of CSS transition using JavaScript / jQuery
The last example still could be done using CSS only, but for more complicated functionality we certainly need some scripting code. If we want to make animation chains and loops and / or vary the values of element properties in different loop cycles we must detect the end of the transition. How we can do it?
Detecting the completion of a transition animation
It is an event that is fired when a transitions is complete. This event is named transitionend, and it offers two properties:
propertyName | a string containing the name of the CSS property whose transition completed |
elapsedTime | a float containing the number of seconds the transition had been running at the time the event fired |
propertyName
a string containing the name of the CSS property whose transition completed
elapsedTime
a float containing the number of seconds the transition had been running at the time the event fired
Please note that the transitioned event usually is fired separately for each transitioned property. For example, if element’s width and height were transitioned then transitioned event will be fired twice, one time for width and one time for height.
Transitionend event doesn't fire if the transition is aborted because the value of an animating property is changed before the transition is completed.
Use the addEventListener() method to receive this event as usual:
Till now everything is simple, but… haven’t you forgoten about the guerrilla groups? That’s the case. While the modern browsers already support the standard on desktop computers, on the mobile platforms some of them don’t. For example, Safari on my tablets doesn’t. So, to ensure that our code will work on every platforms and browsers we must also use the webkit-specific event named 'webkitTransitionEnd'. Fortunately, the properties it provides are exactly the same as a properties provided by the 'transitionend' event, so we can use the same handler function.
Now let’s prepare an example.
Transition animation chain and loop example
In order to illustrate the use of transitionend event let’s create an infinite animation loop of a square div element. Every odd cycle of our example we’ll turn the div into circle by setting its border-radius style to half of the element size, and every even cycle we’ll turn it back into squire. In addition, every cycle we’ll set our div’s color to a random value.
As usual, we start from Cascading Style Sheet defining as following:
- width160px;
- height160px;
- transitionall 2s linear
then we create a very simple HTML:
- div idmy-div classmy-divdiv
and finally we write a script controlling our animation:
- var myDiv = document.getElementById("my-div");
- var EvenCycle = true;
- register the transitionend event handler
- myDiv.addEventListener("transitionend",
- transitionEndHandler, true);
- and register the same event handler for webkitTransitionEnd
- myDiv.addEventListener("webkitTransitionEnd",
- transitionEndHandler, true);
- initially start the animation loop
- myDiv.style.backgroundColor = "gray";
- myDiv.style.borderRadius = "80px";
- function transitionEndHandler (e) {
- turn a rectangle into a circle and vice versa
- if (EvenCycle)
- myDiv.style.borderRadius = "0";
- else
- myDiv.style.borderRadius = "80px";
- EvenCycle = !EvenCycle;
- randomly change the color
- myDiv.style.backgroundColor =
- "rgb(" + Math.floor(Math.random() * 256) + "," +
- Math.floor(Math.random() * 256) + "," +
- Math.floor(Math.random()() * 256) + ",");
}
Putting all together we receive the following simple and nice animation: