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
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;34 @include background("village.jpg", rgba(0, 0, 0, 0.3));56 color: $white;7 display: flex;8 align-items: center;9 justify-content: center;10 text-align: center;11 transition: filter $trns-duration;1213 @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 its0.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;56 @include size(100%);78 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;1516 @include is(active) {17 z-index: 2;18 opacity: 1;19 pointer-events: all;2021 .contents {22 transform: translateY(0) translate3d(0, 0, 0);23 }24 }252627 .background-overlay {28 background: rgba($black, 0.4);29 position: absolute;30 top: 0;31 left: 0;32 width: 100%;33 height: 100%;34 }3536 .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);4344 @include breakpoint(laptop) {45 display: flex;46 width: 60%;47 }48 }4950 .close {51 display: block;52 position: absolute;53 font-family: $font-family--secondary;54 top: -10px;55 right: -10px;5657 @include size(em(40px));5859 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);6465 span {66 @include align;67 }68 }6970 .half {71 padding: em(40px);7273 @include breakpoint(laptop) {74 @include flex-cols(6);7576 padding: em(120px) em(40px);77 }78 }7980 .stars {81 min-height: 250px;82 border-radius: 10px 10px 0 0;83 background: url("../img/stars.jpg") no-repeat (bottom / cover);8485 @include breakpoint(laptop) {86 min-height: 100%;87 border-radius: 10px 0 0 10px;8889 @include background("stars.jpg");90 }91 }9293 h4 {94 line-height: 1;95 margin-bottom: em(10px);96 }9798 p {99 margin-bottom: em(15px);100 }101102 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;115116 @include placeholder(rgba($black, 0.7));117118 &: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!