Monday, April 30, 2012

How I Work: Yahoo!’s Doug Crockford On JavaScript

Welcome to the first in a new series of interviews called “How I Work”. These interviews revolve around how thinkers and creators in the Web world design, code, and create. The goal is not to get into the specific nuances of their craft (as that information already exists online), but rather step back and learn a bit about their habits, philosophies, and workflow for producing great work.

Meet Doug Crockford

First up is Douglas Crockford who believes JavaScript might just be the most elegant language ever. Learn why he thinks you should study the history of computer science, the value of reading your code in front of other people, and that jQuery really is a good thing.
Douglas Crockford is known as The JavaScript Guy. He’s famous not only for his O’Reilly book JavaScript: The Good Parts but even more so as the visionary behind the JSON data format as well as the JSLint tool. He was featured in the book Coders at Work for his contributions and philosophies on what JavaScript got right, and what it didn’t.
As a native of Southern California, Doug has the build of a surfer; lean and tall with white hair and a beard. A veteran of Silicon Valley, he’s worked at Atari Labs, founded and worked at numerous software start-ups, was head of technology at Lucas Films and now has the enviable job of being a JavaScript evangelist at Yahoo!.
Douglas Crockford
Image credits go to Eric Miraglia.
Self-taught (as many of the greats are), he says his goal is simply to get more people coding in JavaScript, or any language for that matter. While his day job may be as a JavaScript evangelist, speaking with Doug you get the sense he really is an evangelist for programming in general.
Below is a conversation that took place in Bozeman, Montana prior to a talk at Montana State University. Doug freely shared his thoughts on great programmers, user empathy, and how JSON restored his faith in humanity.

Why do you feel programmers should study the history of Computer Science?

Well, first semester of physics is a history class. You study Galileo and Newton and all their contributions to the field and that gives us the overall view of physics. It’s a really nice place to start.
I wish CS would do that. It doesn’t seem to have enough value in its history and it’s a really amazing history that’s completely neglected. It’s rarely that the best idea won. So, we’ve taken different paths over the years and maybe haven’t realized why.
Ironically, despite the rate of change in technology, we see in the story of software that it takes a generation to retire or die off before we have a critical mass of bright young minds to embrace new ideas.
I think if people were more aware of their history, they could see these patterns more easily.

What were the traits of the weak programmers you’ve seen over your career?

That’s an easy one—lack of curiosity. They were so satisfied with the work that they were doing was good enough (without an understanding of what ‘good’ was) that they didn’t push themselves.
I’m much more impressed with people that are always learning. The brilliant programmers I’ve been around are always learning.
You see so many people get into one language and spend their entire career in that language, and as a result aren’t that great as programmers.

Do you feel that the pain a programmer goes through in learning a language contributes to this unhealthy attachment to using only one language?

My advice to programmers to avoid this trap is to learn lots of different languages. We’re in sort of a language renaissance right now and there are a ton of brilliant languages to learn from.
To learn new languages takes nights and weekends outside of work, and that’s a commitment. The great programmers are the people that are constantly picking a project and diving into it, learning a language that way.

In Coders at Work, you stress the importance of doing code readings with teams. Why do you feel it’s important to present your code in front of other people?

Well, over the years I noticed that there are some terrific programmers out there that are completely content to sit in their cave all day long writing brilliant code. But they don’t interact much with their team, which means it’s a lost opportunity for mentoring other members.
As you know, a lot of coders aren’t the most socially adept animals either.
So, my idea with code reading sessions is to provide a forum where people can come together and read for each other to get them out of their caves. The masters read for the beginners, and vice versa, as a team-building exercise.
The trick for success is to set up rules ahead of time so that nobody is going to get spanked and everyone is respectful in their feedback. It has to be a good learning experience for everyone. You have to be careful with a dysfunctional team, because it can quickly tear apart the group. But I always call the game before it gets that far.
The rules are that it’s about improving the quality of the code that we’re all responsible for, improving the quality of our team, and improving our individual capabilities.
Some people see this as a terrible time sink. Yet, I’ve found by doing this exercise, bugs are caught way ahead of time and you can prevent a team member from going off the tracks. But again, that’s not the goal, it’s about team building.
Over time the masters help pull up the beginners and the overall output from the team gets better.

Are programmers getting better at user empathy?

