teaching machines

CS 318: Lab 20 – Animations

Dear students,

Today we explore transitions to add a little life to our webpages using CSS transitions. As an example, we’ll create a list whose items pop out when hovered.

We start with a list:


Let’s add some background color to each item:

li {
  background-color: blue;
  color: white;

Let’s remove the bullets, shrink the size a bit, and decrease the padding:

ul {
  list-style: none;
  width: 200px;
  padding-left: 0;

Let’s space things out a bit:

li {
  /* ... */
  margin: 10px auto;
  padding: 20px;

Now let’s accentuate hovered list items:

li:hover {
  background-color: purple;
  transform: translate(20px, 0);

This is where transitions come in. In their absence, we move from hovered to non-hovered styles instantaneously. We want to smoothly traverse between the two states. We need to specify a few CSS properties to enable that blending:

  • transition-property: the names of the CSS properties that we want to blend
  • transition-duration: the time it takes for the transition to finish
  • transition-timing-function: the “directness” of the blending

Let’s make the list items transition between their left and background-color properties over half a second. We’ll start and end the transition slowly:

li {
  /* ... */
  transition-property: transform, background-color;
  transition-duration: 500ms;
  transition-timing-function: ease-in-out;

We can also express this in shorthand notation:

li {
  /* ... */
  transition: transform 500ms ease-in-out, background-color 500ms ease-in-out;

Here’s your TODO list:

  • Read CSS Transitions and Transforms for Beginners and chapter 11 in your textbook. On a quarter sheet, write down 2-3 questions, observations, or ideas for transitions you’d like to include in your client project.
  • A week from today we have our first prototype due. It will be reviewed by your peers in class, and it should be functional and content-complete. Would you like to have a workday next class period to work through issues together?

See you next time!



Our goal today is to add some life to our web pages by adding in some animations via CSS transitions. We’ll animate a hand of playing cards and a flower garden.

First create a lab20 directory. Add a partners.html and include your first names and last initials.


Your first challenge is to create a selectable hand of cards interface that behaves as follows:

Follow these steps to produce your interface:

  • Set all elements’ box-sizing property to border-box.
  • Create a container div to hold the hand of cards. Give it class hand.
  • Create five child labels within hand, each of class card.
  • Within each card, place a checkbox element followed by an img element. Have the image show a playing card of your choosing. These card images are in the public domain. No classes or IDs are needed for these elements.
  • Shrink the cards. Set card to have a fixed width in pixels of your choosing. We’ll refer to that width as W. Set the images to be as wide as their parent element. But don’t use W—use a percentage.
  • Overlay the checkbox on the bottom-left corner of the card. Recall that we use absolute positioning to anchor elements relative to their parents. Let card serve as an anchorable parent by making it relatively positioned. Then absolutely position input[type="checkbox"] against the bottom left of its parent. Add some spacing for aesthetics.
  • You may or may not see the checkboxes disappear after you absolutely position them. Probably they are behind the images. The front-to-back order of stacked HTML elements is determined by the z-index property. The larger the z-index number, the closer to the viewer the element is. The particular numbers are not important, only the relative order. Set the z-index of both the images and the checkboxes so that the checkbox is frontmost.
  • Overlap the cards. We’ll use absolute positioning to achieve this. Each card will be a bit more inset from its parent than the previous card. Set the positioning of hand to be relative so it can serve as an anchoring parent. Switch the positioning of card to absolute. Then set the left properties of each of the individual cards. The first card should have no offset. Inset the second by half of a card—which is half of W. Inset the third by a full card, and so on. To apply rules to individual cards, don’t add IDs. Use the nth-child selector.
  • Center hand. It’s a block element, so centering is done by constraining the width to something less than the full page and setting the left and right margin to auto. How wide should hand be to contain its children? You can calculate this exactly based on W.
  • Animate the selected cards to slide down from the hand when they are clicked on. (Because an image is part of a checkbox’s label element, we can click anywhere on the card to check it.) This will take a few steps to get right. First, write a transition rule for checked checkboxes that pushes the checkbox down. Use this pseudoselector: input[type="checkbox"]. Set the transform property to translate(0, OFFSET)—where OFFSET is some number of pixels of your choosing. Set the transition property so it animates to this transform.
  • The previous step only animated the checkbox, but not the image. In a perfect world, we could write a rule that shifted the entire parent card that surrounded a checked checkbox. Unfortunately, CSS does not currently support selecting the parent of some specified child element. However, we can select the immediate sibling with the + operator. To select a b that immediately follows a, we write a + b. Extend the rule you wrote in the previous step to apply both to the checkbox and to the img that follows the checked checkbox. Recall that we target a list of selectors by separating them with commas. We want something of this form: a, a + b. After this, both the checkbox and image should slide down.
  • When you unselect the card, it probably snaps immediately back into its default location. That’s a little too abrupt. Let’s also set the transition out. Write another rule nearly identical to the one you just wrote, but remove the :checked pseudoselector and zero out the offset. This rule will need to appear before the :checked version; otherwise it will override the checked version. When two rules have the same specificity—as these two do—whichever appears last wins.


Create in flowers.html and flowers.css an interactive floral arrangement that uses CSS transforms and transitions to ensnare the viewer in a state of blissful bee-ness:

Observe these requirements:

  • Set all elements’ box-sizing property to border-box.
  • Create a div with ID flowerbed.
  • Download and unzip these flower icons, courtesy of Freepik. The license of these images require attribution, which we will attend to later.
  • Add sixteen img elements to flowerbed for each of these images. Not all the files have the same resolution, which will frustrate our perfect 4×4 grid. Use CSS to uniformly set each image to a 129×129 square. Add a 10-pixel margin all around to space them apart a bit.
  • To get the images to form a grid with no additional HTML markup, have them all float left. To break them up into rows, we need the images in the first column to clear the ones previous. However, don’t create special IDs or a special class for this. Use an nth-child selector. Recall that one can match a numeric cycle using a form of this selector:
    ...:nth-child(An+B) {
      /* ... */
    A represents the length of the cycle’s period. For example, 3n would match every third child: 3, 6, 9, 12, and so on. B lets us tack on an offset. 3n+2 would match children 2, 5, 8, 11, 14, and so on. In our case, we want to match children 1, 5, 9, and 13 and have those clear their predecessor floats. (Child 1 will have nothing to clear.) What period and offset do we want to use here?
  • When an image is not hovered but another image is, reduce its opacity to 10%. It might be tempting to use the sibling selector (~) for this. Go ahead and watch it fail:
    img:hover ~ img {
      /* ... */
    As you should see, the sibling selector only matches images after the hovered image. It’s really a subsequent sibling selector. What we can do instead is use a descendant selector. Select all images that are children of a hovered flowerbed and reduce their opacity to 10%.
  • But we want the image that is hovered over to stay at its full opacity. Add a rule for this. If this new rule doesn’t seem to have any effect, it may not have a high enough specificity to beat out the 10% rule.
  • Augment your hovered image rule to scale the image 1.5 times its normal size and rotate it 180 degrees. Consult MDN’s documentation on the transform property.
  • Set the image to transition smoothly between its hover and non-hovered opacity and transform properties. Ease the transition in and out over a span of 2 seconds. Since we’ve got multiple properties that we want to transition, the CSS is cleaner if you set the transition- properties separately. If you use the shorthand notation, you have to repeat the durations and timing functions. That’s not fun. Instead, set the standalone transition-duration and transition-timing-function properties to the single value shared by each transition. Set transition-property to the list of properties to animate.
  • In your testing, you should find that sometimes the non-hovered flowers appear on top of the hovered one. If you don’t see this, increase the non-hovered opacity temporarily so that you can see it. This happens because the browser renders subsequent elements on top of previous elements. We can force a different ordering using the z-index property. Set the z-index of your images in their hovered and non-hovered states so that hovered images appear on top of non-hovered images. Add z-index to your list of transition properties. For z-index to have any effect, the element must not be statically positioned. Use relative positioning instead.
  • Center flowerbed within the webpage, both vertically and horizontally. The width-margin technique doesn’t work for vertical centering, so don’t use it here. Instead, use absolute positioning on flowerbed. Anchor its top-left corner to 50% point of its parent. Then translate it up and left -50% to compensate.
  • The license of the icons requires attribution. Add the message “Icons courtesy of Freepik” and have it link to their website: http://www.freepik.com. Anchor the link to the bottom-right of the page.

Publish and Validate

Commit and push your work. Verify that all pages have been uploaded by visiting https://USERNAME.github.io/cs318/lab20 in your browser.

Validate your pages with the W3C Validator. Paste in the URLs to your pages, one at a time, and address all concerns raised by the validator. Fix your changes on the local machine, commit, and push until the validator reports no errors or warnings.


Leave a Reply

Your email address will not be published. Required fields are marked *