Modal

by Alexandru Gatea

HTML

<button data-open="modal" data-target="#myModal">Show Modal</button>

<div class="modal" id="myModal">
  <div class="modal-header">
    <h1 class="modal-title">Lorem Ipsum</h1>
    <button class="close" data-dismiss="modal">&times;</button>
  </div>
  <div class="modal-content has-scrollbar">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed enim mi. Nulla facilisi. Quisque elementum felis at metus elementum placerat. Fusce arcu nibh, rhoncus non lacinia maximus, consequat et diam. Sed in porttitor nulla, at volutpat
      risus. In lacinia porta gravida. Phasellus laoreet quam at porta lobortis. Sed egestas erat est. Vestibulum porta venenatis porttitor. Aliquam est diam, dictum dictum felis eu, fermentum rutrum lorem. Etiam sagittis purus vel hendrerit semper. Suspendisse
      odio urna, placerat vehicula iaculis a, sagittis nec augue. Donec sit amet scelerisque neque. Integer ut gravida turpis. Vestibulum ullamcorper vestibulum maximus. Fusce fringilla libero sit amet leo laoreet, eget suscipit justo pellentesque.</p>
  </div>
  <div class="modal-actions">
    <button class="action primary" data-dismiss="modal">Accept</button>
    <button class="action secondary" data-dismiss="modal">Cancel</button>
  </div>
</div>

SCSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: Roboto;
}

body {
  min-height: 100vh;
  background: #f6f6f6;
  display: flex;
  justify-content: center;
  align-items: center;
}

p {
  font-size: 13px;
  line-height: 20px;
  font-weight: 300;
}

button {
  padding: 10px 20px;
  border-radius: 4px;
  line-height: 20px;
  text-transform: uppercase;
  border: none;
  font-weight: bold;
  outline: none;
  background: #212121;
  color: #fff;
  cursor: pointer;
  
  &.close {
    background: transparent;
    font-size: 40px;
    color: #212121;
    font-weight: 300;
  }
  
  &.secondary {
    background: transparent;
    color: #212121;
  }
}



.modal {
  display: none;
  position: fixed;
  z-index: 3000;
  top: 50%;
  left: 50%;
  width: 500px;
  height: 300px;
  margin-left: -250px;
  margin-top: -150px;
  background: #fff;
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 2px 5px 15px 0px rgba(0, 0, 0, 0.4);
  
  >* {
    padding: 10px;
  }
  
  &-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 60px;
  }
  
  &-content {
    height: 180px;
    overflow-y: auto;
  }
  
  &-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    height: 60px;
    
    .action {
      margin-left: 20px;
    }
  }
  
  &.is-open {
    display: block;
    animation: pop 0.4s ease;
  }
  
  &.is-closing {
    animation: pop-off 0.4s ease forwards;
  }
  
}

.backdrop {
  position: fixed;
  z-index: 2999;
  width: 100%;
  height: 100vh;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.8);
  animation: fade 0.2s linear;
}


.has-scrollbar {
  
  &::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
    background-color: #F5F5F5;
  }
  
  &::-webkit-scrollbar {
      width: 6px;
      background-color: #F5F5F5;
  }
  
  &::-webkit-scrollbar-thumb {
    background-color: #000000;
  }
  
}

@keyframes fade {
  from {opacity: 0;}
  to {opacity:...

JavaScript

const modalTrigger = $('[data-open="modal"]');
const modalCloser = $('[data-dismiss="modal"]')

modalTrigger.on('click', function() {
  backdrop();
  openModal(this);
});

modalCloser.on('click', function() {
  backdropRemove();
  closeModal(this);
});

$(document).on('click', '.backdrop', function(){
	$(this).fadeOut('fast');
    $('.modal.is-open').addClass('is-closing');
  
  setTimeout(function(){
  	$('.modal.is-open').removeClass('is-open is-closing');
  }, 200);
})


function openModal($thisTarget) {
  var modalToOpen = $($thisTarget).attr('data-target');
  $(modalToOpen).addClass('is-open');
}

function closeModal($thisTarget) {
  var modalToClose = $($thisTarget).attr('data-dismiss');
  $($thisTarget).parents("." + modalToClose).addClass('is-closing');
  
  setTimeout(function(){
  	$($thisTarget).parents("." + modalToClose).removeClass('is-open is-closing');
  }, 200);
}

function backdrop() {
  const backdrop = "<div class='backdrop'></div>";
  $('body').append(backdrop);
}

function backdropRemove() {
  $('body').find('.backdrop').fadeOut('fast');
}