The best experience I had with empathy was working in marketing support. There were times I would go out into the field and hold hands with the customers and see the consequences firsthand of some of the crap we were delivering to them.
I was shocked when I moved into systems programming and how the programmers actually held the customer in contempt.
I think every programmer should work in customer support for the product they’re delivering.
It’s another case of over-specialization. “I just write the code,” is the response you get and the programmers don’t see it as a chance to improve peoples’ lives.

How much of a language do you need to know?

Virtually every programming language is too big. Language standards have difficulty removing unnecessary features but as users we can choose not to use it.
I would say you can do 100% with knowing 50% of the language.
The language that taught me that lesson the most was JavaScript, because it has more bad parts than good parts. It gave me a very strong motivation for figuring out what are the good parts and what are the bad parts, and what the criteria is for deciding what’s in or out.
And the good parts are just so good. Be sure to watch Doug’s Google Tech talk titled “JavaScript: The Good Parts.”

What approaches would you say a master has versus a beginner?

When I was a journeyman, I was a maximilist. I tried to use the whole language. While I don’t know if I would call myself a master now, I’m certainly a minimalist. I’ve tried to get good at using as little of the language as possible.
I place a lot of value in simplicity and minimalism.

What are your thoughts on jQuery? Some JS enthusiasts feel like it’s letting people off the hook from truly learning JS.

There is some really clever stuff in jQuery and I think John Resig did some very good work there.
I do have a problem with anybody doing anything without understanding what they’re doing. I’m not going to fault jQuery for attracting those sorts of people.
But I do think there are some other AJAX libraries that maybe doing a better job that aren’t quite as accessible. However, I think there is a place for all of these things.

When you were developing JSON was it tough to pull back and not put too much into it?

My design criteria were three things: minimal, contextual, and a subset of JavaScript.
The last constraint was to keep us from going off the rails and inventing new stuff. We had to only use stuff that was in JavaScript, which meant that our unicode handling wasn’t quite right because JS isn’t quite right, which was disappointing. We don’t have proper support for dates because JS didn’t have it. But we can work around both of these.
But it also meant that when somebody proposed, “Hey we should do this crazy thing” we could be like “Nope”. So, we had a really easy criteria for stopping extra features from being added.
One interesting story about leaving things out: as we got closer to releasing JSON I decided to take out the ability to do comments. When translating JSON into other languages, often times the commenting piece was the most complicated part. By taking the commenting out we reduced the complexity of the parsers by half—everything else was just too simple.
One of the best features of JSON is that it’s stable. If your program works now, it will work forever, and that is an attractive thing.
I still get notes from people saying they’ve got great ideas for the next version. But there isn’t going to be a next version. I always say you’re free to invent a new standard and promote it as much as you like.

How did JSON get adopted?

You know, the adoption of JSON sort of restored my faith in humanity because it was a good idea that won out, only because it was a good idea.
It was a case where there were no slick marketing campaigns. In 2001, I started working on it as a way to tie the browsers to the server. At the time, everyone thought XML had to be used or they’d say “that’s a great idea but JSON isn’t a standard”. So, I bought json.org, made a logo, threw up a Web page and it sat out on the Web for three years.
In the meantime, AJAX happened and when it became the way for writing applications JSON was there. There was counter promotion from the XML community, of course.
But when I arrived at Yahoo! some kids at the company started thinking it was okay to start shipping JSON API’s through Web services. And developers found the apps got faster and were easier to write.
It sort of took off from there—no slick campaigns. So a good idea based on simplicity won out for once.

Watch Doug Crockford At Google Speaking On “JavaScript: The Good Parts”

In this presentation from Google Tech Talks, Doug goes over the ideas behind his landmark book, JavaScript: The Good Parts, and dives into the areas of what JavaScript got right and what it didn’t. Learn about the history and common roadblocks programmers run into when developing with this language.

Learn About The JSON Saga

In this video, Doug tells the interesting tale of how JSON was discovered, and sheds some light on how it became a major standard for describing data in an interesting turn of events.



A Pure CSS3 Cycling Slideshow

Thanks to CSS3, we can create effects and animations without using JavaScript, which will facilitate the work of many designers.
But we must be careful to avoid abusing CSS3, not only because old browsers do not support all of its properties. In any case, we all see the potential of CSS3, and in this article we’ll discuss how to create an infinitely looping slider of images using only CSS3 animation.

To get a solid sense of the process from beginning to end, below is an outline of the article. Please note that this effect will only work properly in modern browsers that support the CSS3 properties being used.Pure CSS3 Cycle Slider

1. Introduction

To follow this tutorial, having a basic understanding of CSS, especially CSS3 transitions and keyframe animation, is important. Using this simple concept, we will see how to make a functional image slider.

