Manipulating CSS3 transitions using jQuery- creating a dropping text effect
Created: Oct 16th, 13'
CSS3 transitions are great; they help offload the tedious work from JavaScript when it comes to performing transition effects on the web page, such as moving an element from point A to B, fading it in/out, or basically any effect that involves the changing of one CSS property value to another. Yes CSS3 animations are awesome, but lets face it, CSS3 isn't a programming language (and rightly so), and can never match the logical prowess of JavaScript. This means while you can use CSS3 to implement the majority of a transition effect, often times JavaScript is still needed to polish it off and achieve the desired outcome. In this tutorial we'll examine how JavaScript can help with CSS3 transitions in the following ways:
- Dynamically set and reset the value of a CSS3 property
- Respond to when a CSS3 transition has completed, via the
transitionend
event.
We'll implement a dropping text example with our new found knowledge, where each character of a header sequentially drops away until the very last, at which time the header resets itself.
We'll be using jQuery 1.8+ as the foundation of this tutorial, as it offers a lot of convenience when it comes to working with CSS3, which you'll soon see how.
Setting CSS (and CSS3) properties in jQuery
Setting a CSS property in jQuery is simple enough, using the .css()
method:
$("#myelement").css({left:0, backgroundColor:'blue'})
This sets the element #myelement's "left
" and "background-color
"
properties to the indicated values.
When it comes to setting CSS3 property values, things usually get a lot
more hairy real fast. That's because of all the CSS3 vendor prefixes (ie:
-moz-
,
-webkit-
etc) one has to account for when setting the baseline property. To
set the CSS3 property "transform
", in jQuery your code may end
up looking something like this:
$("#myelement").css({
transform: 'translateY(300px) rotateZ(120deg)',
MozTransform: 'translateY(300px) rotateZ(120deg)',
WebkitTransform: 'translateY(300px) rotateZ(120deg)',
msTransform: 'translateY(300px) rotateZ(120deg)'
})
Do that a few times, and the last thing you'll want to be doing again is setting CSS3 properties using JavaScript!
There is good news, however, and that's also where jQuery comes into play. Starting in jQuery 1.8+, the framework will automatically detect and set the CSS3 property supported by the browser for you, allowing you to work with just the baseline CSS3 property. So in jQuery 1.8+, the above code would just be:
$("#myelement").css({transform: 'translateY(300px) rotateZ(120deg)'})
Ah that's more like it! Lets illustrate the advantage of this collaboration between JavaScript and CSS3 with the following simple example, which randomly tilts the letters of a headline various degrees:
Demo:
Howdy Mate!
The JavaScript code to tilt each letter of the text is:
jQuery(function(){
var $header1 = $('#header1')
$header1.lettering() // wrap <span class="charx"/ > around each character
within header using Lettering.js
var signage = [1,-1]
$header1.find('span').each(function(){
var degree = Math.round( Math.random() * 30 ) * signage[
Math.round(Math.random() * 1) ]
$(this).css({transform: 'rotate(' + degree + 'deg)'})
})
})
I'm using the plugin Lettering.js
to automatically wrap a <span>
element around each character of a text so
they can be styled and referenced individually. The key here is how we're
randomly generating a degree between -30 and 30, and setting each
character's "rotate()
" value so the degree of rotation is random. That's
what JavaScript brings to CSS3- a sense of chaos- I mean logic!
Manipulating CSS3 transition related properties in jQuery
Time to see how JavaScript works with CSS3 transitions now. There are 4 transition related CSS3 properties, plus a shorthand property:
CSS Property | JavaScript equivalent | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
transition | transition | Shorthand property to set up to 4 of the below property
values at once. Here are some examples: transition: all 0 ease 0; /* Default. No transition */ transition: color 25ms; transition: opacity, left 3s ease-in; transition: all 2s cubic-bezier(0, 0, 0.58, 1) 1s; |
||||||||||||||||
transition-property | transitionProperty | Sets the CSS properties that should be transitioned.
Defaults to all , or all properties inside the CSS selector.
Separate multiple CSS properties with a comma. |
||||||||||||||||
transition-duration | transitionDelay | The duration of the transition, such as 2s
for 2 seconds, 2000ms for 2000 milliseconds etc. Defaults
to 0, meaning no transition is rendered. |
||||||||||||||||
transition-timing-function | transitionTimingFunction | Defines the change in speed of the transition from start
to finish using a designated keyword or a
cubic-bezier curve function. Defaults to "ease ", or the bezier
function cubic-bezier(0.25, 0.1, 0.25, 1).The following values are supported:
|
||||||||||||||||
transition-delay | transitionDelay | Sets the delay before the transition will begin (in s or ms). Defaults to 0, which means immediately. |
Lets create a header now that when clicked on, its characters fall down
one by one. We'll set each character's transitionDelay
property
to be incrementally larger than the previous character's, so the dropping action occurs
sequentially:
Demo:
Click on me!
Lets look at this one's code in full. First, the CSS:
#header2{
font-family: 'Orbitron', sans-serif; /* font style. Default uses Google
fonts */
text-shadow: 2px 2px #B4EAF3, 3px 3px #B4EAF3, 4px 4px #B4EAF3, 5px 5px
#B4EAF3, 6px 6px #B4EAF3;
font-size: 64px; /* font size of text */
color: #207688;
letter-spacing: 15px;
font-weight: 800;
text-transform: uppercase;
position: relative;
}
#header2 span{
display: inline-block;
}
.dropped span{
-moz-transform: translateY(300px) rotateZ(120deg); /* rotate, translate, and
disappear */
-webkit-transform: translateY(300px) rotateZ(120deg);
transform: translateY(300px) rotateZ(120deg);
opacity: 0;
-moz-transition: all 0.3s ease-in;
-webkit-transition: all 0.3s ease-in;
-ms-transition: all 0.3s ease-in;
transition: all 0.3s ease-in;
}
We define a "dropped" CSS class that we'll defer adding to #header2 until the header is clicked on, applying the drop down effect. Now, to the JavaScript portion, which helps us do 3 things:
- Set the transition delay of each SPAN so their values increase sequentially from the previous.
- Add the "
dropped
" class to #header2 when header is clicked on. - Reset the text effect once we think all the text have fallen, by
dynamically removing the "
dropped
" class. The way we deduce when the animation has finished is by adding up the animation time of all the SPANs; we'll see a much better approach later, but for now this will suffice.
<script>
jQuery(function(){
var $header2 = $('#header2')
$header2.lettering() // wrap <span class="charx"/ > around each character
within header
var $spans = $header2.find('span')
var delay = 0
$header2.on('click', function(){
$spans.each(function(){
$(this).css({transitionDelay: delay+'s'}) // apply sequential trans
delay to each character
delay += 0.1
})
$header2.addClass('dropped') // Add "dropped" class to header to apply
transition
setTimeout(function(){ // reset header code
$spans.each(function(){
$(this).css({transitionDelay: '0ms'}) // set transition delay
to 0 so when 'dropped' class is removed, letter appears instantly
})
$header2.removeClass('dropped') // remove class at the "end" to
reset header.
delay = 0
}, 1800) // 1800 is just rough estimate of time transition will finish,
not the best way
})
})
</script>
<body>
<h3 id="header2" class="header">Click on me!</h3>
</body>
When $header2 is clicked on, we loop through each SPAN element containing a character and set its
transitionDelay
property to 0.1s greater than the previous.
Following that, the "dropped
" class gets added to it to kick off the
dropping animation, with one letter falling after the next. To reset the
animation at the end, a setTimeout()
function is used to
estimate when the animation will finish, and when that happens, set
transition-delay
on each character to 0 before finally removing the
"dropped
" class on their parent container. Setting transition-delay
to 0 is necessary, as otherwise, the same sequential delay of each character
will be applied when they reappear.
So we've seen how CSS3 properties- such as those related to transitions-
can be accessed in JavaScript to our delight. But this collaboration extends
beyond that. Whenever a transition runs, JavaScript's transitionend
event handler fires at the very end to let you respond programmically. It's
what we'll be using to supplant our setTimeout()
function above
with for more precise reaction to transition events. Lets look at that next.
- Manipulating CSS3 transitions using jQuery
- Using
transitionend
event to detect when a transition has finished
Using transitionend
event to detect
when a transition has finished