Navigate back to the homepage

How to build a fancy animated modal box

miguel
June 30th, 2016 · 3 min read
0 x 0

Hello everyone I’m back again with another Pixel2HTML tutorial. This time we’ll make a modal box pop-up kind of like the ones that show up when you try to sign to a newsletter or something related like that. Let’s check the final result first…

Completed project overview

Demo gif

  • Check the live demo here
  • Play with the code on Github

Overview

​The whole idea here is that we have a button with an icon inside of it. Check the article “How to work with SVG icons” for a more in depth look at working with SVGs like a boss. ​ So on hover we’ll do some fancy GPU accelerated transitions to scale the button and rotate the icon inside of it. ​ On click the overlay will fade-in and the contents behind it will blur out using some new css filters. Then the modal box shall come down in a bouncy way. ​ You can then dismiss it by either clicking on the “X” or on the overlay background or by pressing the ESC key on your keyboard.

Let’s go!

Setup

​As I always like to start my projects I’ll do a copy of my always trusty Ground-Zero Repo which also includes my collection of *SaSS mixins Manila Mixins because yummy Mango Manila, you know! 🌴

The directory structure is pretty standard, everything is inside the src directory and after doing gulp it will be compiled and spitted out to the dist directory. ​

Please Note: This project’s code is made up using Jade, the SaSS Syntax (.sass not .scss) and CoffeeScript, however for the following examples I’ll write the outputs of the compilers so everyone can read the code ❤️

Making the Header First

First I’ll show you the markup and then I’ll break it down into reasonable components:

This is the header part. (This is visible at the beginning) ​

1<header>
2 <div class="container">
3 <h1>Get a Space Trip!</h1>
4 <p>Secure your chance for a cool trip to the stars!</p><a class="button modal-trigger"><span>Click Here</span>
5 <svg class="icon sir">
6 <use xlink:href="#sir"></use>
7 </svg></a>
8 <p> <a title="A Pixel2Html Invention" href="//pixel2html.com" title="Terms" target="_blank" class="medium-underline">A Pixel2Html Invention</a></p>
9 </div>
10</header>

​​ Now let me show you the CSS for which I do mine with SaSS: ​

1header {
2 min-height: 100vh;
3
4 @include background("village.jpg", rgba(0, 0, 0, 0.3));
5
6 color: $white;
7 display: flex;
8 align-items: center;
9 justify-content: center;
10 text-align: center;
11 transition: filter $trns-duration;
12
13 @include is(blurred) {
14 filter: blur(5px);
15 }
16}

​ That’s quite some CSS let me break it down for you a bit:

  • The first part sets the header to be at least the whole size of the screen sets up a background and turns the text white.
  • Then using Flexbox I’m perfectly centering all of the contents of the header
  • The transition property tells the browser to get ready to transition the fill property for a duration stored as a variable (in this case its 0.3s)
  • Finally I’m using another of my mixins to set up a JS-trigger class that will be called header.is-blurred that will make the header and its contents blur by 5px when the class is applied to the element.

Making the Modal Box

​ Let’s first take a look at the markup needed for the modal box to happen. ​

1<aside class="modal-box">
2 <div class="background-overlay"></div>
3 <div class="contents">
4 <div class="close"> <span>X</span></div>
5 <div class="half stars"></div>
6 <div class="half">
7 <h4>More than you imagine!</h4>
8 <p>It's your chance for a trip to space!</p>
9 <input type="text" placeholder="Enter your email">
10 </div>
11 </div>
12</aside>

​ I’m declaring the whole HTML element as an aside because I think it holds more semantic meaning than a simple div

Everything else should be pretty straight forward.

Onto the SaSS: ​

1.modal-box {
2 position: fixed;
3 z-index: -1;
4 top: 0;
5
6 @include size(100%);
7
8 text-align: center;
9 opacity: 0;
10 display: flex;
11 align-items: center;
12 justify-content: center;
13 pointer-events: none;
14 transition: $trns-duration;
15
16 @include is(active) {
17 z-index: 2;
18 opacity: 1;
19 pointer-events: all;
20
21 .contents {
22 transform: translateY(0) translate3d(0, 0, 0);
23 }
24 }
25
26
27 .background-overlay {
28 background: rgba($black, 0.4);
29 position: absolute;
30 top: 0;
31 left: 0;
32 width: 100%;
33 height: 100%;
34 }
35
36 .contents {
37 background: $white;
38 border-radius: 15px;
39 position: relative;
40 width: 90%;
41 transform: translate3d(0, 0, 0) translateY(-250%);
42 transition: $trns-duration cubic-bezier(0.5, -0.5, 0.5, 1.5);
43
44 @include breakpoint(laptop) {
45 display: flex;
46 width: 60%;
47 }
48 }
49
50 .close {
51 display: block;
52 position: absolute;
53 font-family: $font-family--secondary;
54 top: -10px;
55 right: -10px;
56
57 @include size(em(40px));
58
59 border-radius: 50%;
60 background: $main-color;
61 color: $white;
62 cursor: pointer;
63 box-shadow: 0 5px 8px rgba(0, 0, 0, 0.15);
64
65 span {
66 @include align;
67 }
68 }
69
70 .half {
71 padding: em(40px);
72
73 @include breakpoint(laptop) {
74 @include flex-cols(6);
75
76 padding: em(120px) em(40px);
77 }
78 }
79
80 .stars {
81 min-height: 250px;
82 border-radius: 10px 10px 0 0;
83 background: url("../img/stars.jpg") no-repeat (bottom / cover);
84
85 @include breakpoint(laptop) {
86 min-height: 100%;
87 border-radius: 10px 0 0 10px;
88
89 @include background("stars.jpg");
90 }
91 }
92
93 h4 {
94 line-height: 1;
95 margin-bottom: em(10px);
96 }
97
98 p {
99 margin-bottom: em(15px);
100 }
101
102 input {
103 display: block;
104 font-size: em(16px);
105 border: none;
106 border-radius: 20px;
107 padding: em(8px) em(15px);
108 outline: none;
109 margin: 0 auto;
110 text-align: center;
111 box-shadow: 0 0 5px rgba(0, 0, 0, 0.6);
112 transition: box-shadow $trns-duration, transform $trns-duration;
113 color: $color-acento;
114 line-height: 1;
115
116 @include placeholder(rgba($black, 0.7));
117
118 &:hover {
119 box-shadow: 0 5px 8px rgba(0, 0, 0, 0.15);
120 transform: translate(0, -2px);
121 }
122 }
123}
124

​ We have a TON of SaSS happening here, but on a broad scale whats going on is that we are placing the modal box using fixed position on top of everything.

Inside the aside we have the background overlay and also the modal box itself. ​ We are using flexbox for everything and also a bit of soft shadows for some elements. ​ Now lets glue everything together using javascript… ​

1(function($) {
2 var close, closing, everything, header, modal, overlay, trigger;
3 header = $('header');
4 modal = $('.modal-box');
5 trigger = $('header .modal-trigger');
6 close = $('.modal-box .close');
7 everything = $(document);
8 overlay = $('.modal-box .background-overlay');
9 trigger.on('click', function() {
10 header.addClass('is-blurred');
11 return modal.addClass('is-active');
12 });
13 closing = function() {
14 header.removeClass('is-blurred');
15 return modal.removeClass('is-active');
16 };
17 close.on('click', closing);
18 overlay.on('click', closing);
19 return everything.keyup(function(e) {
20 if (e.keyCode === 27) {
21 return closing();
22 }
23 });
24 })(jQuery);

​ I’m first making everything a self-executing function to prevent global scope variable pollution. I then declare variable names for everything I’ll use and then the whole thing the JS does is basically either add the classes needed or remove them depending on the situation. ​ For extra UX-ness I’ve added the possibility of using the ESC key or clicking the overlay background to remove the modal box.

All compiled the CSS weights a stunning 5kb (amazing, isn’t it?) and the JavaScript is not even a single kb. The more heavy stuff are the images which we could compress more but we won’t because we want that sharpness and wow factor to remain.

And that’s it! You should be good to go at this point. Don’t forget to take a look at the demo and to check the source code.

Have any questions, comments or you think we can make something better? Leave us a comment below! We’d love to exchange ideas and see how you build amazing things with this technique.

If you want more cool tips and tricks hit me up on twitter at @mpalau and don’t forget to follow us at @Pixel2HTML as well.

Until next time!

Join our email list and get notified about new content

Be the first to receive our latest content with the ability to opt-out at anytime. We promise to not spam your inbox or share your email with any third parties.

More articles from Pixel2HTML

7 tips for a more secure blog with WordPress

In Pixel2HTML we code several WordPress instances in a regular month. WordPress itself hosts near the 20% of the internet, so we can…

April 20th, 2016 · 2 min read

The Ultimate Guide to Style Guides

Style Guides have been an extremely popular topic in the last few years. And it makes lots of sense. They’ve been with us for years in…

February 22nd, 2016 · 7 min read
© 2019 Pixel2HTML
Link to $https://twitter.com/pixel2htmlLink to $https://github.com/pixel2htmlLink to $https://instagram.com/pixel2htmlLink to $https://www.linkedin.com/company/pixel2html/Link to $https://dribbble.com/pixel2html