Basic Concepts of CSS3 Transitions

Normally when you change a CSS value, the change is instant. Now, thanks to the transition property, we can easily animate from the old to new state.
We can use four transition properties:
  1. transition-property
    Defines the name(s) of the CSS properties to which the transitions should be applied.
  2. transition-duration
    Defines the duration over which the transitions should occur.
  3. transition-timing-function
    Determines how intermediate values of the transition are calculated. The effects from the timing function are commonly called easing functions.
  4. transition-delay
    Defines when the transition starts.
At the moment, CSS3 transitions are supported in Safari 3.2+, Chrome, Firefox 4+, Opera 10.5+ and IE 10. Because the technology is still relatively new, prefixes for browsers are required. So far, the syntax is exactly the same for each browser, with only a prefix change required. We will omit them in the snippets in this article, but please remember to include the prefixes in your code.
Let’s see how to apply a simple transition to a link:
01a {
02   color: #000;
03   transition-property: color;
04   transition-duration: 0.7s;
05   transition-timing-function: ease-in;
06   transition-delay: 0.3s;
07}
08 
09a:hover {
10   color: #fff;
11}
When assigning an animation to an element, you can also use the shorthand:
1a  {
2   color: #000;
3   transition: color 0.7s ease-in 0.3s;
4}
5 
6a:hover {
7   color: #fff;
8}
The W3C has a list of all “Animatable Properties.”

Basic Concepts of CSS3 Animations

CSS animation enables us to create animations without JavaScript by using a set of keyframes.
Unlike CSS transitions, keyframe animations are currently supported only in Webkit browsers and Firefox and soon in IE 10. Unsupported browsers will simply ignore your animation code.
The animation property has eight subproperties:
  1. animation-delay
    Defines when the animation starts.
  2. animation-direction
    Sets the animation to play in reverse on alternate cycles.
  3. animation-duration
    Defines the length of time an animation takes to complete one cycle.
  4. animation-iteration-count
    Defines the number of times an animation cycle should play before stopping.
  5. animation-name
    Specifies the name of the @keyframes rule.
  6. animation-play-state
    Determines whether an animation is running or paused.
  7. animation-timing-function
    Describes how an animation progresses over one cycle.
  8. animation-fill-mode
    Specifies how a CSS animation should apply styles to its target before and after executing.
Let’s see how to apply a simple animation to a div.
01/* This is the element we are applying the animation to. */
02 
03div {
04   animation-name: move;
05   animation-duration: 1s;
06   animation-timing-function: ease-in-out;
07   animation-delay: 0.5s;
08   animation-iteration-count: 2;
09   animation-direction: alternate;
10 
11   -moz-animation-name: move;
12   -moz-animation-duration: 1s;
13   -moz-animation-timing-function: ease-in-out;
14   -moz-animation-delay: 0.5s;
15   -moz-animation-iteration-count: 2;
16   -moz-animation-direction: alternate;
17 
18   -webkit-animation-name: move;
19   -webkit-animation-duration: 1s;
20   -webkit-animation-timing-function: ease-in-out;
21   -webkit-animation-delay: 0.5s;
22   -webkit-animation-iteration-count: 2;
23   -webkit-animation-direction: alternate;
24}
25 
26/* This is the animation code. */
27 
28@keyframes move {
29   from {
30      transform: translateX(0);
31   }
32   to {
33      transform: translateX(100px);
34   }
35}
36 
37@-moz-keyframes move {
38   from {
39      -moz-transform: translateX(0);
40   }
41   to {
42      -moz-transform: translateX(100px);
43   }
44}
45 
46@-webkit-keyframes move {
47   from {
48      -webkit-transform: translateX(0);
49   }
50   to {
51      -webkit-transform: translateX(100px);
52   }
53}
But we can use the shorthand property to conveniently set all of the animation properties at once.
1div {
2   animation: move 1s ease-in-out 0.5s 2 alternate;
3   -moz-animation: move 1s ease-in-out 0.5s 2 alternate;
4   -webkit-animation: move 1s ease-in-out 0.5s 2 alternate;
5}

Keyframes

Each keyframe describes how an animated element should render at a given point in the animation sequence. The keyframes take a percentage value to specify time: 0% is the start of the animation, while 100% is the end. You can optionally add keyframes for intermediate animations.
01/* Animation from 0% to 100% */
02 
03@keyframes move {
04   0% { transform: translateX(0); }
05   100% { transform: translateX(100px); }
06}
07 
08/* Animation with intermediate keyframes */
09 
10@keyframes move {
11   0% { transform: translateX(0); }
12   50% { transform: translateX(20px); }
13   100% { transform: translateX(100px); }
14}
The W3C has a lot of useful and detailed information on “CSS3 Animations.”

Basic Structure of Our Slider

Now that we know how transitions and animation work, let’s see how to create our slider using only CSS3. This sketch shows how the animation should work:
Sketch animation slider function
How the animation slider functions
As you can see, the slider will be a container inside of which the images will be displayed.
The animation is very simple: the image follow a predefined path, animating the top property and changing the z-index and opacity properties when the image returns to its initial position.
Let’s dive right into the HTML markup to create the slider.

2. HTML Markup

The HTML markup is very simple; it’s all organized and SEO-friendly. Let’s see the full code first and then figure out in detail how everything works.
01<div class="container">
02   <div id="content-slider">
03      <div id="slider"<!-- Slider container -->
04         <div id="mask"<!-- Mask -->
05 
06         <ul>
07         <li id="first" class="firstanimation"<!-- ID for tooltip and class for animation -->
08         <a href="#"> <img src="images/img_1.jpg" alt="Cougar"/> </a>
09         <div class="tooltip"> <h1>Cougar</h1> </div>
10         </li>
11 
12         <li id="second" class="secondanimation">
13         <a href="#"> <img src="images/img_2.jpg" alt="Lions"/> </a>
14         <div class="tooltip"> <h1>Lions</h1> </div>
15         </li>
16 
17         <li id="third" class="thirdanimation">
18         <a href="#"> <img src="images/img_3.jpg" alt="Snowalker"/> </a>
19         <div class="tooltip"> <h1>Snowalker</h1> </div>
20         </li>
21 
22         <li id="fourth" class="fourthanimation">
23         <a href="#"> <img src="images/img_4.jpg" alt="Howling"/> </a>
24         <div class="tooltip"> <h1>Howling</h1> </div>
25         </li>
26 
27         <li id="fifth" class="fifthanimation">
28         <a href="#"> <img src="images/img_5.jpg" alt="Sunbathing"/> </a>
29         <div class="tooltip"> <h1>Sunbathing</h1> </div>
30         </li>
31         </ul>
32 
33         </div<!-- End Mask -->
34         <div class="progress-bar"></div<!-- Progress Bar -->
35      </div<!-- End Slider Container -->
36   </div>
37</div>
  1. div id="slider"
    This is the main container of the slider. It does not have a particular function, but we will need it to pause the animation.
  2. div id="mask"
    We will use this to hide everything that happens outside of the slider. In addition to hiding the content, the mask allows us to display the contents of the slider.
  3. li id="first" class="firstanimation"
    Every list item has an ID and a class. The ID displays the tooltip, and the class is tied to the animation that has to occur.
  4. div class="tooltip"
    This simply displays the title of the image. You can modify it to your needs; for example, by making it clickable and adding a short description.
  5. div class="progress-bar"
    This contains the function that shows the progress of the animation.
Now it’s time for the CSS file.

3. CSS Style

Let’s create the basic structure of the slider. It will have the same image size. The border property will be useful to create a frame around the image.
01/* SLIDER STRUCTURE */
02 
03#slider {
04   background: #000;
05   border: 5px solid #eaeaea;
06   box-shadow: 1px 1px 5px rgba(0,0,0,0.7);
07   height: 320px;
08   width: 680px;
09   margin: 40px auto 0;
10   overflow: visible;
11   position: relative;
12}
The mask class will hide all of the elements that lie outside of the slider; its height must be equal to the height of the slider.
1/* HIDE ALL OUTSIDE OF THE SLIDER */
2 
3#mask {
4   overflow: hidden;
5   height: 320px;
6}
Finally, to sort the list of images, we’ll have position: absolute and top: -325px so that all of the images are positioned outside of the slider.
01/* IMAGE LIST */
02 
03#slider ul {
04   margin: 0;
05   padding: 0;
06   position: relative;
07}
08 
09#slider li {
10   width: 680px/* Width Image */
11   height: 320px; /* Height Image */
12   position: absolute;
13   top: -325px; /* Original Position - Outside of the Slider */
14   list-style: none;
15}
With these few lines of code, we have created our slider. Now we just need to add the animation.

4. CSS3 Keyframes Animation

Slider Animation
Image animation for the slider
Before we begin with the animation, we have to specify some parameters in order to get the right view of the animation.
As we know, the total duration of the animation will be 25 seconds, but we have to know how many keyframes equals 1 second.
So, let’s work out a series of operations that gives us the exact number of keyframes based on the images we have and the total duration of the animation. Here are the calculations:
  1. Define the total number of images to use in the slider
    5
  2. Define the length of animation for each image
    5 seconds
  3. Define the total duration of the animation
    Multiply the total number of images by the duration of each image:
    5 images × 5 seconds = 25 seconds
  4. Calculate how many keyframes equals one second
    Divide the total number of keyframes by the total duration of the animation.
    100 keyframes / 25 seconds = 4 keyframes
    4 keyframes = 1 second
With all of this math, we can now apply the CSS animation to the slider. We will be able to put the animation on infinite loop because each image will follow its own animation that activates once it comes up in the slider.
01#slider li.firstanimation {
02   animation: cycle 25s linear infinite;
03}
04 
05#slider li.secondanimation {
06   animation: cycletwo 25s linear infinite;
07}
08 
09#slider li.thirdanimation {
10   animation: cyclethree 25s linear infinite;
11}
12 
13#slider li.fourthanimation {
14   animation: cyclefour 25s linear infinite;
15}
16 
17#slider li.fifthanimation {
18   animation: cyclefive 25s linear infinite;
19}
Once the properties of the animation have been assigned, we need to use keyframes to set the animation in motion.
Following this principle, we can connect the animations to each other even though they are separate, which will give us an infinite loop.
I’ve added the opacity and z-index properties to make the transition from one image to the next more attractive.
As you can see in the code, the first animation has more keyframes than the rest. The reason for this is that when the gallery is started, the first image is positioned to make way for the second image; but when the last image has finished its animation, the first image has to have additional keyframes in order for the user not to see a break between animation cycles.
Here is all of the code for the animations:
01/* ANIMATION */
02 
03@keyframes cycle {
04   0%  { top: 0px; } /* When you start the slide, the first image is already visible */
05   4%  { top: 0px; } /* Original Position */
06   16% { top: 0px; opacity:1; z-index:0; } /* From 4% to 16 % = for 3 seconds the image is visible */
07   20% { top: 325px; opacity: 0; z-index: 0; } /* From 16% to 20% = for 1 second exit image */
08   21% { top: -325px; opacity: 0; z-index: -1; } /* Return to Original Position */
09   92% { top: -325px; opacity: 0; z-index: 0; }
10   96% { top: -325px; opacity: 0; } /* From 96% to 100% = for 1 second enter image*/
11   100%{ top: 0px; opacity: 1; }
12}
13 
14@keyframes cycletwo {
15   0%  { top: -325px; opacity: 0; } /* Original Position */
16   16% { top: -325px; opacity: 0; }/* Starts moving after 16% to this position */
17   20% { top: 0px; opacity: 1; }
18   24% { top: 0px; opacity: 1; }  /* From 20% to 24% = for 1 second enter image*/
19   36% { top: 0px; opacity: 1; z-index: 0; }   /* From 24% to 36 % = for 3 seconds the image is visible */
20   40% { top: 325px; opacity: 0; z-index: 0; } /* From 36% to 40% = for 1 second exit image */
21   41% { top: -325px; opacity: 0; z-index: -1; }   /* Return to Original Position */
22   100%{ top: -325px; opacity: 0; z-index: -1; }
23}
24 
25@keyframes cyclethree {
26   0%  { top: -325px; opacity: 0; }
27   36% { top: -325px; opacity: 0; }
28   40% { top: 0px; opacity: 1; }
29   44% { top: 0px; opacity: 1; }
30   56% { top: 0px; opacity: 1; }
31   60% { top: 325px; opacity: 0; z-index: 0; }
32   61% { top: -325px; opacity: 0; z-index: -1; }
33   100%{ top: -325px; opacity: 0; z-index: -1; }
34}
35 
36@keyframes cyclefour {
37   0%  { top: -325px; opacity: 0; }
38   56% { top: -325px; opacity: 0; }
39   60% { top: 0px; opacity: 1; }
40   64% { top: 0px; opacity: 1; }
41   76% { top: 0px; opacity: 1; z-index: 0; }
42   80% { top: 325px; opacity: 0; z-index: 0; }
43   81% { top: -325px; opacity: 0; z-index: -1; }
44   100%{ top: -325px; opacity: 0; z-index: -1; }
45}
46@keyframes cyclefive {
47   0%  { top: -325px; opacity: 0; }
48   76% { top: -325px; opacity: 0; }
49   80% { top: 0px; opacity: 1; }
50   84% { top: 0px; opacity: 1; }
51   96% { top: 0px; opacity: 1; z-index: 0; }
52   100%{ top: 325px; opacity: 0; z-index: 0; }
53}
Having created the animations, we have to add a progress bar to display the duration of each animation.

5. Progress Bar

Progress bar Animation for each image
The progress bar for each animation
The process of animating the progress bar is the same as it was for the slider. First, we create the progress bar itself:
01/* PROGRESS BAR */
02 
03.progress-bar {
04   position: relative;
05   top: -5px;
06   width: 680px;
07   height: 5px;
08   background: #000;
09   animation: fullexpand 25s ease-out infinite;
10}
Don’t be afraid of the syntax here. It has the same function as from to; you can see that the keyframes set the appearance and disappearance of each image.
01/* ANIMATION BAR */
02 
03@keyframes fullexpand {
04   /* In these keyframes, the progress-bar is stationary */
05   0%, 20%, 40%, 60%, 80%, 100% { width: 0%; opacity: 0; }
06 
07   /* In these keyframes, the progress-bar starts to come alive */
08   4%, 24%, 44%, 64%, 84% { width: 0%; opacity: 0.3; }
09 
10   /* In these keyframes, the progress-bar moves forward for 3 seconds */
11   16%, 36%, 56%, 76%, 96% { width: 100%; opacity: 0.7; }
12 
13   /* In these keyframes, the progress-bar has finished his path */
14   17%, 37%, 57%, 77%, 97% { width: 100%; opacity: 0.3; }
15 
16   /* In these keyframes, the progress-bar will disappear and then resume the cycle */
17   18%, 38%, 58%, 78%, 98% { width: 100%; opacity: 0; }
18}

6. Tooltip

The slider is more or less complete, but let’s add a few details to make it more functional. We’ll insert tooltips for the image titles that will be visible on hover.
Simple Tooltip on image
Simple tooltip
Here is the CSS for the tooltips:
01   #slider .tooltip {
02   background: rgba(0,0,0,0.7);
03   width: 300px;
04   height: 60px;
05   position: relative;
06   bottom: 75px;
07   left: -320px;
08}
09 
10#slider .tooltip h1 {
11   color: #fff;
12   font-size: 24px;
13   font-weight: 300;
14   line-height: 60px;
15   padding: 0 0 0 10px;
16}
Here we’ve made only the image titles visible, but you can do the same to custom text, links or whatever you like.

7. CSS3 Transitions

Tooltip Animation
Animate the tooltip on hover
We have seen how to apply CSS3 transitions to elements; now let’s do it to the tooltips.
If you remember, we added an ID to each list (first, second, etc.) to have only the tooltip associated with an image appear on hover, rather than all of the tooltips appear together.
01#slider .tooltip {
02
03   transition: all 0.3s ease-in-out;
04}
05 
06#slider li#first: hover .tooltip,
07#slider li#second: hover .tooltip,
08#slider li#third: hover .tooltip,
09#slider li#fourth: hover .tooltip,
10#slider li#fifth: hover .tooltip {
11   left: 0px;
12}

8. Pause And Restart

Stop slider on mouse hover
Stop slider on mouse hover
To allow users to pause to read content or look at an image, we should stop the animation when they hover over an image. (We’ll also have to stop the animation of the progress bar.)
1#slider: hover li,
2#slider: hover .progress-bar {
3   animation-play-state: paused;
4}

9. Demo

Finally, we’ve reached the end of the tutorial. The slider is now 100% complete!
Pure CSS3 Cycle Slider
Pure CSS3 cycling slider demo
Check out the demo. It works in Firefox 5+, Safari 4+ and Google Chrome, as well as the iPhone and iPad. You can also download the ZIP file.
Thanks to Massimo Righi for his images.

10. Conclusion

The effect is impressive, but admittedly, this slider is not very versatile. For instance, to add more images, you have to edit all of keyframes. CSS3 has great potential, but it does have limits, and sometimes JavaScript is preferable, depending on your target users.
This slider has some interesting features, such as pausing on hover and uniques link for the images, which allow users to interact with the slider. If you want full support among browsers, this is not possible, so JavaScript is recommended. Unfortunately, CSS3 animation has many limitations; its lack of flexibility in particular will prevent its widespread use for now. Hopefully this will spur you on to further study of CSS3.
Feel free to share your thoughts in the comments section below!