CSS Animations Inspired By BBC's Match of the Day
Tags: motd, css, animation, showdev
Published: 2018-11-16 10:35:14

---
title: CSS Animations Inspired By BBC's Match of the Day
published: true
description: BBC's Match of the Day inspired CSS animations, this article shows you how to recreate those animations seen on TV 📺 using just CSS.
cover_image: https://github.com/deadlybyte/motd-css-animations/raw/master/cover-image.png
tags: motd, css, animation, showdev
---

![MOTD Match Stat's Animation Sequence](https://github.com/deadlybyte/motd-css-animations/raw/master/motd-match-stats-animation.gif)
<figcaption><abbr title="Match of the Day">MOTD</abbr> Match Stats Animation</figcaption>

I'm an avid football (soccer) fan (Wolverhampton Wanderers 🐺 / <abbr title="Athletic Football Club ">AFC</abbr> Bournemouth 🍒) and like nothing better than sitting down to watch the Premier League highlights on <abbr title="British Broadcasting Corporation">BBC</abbr>'s <abbr title="Match of the Day">MOTD</abbr> on a Saturday evening. After a game's highlights, the players and managers are interviewed and while these interviews are taking place, an array of stats and information is displayed to the viewer. This is achieved using fancy animation techniques which draw attention to key information. I've always been impressed with this and it looks super cool.

Feeling inspired, I wanted to recreate some of these animation sequences via <abbr title="Cascading Style Sheets">CSS</abbr>, so no JavaScript. This was a good opportunity to practise and learn new skills. The following guide will go through the steps to create the animations.

# Initial Project Setup
To make this simple, we'll create a single <abbr title="Hypertext Markup Language">HTML</abbr> page called *index.html* that will reference all the <abbr title="Hypertext Markup Language">HTML</abbr> and <abbr title="Cascading Style Sheets">CSS</abbr>, resulting in no JavaScript.

In the *index.html* file we'll create a div element with the class **container** that will have a child div element with the class **motd-card**. This div element will contain two div elements, one for the title and the other for the contents of the card. 


```html
<div class="container">
    <div class="motd-card">
        <div class="motd-card-title">Match Stats</div>
        <div class="motd-card-body">
        </div>
    </div>
</div>

```

The body div with the class **motd-card-body** will contain a further two div elements, one for the match details with a class of **match** and another with the class **attendance** for the number of people who attended the match.

```html
<div class="container">
    <div class="motd-card">
        <div class="motd-card-title">Match Stats</div>
        <div class="motd-card-body">
            <div class="match">
                <!-- Add match markup here -->
            </div>
            <div class="attendance">Attendance: 30,544</div>
        </div>
    </div>
</div>

```

The div with the class **match** will contain the following markup to style the teams and score data.

```html
<span class="team">Brighton</span><span class="score">1-0</span><span class="team">West Ham</span>

```

**Note:** Sorry West Ham fans, but the example I'm using is when Brighton beat West Ham 1-0 at Amex Stadium on the 5th October 2018.


Next, we need to add the <abbr title="Cascading Style Sheets">CSS</abbr> styles so the match stats are styled correctly and looks like that displayed on the <abbr title="Television">TV</abbr> 📺.

```css
html,
body {
    height: 100%;
}

body {
    background-color: #333;
    font-family: 'Ubuntu', Arial, Helvetica, sans-serif;
    margin: 0;
}

.motd-card {
    width: 275px;
}

.motd-card-title {
    background-color: #FFD130;
    color: #2B0400;
    font-weight: bold;
    padding: 8px 0 6px;
    margin: 0;
    overflow: hidden;
    text-align: center;
    text-transform: uppercase;
    white-space: nowrap;
}

.motd-card-body {
    background-color: #FFF;
    color: #2B0400;
    overflow: hidden;
}

.match {
    font-weight: bold;
    padding: 5px 0 0;
    text-align: center;
}

.team {
    text-transform: uppercase;
}

.score {
    background-color: #FFD130;
    padding: 2px 6px;
    margin: 0 6px;
}

.attendance {
    font-size: 0.75em;
    padding: 4px;
    text-align: center;
    text-transform: uppercase;
}
```

Make sure to add a link element within the head tag of the <abbr title="Hypertext Markup Language">HTML</abbr>, which links to the [Google Font Ubuntu](https://fonts.google.com/specimen/Ubuntu). This is so the text uses a similar sans-serif font to that used by the <abbr title="British Broadcasting Corporation">BBC</abbr>'s <abbr title="Match of the Day">MOTD</abbr>.


```html
<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
```

Completed *index.html* should look like the one below.

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
        <title>Match Of The Day CSS Animation</title>
        <style>
            html,
            body {
                height: 100%;
            }

            body {
                background-color: #333;
                font-family: 'Ubuntu', Arial, Helvetica, sans-serif;
                margin: 0;
            }

            .motd-card {
                width: 275px;
            }

            .motd-card-title {
                background-color: #FFD130;
                color: #2B0400;
                font-weight: bold;
                padding: 8px 0 6px;
                margin: 0;
                overflow: hidden;
                text-align: center;
                text-transform: uppercase;
                white-space: nowrap;
            }

            .motd-card-body {
                background-color: #FFF;
                color: #2B0400;
                overflow: hidden;
            }

            .match {
                font-weight: bold;
                padding: 5px 0 0;
                text-align: center;
            }

            .team {
                text-transform: uppercase;
            }

            .score {
                background-color: #FFD130;
                padding: 2px 6px;
                margin: 0 6px;
            }

            .attendance {
                font-size: 0.75em;
                padding: 4px;
                text-align: center;
                text-transform: uppercase;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="motd-card">
                <div class="motd-card-title">Match Stats</div>
                <div class="motd-card-body">
                    <div class="match">
                        <span class="team">Brighton</span><span class="score">1-0</span><span class="team">West Ham</span>
                    </div>
                    <div class="attendance">Attendance: 30,544</div>
                </div>
            </div>
        </div>
    </body>
</html>
```
{% codepen https://codepen.io/deadlybyte/pen/rqdXRq %}


# Creating The Animation Sequence

OK, so now the basic <abbr title="Hypertext Markup Language">HTML</abbr> and <abbr title="Cascading Style Sheets">CSS</abbr> has been written we can now concentrate on the match stats animation sequences. There are several parts to the animation. These can be broken down into three transitions:

* Entry on screen
* Displaying initial data
* Exit off screen

## Entry On Screen Animation

Entry on screen is the first transition and is how the animation enters the display. So the first thing that happens is the title for the bar gradually grows from the left until the bar is full width. We need to animate this first, so in <abbr title="Cascading Style Sheets">CSS</abbr> we can create animation keyframes using the <abbr title="Cascading Style Sheets">CSS</abbr> rule **@keyframes**.

<abbr title="Cascading Style Sheets">CSS</abbr> keyframes are what describe the animation sequence. During animation the <abbr title="Cascading Style Sheets">CSS</abbr> styles are changed accordingly as specified in the keyframe selectors. The browser works out the animation sequences that are needed in-between to make the animation smooth and seamless.

You can find out more about @keyframes rules by visiting the [MDN web docs - @keyframes](https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes).

To declare a <abbr title="Cascading Style Sheets">CSS</abbr> keyframes rule I've used the **@keyframes** along with a name that I can reference later on. For our initial animation we'll call it **expand-card-title**.

The **from** and **to** keyframe selectors can be used to control how the animation will start and end. Initially the title isn't visible, so the from width should be set to 0 pixels wide. When set to 0 then nothing is displayed. The end state needs to be the full width of the title which is 275<abbr title="pixels">px</abbr> wide.

Add the following keyframes rule to the end of the <abbr title="Cascading Style Sheets">CSS</abbr> style tag declared within the *index.html* file.


```css
@keyframes expand-card-title {
    from {
        width: 0;
    }
    to {
        width: 275px;
    }
}
```

The above keyframes rule will animate the width of the title until it reaches the full width.


### Animation <abbr title="Cascading Style Sheets">CSS</abbr> Properties

We now need to wire up the keyframes rule to the <abbr title="Cascading Style Sheets">CSS</abbr> class rule and this is done via the **animation-*** properties. The two important properties are the **animation-name** and **animation-delay**. The **animation-name** references the keyframes rule, so in the above case **expand-card-title**. The **animation-duration** expects a value defined in seconds (s) or milliseconds (ms) and this is how long the animation cycle should take to complete. For this animation we'll use 0.8s (800 milliseconds) as the value.

You can find out more about animation-* properties and there accepted values by visiting the [MDN web docs - animation](https://developer.mozilla.org/en-US/docs/Web/CSS/animation).

Find the <abbr title="Cascading Style Sheets">CSS</abbr> class **.motd-card-title** and make the following modifications.

```css
.motd-card-title {
    animation-duration: 0.8s;
    animation-name: expand-card-title;
    ...
}
```

Now the title animates as expected, however the body is still visible which isn't the desired outcome.

{% codepen https://codepen.io/deadlybyte/pen/zMBrzz %}

We'll need to hide the body, so we'll make a slight modification to the <abbr title="Cascading Style Sheets">CSS</abbr> class **.motd-card-body**. Therefore we'll need to add the property **max-height** and set the value to 0, which will make the body hidden from view.

```css
.motd-card-body {
    ...
    max-height: 0;
    ...
}

```

Once the above has been implemented, the title will now animate as desired.

{% codepen https://codepen.io/deadlybyte/pen/OBZLmx %}


## Displaying Initial Data Animation - Part I

The next transition is the initial display of data. This is achieved by moving the title up and revealing the body contents underneath. Firstly, we need to define the transition, which will move the title up. This is achieved by defining the keyframes rule **make-room-for-body**. Add the new keyframes rule after the **expand-card-title** rule.

```css
@keyframes make-room-for-body {
    from {
        top: 28px;
    }
    to {
        top: 8px;
    }
}
```

Again, we've used the **from** and **to** keyframe selectors to control the transition. In this case we want the card to move up allowing the contents to be shown.

Next we have to make a few modifications to the **.motd-card** selector. We need to add both the position and top properties to aid with making the card move up, which will make room for the contents.

```css
.motd-card {
    position: absolute;
    top: 28px;
    ...
}
```

Notice that the top is set to the same value 28<abbr title="pixels">px</abbr> as the top property in the **make-room-for-body** keyframes rule. This is so the animation uses the same value and doesn't judder around and look unnatural.

Find the **.motd-card-title** and make the following modifications.

```css
.motd-card {
    animation-name: make-room-for-body;
    animation-duration: 0.4s;
    animation-delay: 1s;
    ...
}
```

### Animation Delay <abbr title="Cascading Style Sheets">CSS</abbr> Property
Here I'll introduced another animation property called **animation-delay**. This is the time in either seconds (s) or milliseconds (ms) waited before the animation starts.

You can find out more about animation-delay and its accepted values by visiting the [MDN web docs - animation-delay](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay).


The **animation-delay** for the **make-room-for-body** needs to be higher than the duration of **expand-card-title** animation sequence (i.e. the expand-card-title transition has to be finished before we start the next transition). So setting the delay to a second means the **expand-card-title** transition would have completed as the duration for this is 0.8s. This allows for 0.2s delay before the next transition starts (0.8s + 0.2s = 1s).

Before we move on, we need to address the issue that the title is moving up as expected, but then jolts back down to its original position.

{% codepen https://codepen.io/deadlybyte/pen/bmMbvM %}

It's doing this because the transition finished and the top property is set to 8<abbr title="pixels">px</abbr>, yet the initial **motd-card** <abbr title="Cascading Style Sheets">CSS</abbr> class has the top property defined as 28<abbr title="pixels">px</abbr>. After the transition has finished the default <abbr title="Cascading Style Sheets">CSS</abbr> styles are restored and the top property is reset to initial value 28<abbr title="pixels">px</abbr>. This is what is causing the jolt.

### Animation Fill Mode <abbr title="Cascading Style Sheets">CSS</abbr> Property
The solution for this is **animation-fill-mode** property. This property can be used with the value forwards, which means the <abbr title="Cascading Style Sheets">CSS</abbr> styles that were defined in the final transition will be retained and stops the property values being reverted to their initial values.

You can find out more about animation-fill-mode and its accepted values by visiting the [MDN web docs - animation-fill-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode).

```css
.motd-card {
    ...
    animation-fill-mode: forwards;
    ...
}
```

{% codepen https://codepen.io/deadlybyte/pen/NErdBe %}


## Displaying Initial Data Animation - Part II

Now we can move on to the second phase of displaying the initial data transition, which involves showing the card body / content. We'll use the transition to reveal the card body by making the max-height property increase until all the content is completely visible.

For the next step, we need to setup a keyframes rule. This time will call it **reveal-card-body**. Add this keyframes rule after the other keyframes rules.

```css
@keyframes reveal-card-body {
    from {
        max-height: 0;
    }
    to {
        max-height: 100%;
    }
}
```

We now have to add the keyframes rule to the **.motd-card-body** selector using the **animation-*** properties. So find the **.motd-card-body** and add the following properties.

```css
.motd-card-body {
    animation-delay: 1s;
    animation-duration: 1s;
    animation-fill-mode: forwards;
    animation-name: reveal-card-body;
    ...
}
```

We use the **animation-fill-mode** property, as we don't want the max-height property to revert back to the value 0, which would make the content disappear. Using **animation-fill-mode** with the value of forwards will retain the max-height value to 100%, thus keeping the content visible after the transition has occurred.

Again we've used an animation delay of a second, as we want the first transition Entry On Screen to finish before this transition is started.

{% codepen https://codepen.io/deadlybyte/pen/xyjbZz %}


### Transition Timing Function <abbr title="Cascading Style Sheets">CSS</abbr> Property
However, the animation is still not smooth, so there's another property that we can use to make this transition smoother and this is called **transition-timing-function**.

By default, the value is set to ease. This is a transition effect that start slowly and then speeds up and the ends slowly. This doesn't give the smooth transition we require, therefore, I suggest we change this and use the ease-in-out value, which will transition with a slow start and end.

You can find out more about transition-timing-function and its accepted values by visiting the [MDN web docs - transition-timing-function](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-timing-function).

```css
.motd-card-body {
    ...
    transition-timing-function: ease-in-out;
    ...
}
```

To make it smoother still we can add a transition-timing-function property to the .motd-card <abbr title="Cascading Style Sheets">CSS</abbr> class with the value of ease-out.

```css
.motd-card {
    transition-timing-function: ease-out;
}
```

{% codepen https://codepen.io/deadlybyte/pen/wYjBdG %}

## Refactor

Before we go any further, we need to consider refactoring and making it easier for the next phase, which is the Exit Off Screen.

As with most <abbr title="Cascading Style Sheets">CSS</abbr> properties there is also a <abbr title="Cascading Style Sheets">CSS</abbr> property shorthand. You've probably seen these before a common shorthand property is the background property, where you can specify multiple <abbr title="Cascading Style Sheets">CSS</abbr> properties relating to the background in one handy property. For example:

```css
background: no-repeat url('../../media/examples/star.png');
```

The **animation-*** properties also have a shorthand version, which allows us to declare our animations using a short way. This shorthand also allows us to specify the transition-timing-function and multiple animations for the <abbr title="Cascading Style Sheets">CSS</abbr> class.

You can find out more about animation shorthand and its accepted values by visiting the [MDN web docs - animation](https://developer.mozilla.org/en-US/docs/Web/CSS/animation).

Let's refactor the **.motd-card-title** <abbr title="Cascading Style Sheets">CSS</abbr> class, remove the animation-* properties and replace with the following:

```css
animation: expand-card-title 0.8s;
```

{% codepen https://codepen.io/deadlybyte/pen/MPGYRG %}

That's a lot cleaner and easier to read, now let's refactor the **motd-card** <abbr title="Cascading Style Sheets">CSS</abbr> class by again removing the animation-* properties and the transition-timing-function properties and replace with the following:

```css
animation: make-room-for-body 0.4s ease-out 1s forwards;
```

Let's quickly explain what each value represents.

Value | Description
-- | -- |
make-room-for-body | The name of the keyframes rule
0.4s | The duration of the animation
ease-out | The transition-timing-function effect
1s | The animation delay
forwards | The animation-fill-mode

The order of these properties are crucial as the first time value is the duration and the second time value is the delay used for the transition.

{% codepen https://codepen.io/deadlybyte/pen/PyewMb %}

We'll now refactor the **.motd-card-body** <abbr title="Cascading Style Sheets">CSS</abbr> class, remove the animation-* and the transition-timing-function properties and replace with the following:

```css
animation: reveal-card-body 1s ease-in-out 1s forwards;
```
Again the values represent the animation name (reveal-card-body), animation duration (1s), transition timing function effect (ease-in-out), animation delay (1s) and the animation fill mode (forwards).

{% codepen https://codepen.io/deadlybyte/pen/WaJvbX %}

## Exit Off Screen Animation

As mentioned earlier in the refactoring using the animation shorthand <abbr title="Cascading Style Sheets">CSS</abbr> property we can now specify multiple animations, which brings us nicely onto the exit transitions.

So we've got the card to appear, but what about removing it and animating this. Well we're in luck and no we don't have to define more keyframes rules, as luckily the <abbr title="Cascading Style Sheets">CSS</abbr> animations specification support reversing a transition. How do we do that? Well the **animation-direction** property is the answer.

### Animation Direction <abbr title="Cascading Style Sheets">CSS</abbr> Property

The animation-direction can set whether an animation should play forwards, backwards, or alternating back and forth. As we want to reverse the animation, we can use the reverse value.

You can find out more about animation-direction and its accepted values by visiting the [MDN web docs - animation-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction).

But didn't we just refactor, so we didn't have to use the animation-* properties and used the animation shorthand <abbr title="Cascading Style Sheets">CSS</abbr> property instead. Yes, we did, it was just easier to explain and if you need any reference and support you can easily find the documentation.

We can now start to remove the card from the page. Before we do this, we must consider the timings as we want the content to be readable before it's removed. There's no point in removing it as soon as it's displayed as the user won't get a chance to read it.

We know it takes around a second to finish all animations and we want the content to be displayed for four seconds prior to starting the exit transition. Therefore, a delay of five seconds would be needed before we start the exit transition. With that in mind, we'll need to work backwards and apply this delay to the last transition. So, find the **.motd-card-body** <abbr title="Cascading Style Sheets">CSS</abbr> class and add another animation for the exit transition.

```css
.motd-card-body {
    animation:
        reveal-card-body: 1s ease-in-out 1s forwards,
        reveal-card-body: 1s ease-in-out 5s forwards reverse;
}
```
Animations are separated via a comma and we've placed them on separate lines, this makes it easier to read and maintain, but they can be placed on the same line. Don't forget to use the semi-colon (**;**) to mark the end of the animation property.

Regarding the second animation in the above exit transition, we want to keep the property values from the transition (in this case the max-height value of 0). Start at to and end with the from selector within the **keyframes** rule **reveal-card-body**.

{% codepen https://codepen.io/deadlybyte/pen/JmvdqR %}

We'll then need to move the title back down to the original top starting position of 28 pixels. So find the **.motdf-card** <abbr title="Cascading Style Sheets">CSS</abbr> class and add another animation for the exit transition.

```css
.motd-card {
    animation:
        make-room-for-body 0.4s ease-out 1s forwards,
        make-room-for-body 0.4s ease-out 6s forwards reverse;
    ...
}
```

Those that are eagle-eyed would have noticed that the delay has been set to six seconds, although before we mentioned that it should be five seconds. We've set it to six seconds as this will allow the **reveal-card-body** exit transition to complete first. This will give us the desired effect of the title moving back down to its original starting position.

{% codepen https://codepen.io/deadlybyte/pen/QZrbXY %}

Finally, we need to shrink the title and remove it from view. To do this find the **.motd-card-title** <abbr title="Cascading Style Sheets">CSS</abbr> class and modify accordingly:

```css
.motd-card-title {
    animation:
        expand-card-title: 0.8s,
        expand-card-title: 0.8s 6.4s forwards reverse;
    ...
}
```

We're delaying the exit transition by 6.4 seconds so the above exit transition **make-room-for-body** is completed before we trigger this transition. We've used forward here so the transition property is retained resulting in the card being removed from view.

{% codepen https://codepen.io/deadlybyte/pen/MPGajY %}

Now that it's complete, you can play around with the colours, size and speed. As a further step you could also add JavaScript to make the animation dynamic and remove the hard-coded values.

And that's it! You've built a <abbr title="Match of the Day">MOTD</abbr> inspired <abbr title="Cascading Style Sheets">CSS</abbr> animation. Below is the final version of the *index.html* file.

```html
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
  <title>Match Of The Day CSS Animation</title>
  <style>
    html,
    body {
      height: 100%;
    }

    body {
      background-color: #333;
      font-family: 'Ubuntu', Arial, Helvetica, sans-serif;
      margin: 0;
    }

    .container {
      align-items: center;
      display: flex;
      height: 100%;
      justify-content: center;
      margin: 0;
    }

    .motd-card {
      animation:
        make-room-for-body 0.4s ease-out 1s forwards,
        make-room-for-body 0.4s ease-out 6s forwards reverse;
      position: absolute;
      top: 28px;
      width: 275px;
    }

    .motd-card-title {
      animation:
        expand-card-title 0.8s forwards,
        expand-card-title 0.8s 6.4s forwards reverse;
      background-color: #FFD130;
      color: #2B0400;
      font-weight: bold;
      padding: 8px 0 6px;
      margin: 0;
      overflow: hidden;
      text-align: center;
      text-transform: uppercase;
      white-space: nowrap;
    }

    .motd-card-body {
      animation:
        reveal-card-body 1s ease-in-out 1s forwards,
        reveal-card-body 1s ease-in-out 5s forwards reverse;
      background-color: #FFF;
      color: #2B0400;
      max-height: 0;
      overflow: hidden;
    }

    .match {
      font-weight: bold;
      padding: 5px 0 0;
      text-align: center;
    }

    .team {
      text-transform: uppercase;
    }

    .score {
      background-color: #FFD130;
      padding: 2px 6px;
      margin: 0 6px;
    }

    .attendance {
      font-size: 0.75em;
      padding: 4px;
      text-align: center;
      text-transform: uppercase;
    }

    @keyframes expand-card-title {
      from {
        width: 0;
      }

      to {
        width: 275px;
      }
    }

    @keyframes make-room-for-body {
      from {
        top: 28px;
      }

      to {
        top: 8px;
      }
    }

    @keyframes reveal-card-body {
      from {
        max-height: 0;
      }

      to {
        max-height: 200px;
      }
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="motd-card">
      <div class="motd-card-title">Match Stats</div>
      <div class="motd-card-body">
        <div class="match">
          <span class="team">Brighton</span><span class="score">1-5</span><span class="team">West Ham</span>
        </div>
        <div class="attendance">
          Attendance: 30,544
        </div>
      </div>
    </div>
  </div>
</body>

</html>
```
Also get the latest source code from [GitHub](https://github.com/deadlybyte/motd-css-animations).