Skip to content

Instantly share code, notes, and snippets.

@ikonikre
Created November 14, 2016 02:55
Show Gist options
  • Save ikonikre/44638c32084b2b1897c94e7f111ce94c to your computer and use it in GitHub Desktop.
Save ikonikre/44638c32084b2b1897c94e7f111ce94c to your computer and use it in GitHub Desktop.
Modal Animation Physics
<div class="modal-frame">
<div class="modal">
<div class="modal-inset">
<div class="button close"><i class="fa fa-close"></i></div>
<div class="modal-body">
<h3>Such Modal, Much Animate!</h3>
<p>Nothing groundbreaking, but I hope you enjoyed <br /> the physics for the open/close animation =).</p>
<p class="ps">**I know the SASS is a bit messy, I did this on the fly and for fun <br /> and w.e. I DO WHAT I WANT!!</p>
</div>
</div>
</div>
</div>
<div class="modal-overlay"></div>
<button class="fancy-btn open">Can I haz Modal?</button>

Modal Animation Physics

Messing around with keyframe/transition physics for a modal. Mostly focused on the timing between the overlay, modal container, and modal content to try to make the whole event look more organic. Believe it or not, inspired by the menu pop-ups in Super Mario 3D. Enjoy

A Pen by Ikonikre on CodePen.

License.

$(document).on('ready', function(){
$modal = $('.modal-frame');
$overlay = $('.modal-overlay');
/* Need this to clear out the keyframe classes so they dont clash with each other between ener/leave. Cheers. */
$modal.bind('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e){
if($modal.hasClass('state-leave')) {
$modal.removeClass('state-leave');
}
});
$('.close').on('click', function(){
$overlay.removeClass('state-show');
$modal.removeClass('state-appear').addClass('state-leave');
});
$('.open').on('click', function(){
$overlay.addClass('state-show');
$modal.removeClass('state-leave').addClass('state-appear');
});
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
@import "compass/css3";
* { box-sizing: border-box; }
html, body {
width: 100%; height: 100%;
position: relative;
margin: 0; padding: 0;
font-family: 'Noto Sans', sans-serif;
font-weight: 400;
font-size: 16px; line-height: 22px;
background-color: #F2E1AC;
}
.fancy-btn {
-webkit-appearance: none;
cursor: pointer; outline: none; border: none;
position: relative; top: 50%;
display: block; min-width: 10%;
line-height: 55px; font-size: 14px;
text-transform: uppercase;
margin: 0 auto; padding: 0 10px;
background-color: #F2594B;
color: #FFF;
border-radius: 3px;
@include transform(translateY(-50%));
&:hover {
background-color: lighten(#F2594B, 5%);
}
}
// completely redoing the modal from the ground up.
.modal-overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
margin: auto;
background-color: #fff;
opacity: 0;
visibility: hidden;
z-index: 40;
@include transition(opacity .25s ease 0s, visibility linear .35s);
&.state-show {
opacity: .7;
visibility: visible;
@include transition-delay(0s);
@include transition-duration(.2s, 0s);
}
}
.modal-frame {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
margin: auto;
z-index: 50;
/* display: table; */
@include display-flex;
@include align-items(center);
-moz-box-align: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
-moz-box-pack: center;
-ms-flex-pack: center;
width: 100%;
text-align: center;
visibility: hidden;
// animation classes and behavior
&.state-appear {
visibility: visible;
.modal-inset {
@include animation(modalComeIn .25s ease);
visibility: visible; /* to keep @ final state */
}
.modal-body {
opacity: 1;
@include transform(translateY(0) scale(1,1))
}
}
&.state-leave {
visibility: visible;
.modal-inset {
@include animation(modalHeadOut .35s ease .1s);
visibility: visible;
}
.modal-body {
opacity: 0;
@include transition-delay(0s);
@include transition-duration(.35s);
@include transition-timing-function(ease);
@include transform(translateY(25px))
}
}
}
@-moz-document url-prefix() {
.modal-frame {
height: calc(100% - 55px);
}
}
.modal {
display: block;
vertical-align: middle;
text-align: center;
}
.modal-inset {
position: relative;
padding: 60px;
background-color: white;
min-width: 320px;
min-height: 126px;
margin: auto;
visibility: hidden;
@include box-shadow(2px 2px 8px 1px rgba(0,0,0,.2));
@include backface-visibility(hidden); // helps render animation
@include transform(translate3d(0,0,0)); // helps render animation
@include transform-style(preserve-3d); // helps render animation
.close {
display: block;
cursor: pointer;
position: absolute;
top: 10px;
right: 10px;
padding: 10px;
opacity: .4;
&:hover {
opacity: 1;
}
}
}
.modal-body {
margin: auto;
opacity: 0;
@include transform(translateY(0) scale(.8, .8));
@include transition-property(opacity, transform);
@include transition-duration(.25s);
@include transition-delay(.1s);
h3 {
font-weight: 700;
padding-bottom: 22px;
display: block;
color: #F2594B;
text-align: center;
}
p {
padding-bottom: 20px;
}
.ps {
font-size: 12px;
opacity: .3;
}
}
@mixin keyframes($name) {
@-webkit-keyframes #{$name} {
@content;
}
@-moz-keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
@include keyframes(modalComeIn) {
0% {
visibility: hidden;
opacity: 0;
@include transform(scale(.8, .8));
}
65.5% {
@include transform(scale(1.03, 1.03));
}
100% {
visibility: visible;
opacity: 1;
@include transform(scale(1, 1));
}
}
@include keyframes(modalHeadOut) {
0% {
visibility: visible;
opacity: 1;
@include transform(translateY(0) scale(1, 1));
}
100% {
visibility: hidden;
opacity: 0;
@include transform(translateY(35px) scale(.97, .97));
}
}
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="http://fonts.googleapis.com/css?family=Noto+Sans:400,700" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment