Advertisement

Building the Merry Christmas Web App Interface

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

Today we're going to build the Merry Christmas Web App Interface; a Photoshop layout from an earlier tutorial by Tomas Laurinavicius.

This will be a two-part tutorial. We'll be using some basic responsive techniques and progressively enhanced elements, all made a little bit easier with the use of SASS. This tutorial won't cover how to make the app function with Twitter, but it will lay the foundations to take the development further.

You can find out more about SASS through our screencast series Mastering Sass, or by visiting sass-lang.com. I'm on a Mac so I'll be using the excellent CodeKit to handle watching and compiling my SASS stylesheet. There are plenty of alternatives to CodeKit such as Koala and Scout. They all provide near enough the same functionality and prove invaluable when you don't want to be fiddling about with the command line.

So without further ado, shall we start building the page?


Slicing the PSD

Our first step is to create any slices we need in our PSD and export them to images.

For this particular design there are only four images we need, and they are all contained in the top section.

building-xmas-web-app-01-psd-slices

We have the large background image, the top Christmas tree, the white Christmas tree and the bottom green Christmas tree. Using the Slice tool in Photoshop we can draw a box around each element we would like to export. In order to get the background image on its own we have to hide the layers above it before saving for Web to avoid having those elements being part of the image. We can quickly hide all layers except the one we want, by holding ALT/Option and clicking on the visibility icon next to the layer. Doing this on a group of layers in Photoshop will show only the contents of the group and won't affect layers already hidden.

Once we have our slices we can use Photoshop's "Save for Web" dialog to export our images somewhere safe. Check out Quick Tip: Speed Up Your Workflow With Photoshop Actions for more on slicing in Photoshop.

The next step is to sort out our files and folders.


Directory Structure and Base HTML

In order to start work on the web page we need some files and folders to work with. We only need a basic set up here, so the following structure should cover it.

building-xmas-web-app-02-files-folders

We now need to copy the images exported earlier into the images folder and create a style.scss file to hold all of our SASS declarations.

Remember: when using a companion app like CodeKit, check the output path of your compiled CSS file so you're sure it will appear in the right place.

Sass Project Files

When using Sass and, indeed, plain CSS, you have the ability to split your stylesheet up into to smaller chunks and include them all in one file. For example you could have a _variables.scss "partial" to hold all the variable declarations and a _functions.scss "partial" to hold any mixins you might create. The world really is your oyster here, but for this project it is simple enough to have just one Sass file, so that's what we will do.

I also like to include a copy of Modernizr.js so we have the ability to detect different browser capabilities if we need to. The build used here includes plenty of CSS3 and HTML5 capabilities.

We also need to include the six user avatars we can see in the tweets. These can be found in their original form at uifaces.com which is great resource for when we want to use real faces in a design. Download whichever six user avatars you please, then pop them in a directory called faces inside the images directory.

The last file to add is normalize.css. This is one of the best CSS resets available these days and will give us a good level grounding in all browsers. Download the latest and add it to the css directory.

Next we are going to open up index.html and add the basic HTML markup we need. The following should get us started nicely.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0">

    <title></title>
</head>
<body>
    <div class="wrap">
        <header>

        </header>
        <section class="main group">
            
            <div class="content">


            </div> <!-- content -->

        </section>
        <footer>
            
        </footer>
    </div>
</body>
</html>

The important thing here is the Viewport meta tag which tells mobile browsers to use the correct initial scale of 1.0, which is effectively 100%. Be sure to read Quick Tip: Don't Forget the Viewport Meta Tag for the low-down on the viewport meta tag.


Setting up the Base SASS Styles

One of the best things about Sass is, in my opinion, variables. We're going to be using a number of variables in our Sass stylesheet to hold information like the font-family, font-size and colours. Check the following to see exactly what to set up.

$black: #000;
$white: #FFF;
$grey: #e9e9e9;
$darkgrey: #727272;
$red: #cf2f32;
$green: #42a747;

$padding: 10px;
$margin: 10px;
$main-width: 1000px;

$font-size: 14px;
$font-family: 'Open Sans', sans-serif;
$title-font: 'Josefin Slab', serif;

The top section lists the colours used in the design. These can easily be colour-picked from within Photoshop. I always include a $white and $black variable in order to easily create and control shades of grey if needed. We also have some standard padding and margin amounts, the width of the main content area and some font information. You may notice here that we are using "Josefin Slab" and not "Klinic Slab". Josefin Slab is a close alternative font to Klinic and is available for use on the web via Google Fonts. That means we can include it here easily with a simple @import statement. The same goes for the other font used, "Open Sans".

The next four lines handle the various responsive break-points I decided upon. We are going to be adopting a mobile first approach here so our break-points reflect that. The actual pixel values used were more trial and error than anything else but I have done the hard work so you don't have to!

$break-four: 1050px;
$break-three: 760px;
$break-two: 520px;
$break-one: 360px;

Finally, along with the Google font imports, we have another @import to bring in the normalize.css file we downloaded earlier.

@import url("http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,400,600,700,300");
@import url("http://fonts.googleapis.com/css?family=Josefin+Slab:300,400,600,700");
@import url('normalize.css');

Custom Reset Styles

The next step is to add some reset styles of our own.

* {
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -ms-box-sizing: border-box;
    box-sizing: border-box;
}

body {
    margin: 0;
    padding: 0;
    font-family: $font-family;
    font-size: $font-size;
    overflow-y: scroll;
    overflow-x: hidden;
}

I like to set the position of everything to relative , just to be sure, so when we use absolutely positioned elements we know they are based on their parent. We can then reset this value per element if we need to.

We should also set the box-sizing property for all elements to border-box. This is especially useful when working with responsive elements as any percentage based widths will include any padding set. This means you can float two elements side by side with 50% width each and adjust the padding on both knowing it won't break the layout. That's a very useful CSS property!

Next, we just have to set up some defaults for the body. There's nothing too exciting here except our first use of Sass variables, yay! Ok, so if everything is set up correctly, saving the style.scss file will generate the actual stylesheet we need to link to.

Hook 'em up!

Back in our index.html file we should add the link to our CSS and Modernizr. It may also be nice to give this app a title...

<title>2013 Was Awesome | Merry Xmas & a Happy New Year!</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/modernizr.js"></script>

With that done we can save our index.html file and view it in the browser. Don't worry if you see a blank white screen, that's exactly how it should be at the moment. The next stage is to flesh it out with some HTML markup.


Coding the Header

First things first, let's code the header. For this we are going to use the HTML5 element header. Inside the index.html find the header and add our header background image...

<body>
 <div class="wrap">
  <header>
   <img src="images/xmas-bg.jpg" alt="Merry Christmas!" class="header-image">
  </header>
  <section class="main group">
   <div class="content">

   </div> <!-- content -->
  </section>
  <footer>
  </footer>
 </div>
</body>

We're adding the background image as an img element here, so we can easily scale it when the browser resizes. This is possible with CSS background images (using background-size) but that method has never worked reliably cross-browser for me and can be laggy due to the browser having to repaint everything all the time. Give the image a class name so we can reference it in our Sass file.

The Innards

Next we are going to write the inner section of the header. This will hold the Christmas trees, the text and the Twitter connect button.

<div class="header-inner">

 <div class="titles">
  <div class="xmas-tree-top">
   <img src="images/xmas-tree.png" alt="Merry Christmas!">
  </div>
  <p class="title">
   2013 Was Awesome. <span>Time to say <em>'Thank You'</em></span>
  </p>
  <p class="title-small">
   and wish your friends a
  </p>
  <h1>
   <span>Merry Christmas!</span>
  </h1>
 </div>
 
 <a href="#" class="connect">Connect with Twitter</a>
 
 <img src="images/xmas-tree-green.png" alt="Merry Christmas!" class="xmas-tree-bottom">

</div>

There's quite a bit going on here. We have...

  • Wrapping div with a class of header-inner
  • Wrapper for all of the title elements
  • The top Christmas tree
  • The main title with sub-title
  • A sub-sub-title
  • The Merry Christmas message
  • The Twitter connect button
  • Finally, the bottom Christmas tree

Wow! Listed out like that makes it seem like a lot in one small area. However, that is our header coding complete! If you save the file and view it in a browser it will look like the following.

building-xmas-web-app-09-header-done

Nice! It doesn't look like much though, so our next task is to lay down some Sass rules and get the header looking exactly like the design. Switch to the stylesheet to begin.

Styling the Header

The first group of styles to add look something like this...

header {
    width: 100%;
    height: 390px;
    color: $white;
    background: $grey;

    @media screen and (min-width: $break-four) {
        height: 799px;
    }
}

header .header-image {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 100%;
    height: auto;
    max-height: 799px;
    min-height: 400px;
}

.header-inner {
    width: 90%;
    margin: 0 auto;

    @media screen and (min-width: $break-four) {
        width: 60%;
    }
}

.titles {
    padding-top: 40px;
}

Here we have some default styles for our header. We must also use our first bit of responsive Sass here as we need to make sure the height increases as the browser gets wider. I think Sass really shines here as it gives us the ability to use media queries directly nested under the element they are meant to act upon. This greatly speeds up the time taken to add responsive declarations. You will notice we are also using our fourth break-point variable which specifies a desktop size dimension and tells the browser to change the height when the minimum width of the window is whatever the value of $break-four is.

Here we need to make the header image absolutely positioned to the top left. We then should make sure this image grows and shrinks with the browser, so setting the width to 100% covers that. The next three properties determine how the height should be handled. A height of auto allows the image to retain its aspect ratio when its width changes. We don't want it to scale up past its actual height so the max-height property makes sure of that. Likewise the min-height property will stop the image getting smaller than 400px.

Our header-inner div is responsible for holding all of our titles and Christmas tree images. This means it must be centered at all times in the window. Our base style here is 90% width which will work wonderfully for mobile and tablets. The media query tells the browser to use 60% width at desktop sizes.

So lets take a look in the browser...

building-xmas-web-app-11-header-responsive

That's desktop on the left and mobile on the right. They both look pretty similar, but when you change the browser size the inner-header definitely changes width. Great! Let's keep going. The last step in the code above is to just add some padding to the .titles div. This will bump it down from the top of the window slightly.

Oh, Christmas Tree

Our next challenge is the top Christmas tree. We're going to be using the :before and :after pseudo elements to create the hexagon shape. You can read about pseudo elements in Building Icons With a Single HTML Element.

.header-inner .titles .xmas-tree-top {
    position: absolute;
    background: $white;
    left: 50%;
    margin-left: -37.5px;
    top: 30px;
    padding: $padding/2 $padding*2;
    width: 75px;


    @media screen and (min-width: $break-four) {
        margin-left: -58px;
        top: 80px;
        padding: $padding $padding*3.5;
        width: auto;
    }

    &:before {
        content: "";
        position: absolute;
        left: 0px;
        border: 38px solid transparent;
        border-bottom: 20px solid $white;
        top: -58px;


        @media screen and (min-width: $break-four) {
            border: 63px solid transparent;
            border-bottom: 30px solid $white;
            top: -93px;
        }
    }

    &:after {
        content: "";
        border: 38px solid transparent;
        border-top: 20px solid $white;
        position: absolute;
        bottom: -58px;
        left: 0px;

        @media screen and (min-width: $break-four) {
            border: 63px solid transparent;
            border-top: 30px solid $white;
            bottom: -93px;
        }
    }

    img {
        display: block;
        width: 100%;
        max-width: 56px;
        height: auto;
    }

}

This looks fairly complicated, but it's really quite simple. There's quite a bit Sass use here with a lot of our variables coming in to play. The xmas-tree-top element itself is absolutely positioned to be in the center at all times. This is achieved with...

left: 50%;
margin-left:-37.5px;
width: 75px;

The margin-left is half the width of the element, so it pulls the element back in to be exactly centered. We're also using a simple media query again for desktop sizes which adjusts the padding and the top position.

The next two parts are the interesting bits! First up is the :before element. What we want to create with this element is a triangle to sit on top of the Christmas tree box. We are going to take advantage of a technique described in Quick Tip: Drawing and Using CSS Triangles. On a simple level, we just have to create an element with a border the width we require. Now, in all honesty, this took a bit of trial and error to get right and it probably will whenever you use this technique, unless you are creating an equilateral triangle. The values in the code create the triangle we need which is slightly squashed. The top position is calculated by adding the two border values together as that is the actual height of our pseudo element.

The :after element follows much the same pattern to create the bottom triangle. The only difference being border-top rather than border-bottom. We, finally, must specify some styles for the Christmas tree image. We have to make sure it is 100% of the parent element up to its actual width. In this case that is 56px. The height will be automatic based on the current width.

Phew! That was a lot to take in. Save all the files and view the fruits of your labour in the browser...

building-xmas-web-app-12-xmas-tree-top

Excellent. The Christmas tree box looks amazing and it scales up and down with the browser. Now let's take care of those titles...

Those Titles

.title, .title-small, h1 {
    text-align: center;
    font-size: 36px;
    margin: 0;
    font-family: $title-font;
    font-weight: 300;
    letter-spacing: -0.03em;
}

.title {
    margin-top: 60px;
    font-size: 200%;

    span {
        display: block;
    }

    @media screen and (min-width: $break-four) {
        margin-top: 200px;
        font-size: 300%;
    }

}

.titles {

    .title-small {
        margin: $margin*2 auto 0;
        width: 100%;
        font-size: 155%;

        &:before, &:after {
            content: url(../images/xmas-tree-white.png);
            position: absolute;
            top: 2px;
        }

        &:before {
            left: 0px;
        }

        &:after {
            right: 0px;
        }

        @media screen and (min-width: $break-one) {
            font-size: 200%;
            width: 12em;
        }

    }

}

.titles h1 {
    text-transform: uppercase;
    font-size: 222%;
    border-bottom: 2px solid $white;
    width: 9em;
    margin: 20px auto 0;

    span {
        display: block;
        margin-bottom: 3px;
        border-bottom: 2px solid $white;
    }

    @media screen and (min-width: $break-two) {
        font-size: 300%;
    }

}

There isn't too much going on here. The media query for .title makes sure the font-size is bigger and the spacing from the top is larger when on desktop window sizes. We are using :before and :after pseudo elements again to display the two white Christmas trees on the smaller title.

Another thing to note is the use of width: 12em in our media query for .title-small and also for the h1. This means the width is based on the font size of that element instead of the parent element width like percentage based values are. More information on this can be found by reading Taking the "Erm.." Out of Ems.

Let's save our Sass file again and check out what we have in the browser...

building-xmas-web-app-13-titles

This is starting to look much better! The titles all scale nicely and move position when needed. We have two elements left to style up before our header is complete. Onwards and upwards!

Connect

.header-inner .connect {
    display: block;
    width: 195px;
    height: 50px;
    line-height: 45px;
    text-align: center;
    border-radius: 30px;
    border: 2px solid #c52f30;
    color: $red;
    margin: 30px auto 0;
    text-decoration: none;
    -webkit-transition: background 0.4s ease, color 0.4s ease;
    -moz-transition: background 0.4s ease, color 0.4s ease;
    -o-transition: background 0.4s ease, color 0.4s ease;
    -ms-transition: background 0.4s ease, color 0.4s ease;
    transition: background 0.4s ease, color 0.4s ease;

    &:hover {
        background: $red;
        color: $white;
        -webkit-transition: background 0.4s ease, color 0.4s ease;
        -moz-transition: background 0.4s ease, color 0.4s ease;
        -o-transition: background 0.4s ease, color 0.4s ease;
        -ms-transition: background 0.4s ease, color 0.4s ease;
        transition: background 0.4s ease, color 0.4s ease;
    }

}

.xmas-tree-bottom {
    display: none;
    margin: 30px auto 0;

    @media screen and (min-width: $break-four) {
        display: block;
    }
}

The first thing you will notice here is the use of CSS3 Transitions. This will give us a nice fade as we hover over the Twitter connect button. You must specify the transition on both the normal and hover state to get it to fade in and out. The other styles for the button are quite simple and we don't need any media queries for it as it is small enough to remain the same throughout all browser sizes.

Last Christmas (Tree)

Last, but by no means least, is the bottom Christmas tree. Very simply, center it on the screen and show it only at desktop-based sizes. This is just a choice I made about whether to keep the tree at mobile sizes or hide it. Having played around with different positions I decided it didn't add anything to the user experience on a small screen, so it is best to hide it.

That wraps up our header! Save all files and let's take a look where we are now...

building-xmas-web-app-14-header-styles-complete

Ah yes, this is much more like it! It is a great feeling when you see the hard work pay off isn't it? Our header is looking great and everything is working as it should. The next section begins work on the main content.


The Main Content

Ok, our first step in building the main content is the HTML for the tweet boxes. It goes a little something like this:

<div class="message-box">
   <p class="date-time">22:13 - 28 November 2013</p>
     <div class="message group">
         <img src="images/faces/jl.jpg" alt="Placeholder" class="message-image">
         <div class="message-content">
           <h3>Jonny Livingston</h3>
           <p>@jonnylvng</p>
           <div>
              Happy Thanksgiving! I'm so thankful for all of you guys. Thank you for the love and support you give me.
           </div>
        </div>
    </div>
</div>

This code should go inside div.content and, as you can see, it is made up of a few sections. We have the .date-time paragraph outside of the .message div. This element holds the image and the message content itself. The .message-content div contains the three parts of information in different HTML elements, which means we won't need classes to style them individually. If you save the file and look in the browser you will see:

building-xmas-web-app-15-message-box

Styling the Main Content

We definitely need some styles here to get this looking how it should. Let's take a look at those now.

.main {
    background: $grey;

    .content {
        width: 100%;
        margin: 0 auto;

        @media screen and (min-width: $break-four) {
            width: $main-width;
        }

        .message-box {
            width: 100%;
            padding: $padding*3 $padding*1.5;

            @media screen and (min-width: $break-four) {
               float: left;
               width: 50%;
            }
        }

    }

}

To start with we need some base styles for our main section and our content div. Simply, make the background of main the grey colour from our variable and set the width of content to 100%. You will see the margin style here being used to center the element which will only come into play when the width isn't 100%, but I like to include it here so any of our responsive break-points inherit it.

The message-box itself is, also, very simple for mobile and tablet layouts with just 100% width and some padding. Our media queries will both kick in at desktop based sizes, setting the content to the $main-width variable and the message-box to float left and cover 50% of the content div, rather than 100%. This will make the boxes sit up next to each other like we see in the design. If we save and take a look we should see:

building-xmas-web-app-16-message-box-styles

It's definitely taking shape and changing at the right window sizes so that's good!

Utilities

One important utility style to add right at the end of the Sass file is as follows:

//Utilities
.group:after {
  content: "";
  display: table;
  clear: both;
}

This makes sure that any element with this class name will contain their child elements if they are floated. More about why this works can be found on Nicolas Gallagher's blog.

.date-time {
    font-weight: 400;
    color: darken($grey, 30%);
}

A very quick declaration here for the date-time element. It should be nested within our message-box styles. I believe this is the first use of a Sass colour function which are, on the whole, very useful. This one darkens the $grey colour by 30%. This is awesome when you already have a colour and you just want to quickly use a different shade of it.

Message Box

Let's move onto the message box now.

.message {
    padding: $padding*2;
    height: auto;
    border-radius: 3px;
    background: $white;
    text-align: center;

    @media screen and (min-width: $break-two) {
      text-align: left;
    }

    @media screen and (min-width: $break-four) {
      height: 175px;
    }

    &:before {
      content: "";
      position: absolute;
      left: 20px;
      top: -20px;
      border: 10px solid transparent;
      border-bottom: 10px solid $white;
    }

    .message-image {
      border-radius: 50%;
      width: auto;
      max-width: 99px;
      height: auto;
      float: none;

        @media screen and (min-width: $break-two) {
          float: left;
        }
    }

}

Ok, there's quite a bit of code here. On mobile and tablets it is nice to have content like this centered as there isn't a great deal of room. Our base styles for message cover that by setting the text-align property to center. Make sure to also give this box a white background and a small border-radius to match the design. We have set two break points for this element so we can be sure that anything above mobile will reset the text-align to left-justified and, further up the window size scale, set the height for the box so when they are floating next to each other everything lines up nicely.

Oh look! Another :before pseudo element. This is pretty much the same as the top Christmas tree in that we are creating a triangle to sit above the box and just below the date-time element.

Now it's time to style up the image. For this design it probably isn't necessary for the image to scale up and down but whenever working with responsive layout I always like to make images behave this way, especially when they are contained within an element that does a fair amount of changing at various sizes. So to cover most scenarios we simply set the width and height to auto and make sure there is a max-width property to stop the image scaling beyond its parent's size.

On any window size above mobile we need to float the image left to sit along side the message content. It's time again to save our work and switch back to the browser:

building-xmas-web-app-17-message-box-styles2

Well that looks much better! Just the message content left to do.


To Be Continued…

We'll carry on building this festive app in part two, which is on its way very soon. Thanks for reading so far, I hope my explanations make sense and that you have followed along fine. I look forward to guiding you through to the completed site next time!