This is part two of a four part tutorial that will teach you how to put together a holiday card generator you can share with friends and family. The tutorial will cover basic HTML, CSS, and Javascript to ensure that your creation will have proper structure, style and functionality. If you are interested in seeing what a finished product looks like, click here and scroll to the bottom to check out a generator our team put together.

Building a Holiday Card Generator

Fun With CSS

Welcome back! Now that we have our lovely card generator structured, it's time for some fun with CSS. CSS is wildly powerful and doesn't get enough credit for the hard work it does for your webpage. You can do so much with CSS, like:

- Spacing and positioning your elements
- Changing your font styles and colors
- Adding borders and background images
- Creating hover effects
- Animations and transitions
- Responsive design to add custom styling for different screen sizes

I can't help you too much with this step of the project - it's up to you to research the different CSS properties to achieve the card design you have in mind. It's your personal brand and style that will make your card unique. I start by sketching out a rough idea of what I want the end product to look like, choose my colour scheme and make sure I'm happy with my layout before getting started.

Before you start styling, I recommend getting familiar with Developer Tools, a very useful way to play with your CSS style and HTML page structure that is included in most browsers. You can open developer tools with right click -> inspect. Dev tools allows you to interact and change the HTML & CSS on any webpage and learning how to leverage the power of dev tools for exploring and playing with your code will drastically improve your life. Learn more about the different features and how to use DevTools in this tutorial or this video.

Styling Basic Card

Here's my beautiful, yet simple card. Let's explore some of the basic CSS styles I've used.

img

First up, take a look at the text container and you'll notice that lovely cursive font. Over in our index.html file we've included a link tag:

<link href="https://fonts.googleapis.com/css?family=Lato|Petit Formal Script" rel="stylesheet">

This little nugget is adding two fonts called 'Petit Formal Script' and 'Lato' to our project directly from Google Fonts. Google Fonts is a great free resource for adding more font variety to your projects than what your browser will include by default. If you want to add a custom fonts, browse their library and find a font that you enjoy and hit the red '+' button to genereate a link tag to include in your index.html file.

Once you've imported your desired fonts, you can use them by name in your CSS font-family declarations - below I've set all of the h1 & h2 tags to use our cursive 'Petit Formal Script' font imported from Google, and adjusted some of the default sizes to better suit the card container.

h2, h3 {
  color: darkred;
  font-family: 'Petit Formal Script', cursive;
}
h2 {
  text-align: center;
  font-size: 2.5rem;
}
h3 {
  font-size: 1.6rem;

}
p {
  font-size: 1.3rem;
  padding-left: 1rem;
}

I'ved also added padding to our paragraph (<p>). Padding or margins can be added to any of your elements to add help align and add buffer spacing between your elements. You can up on the box model or try out a Codecademy course to get a better understanding on how and when to use each box model property.

We've applied some padding, a maximum height and a few other small CSS tweaks to make sure our text content is well positioned within our card container. Feel free to play with this structure using your dev tools to tweak the card to your liking.

#card-container {
  background-color: white;
}
.text-container {
  padding: 4rem 1rem 2rem 1rem;
  max-height: 400px;
  overflow: hidden;
  word-wrap: break-word;
}
#card-from {
  float: right;
  padding-right: 1rem;
}

I've included this lovely festive image using the <img> tag, but you can use any image you'd like. In the code below, I've removed any margin and set it to occupy 100% of it's container's width. In this case, the image is in the two-thirds column, which means the image will stretch to fit the whole two-thirds of the card.

In order to prevent the image from stretching and distorting these family's faces, the property object-fit: cover; will ensure we preseve the original image's aspect ratio. Finally, we floated the image to the right of it's container to make sure there is no extra white space to the right of the image.

img {
  height: 400px;
  width: 100%;
  margin: 0;
  float: right;
  object-fit: cover;
}

CSS Animations

CSS animations are pretty mind blowing and it's incredible what some artists can creating using just code. Check out some of these animations if you don't believe me.

Animations can be used to create anything from a loading screen spinner to a pulsating gradient background - you can learn more about building your own animations, keyframes and animation properties in this article.

As someone who is admittedly artistically challenged, I like to stand on the shoulders of giants when I'm looking for a neat animation. Say we want to have a card that has blinking Christmas lights in it - I'm going to pop over to Google and ask the experts. A quick search for Christmas Lights CSS turns up CodePen links where kind folks have graced us with their CSS magic.

Don't celebrate Christmas, or maybe you're tired of looking at the lights? Tack 'CSS animation' on the end of your Google search and you will likely be in luck, like some Hanukkah candles or some falling snow. Keep in mind you'll likely need to tweak the CSS to fit in with your page structure and style.

Let's add some snow over the card image! We'll need to add <div id="snow"></div> to our card file to hold the snow animation just under the image - the image column in the card container should now look like this.

<div class="two-thirds column">
    <img src="./img/our-family.jpg">
    <div id="snow"></div>
</div>

Now we can add code for the snow CSS animation to the card.css file:

#snow{
    background: none;
    font-family: Androgyne;
    background-image: url('http://www.wearewebstars.dk/codepen/img/s1.png'),
    url('http://www.wearewebstars.dk/codepen/img//s2.png'), 
    url('http://www.wearewebstars.dk/codepen/img//s3.png');
    height: 400px;
    left: 0;
    position: relative;
    top: 0;
    width: 100%;
    z-index:1;
    -webkit-animation: snow 10s linear infinite;
    -moz-animation: snow 10s linear infinite;
    -ms-animation: snow 10s linear infinite;
    animation: snow 10s linear infinite;
}
@keyframes snow {
  0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
  50% {background-position: 500px 500px, 100px 200px, -100px 150px;}
  100% {background-position: 500px 1000px, 200px 400px, -100px 300px;}
}
@-moz-keyframes snow {
  0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
  50% {background-position: 500px 500px, 100px 200px, -100px 150px;}
  100% {background-position: 400px 1000px, 200px 400px, 100px 300px;}
}
@-webkit-keyframes snow {
  0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
  50% {background-position: 500px 500px, 100px 200px, -100px 150px;}
  100% {background-position: 500px 1000px, 200px 400px, -100px 300px;}
}
@-ms-keyframes snow {
  0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
  50% {background-position: 500px 500px, 100px 200px, -100px 150px;}
  100% {background-position: 500px 1000px, 200px 400px, -100px 300px;}
}

When you refresh the page, you should see some dainty snow falling over your card's image.

Pseudo Classes

Pseudo classes allow you to add conditional styles depending on different actions your user is taking - like hovering over an element, focusing an input field or visiting a link. You can learn more about the different pseudo classes here.

Our CSS framework comes with some default styles that are decidedly un-festive, like the blue outline when we focus our form input fields and our bland white and grey 'save' button. Let's fix that!

We're going to start by targeting the <input>, <select> and <textarea> fields and updating their border color when they are in focus - meaning when the input element as been selected and a user is able to type. We can use the :focus pseudo class to change our border-color, using the !important flag to make sure our styles will override the default input:focus styling imported from our CSS framework.

Add the following to your main.css file to update the <input>, <select> and <textarea> field border on focus.

input:focus, textarea:focus, select:focus {
    border-color: darkgreen !important;
}

Let's also add an effect to our save button that will update the background-color and the font color when a user hovers over the button.

button:hover {
    background-color: darkred;
    color: white;
    border: white;
}

Responsive Design

One of the most beautiful parts of using a grid system to structure our page is the built-in responsiveness of our columns. If you shrink your screen size, notice how your form and card container columns collapse neatly and beautifully into one column?

Using media queries, you're able to customize different CSS rules to apply depending on the width of your screen. This is incredibly important in our modern-era of devices that come in all shapes and sizes. This allows us to redestribute our page elements and add custom sizing for mobile or tablet devices in addition to standard desktop screens.

Now if you shrink your screen, the card message disapears outside of the card frame. Let's add a media query to adjust our styling around where our card starts to break so we always have enough real-estate for our message. Here's what a media query would look like to change our column width and image height on screens that are smaller than 1000px wide, plus some adjustments for our snow animation.

You can add this at the bottom of your card.css file.

@media (max-width: 1000px) {
  #card-container {
    max-height: auto;
  }
  .one-third.column, .two-thirds.column {
    width: 100%;
    float: none;
  }
  .column {
    margin: 0;
  }
  img {
    height: auto;
  }
  #snow {
    height: 300px;
  }
}

@media (max-width: 768px) {
  #snow {
    height: 155px;
  }
}

Try out some different media queries to adjust the style and layout of your card on different screen sizes - you can read this article to learn a little more about responsive styling.