Demo Github
Material Design el Framework para hacer nuestras aplicaciones adaptables a cualquier dispositivo es una de los Frameworks que nos da muchas expectativas de todo lo nuevo que puede traer.Voy a mostrarles una manera de crear ventanas Modales con javascript nativamente y lo puedan aplicar a sus proyectos hechos con Material Design.
Primero creamos la vista html:
index.html
En los comentarios indico para que sirve cada elemento html:
<!-- al hacer click en este boton se abrira la Ventana modal --> <a href="" data-modal="#modal" class="modal__trigger">Boton</a> <!-- Ventana Modal --> <div id="modal" class="modal modal__bg" role="dialog" aria-hidden="true"> <div class="modal__dialog"> <div class="modal__content"> <h1>Material Design es dinámico</h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer id dignissim elit. In hac habitasse platea dictumst. Mauris ac acus ipsum. Aliquam sed felis eu enim maximus convallis eu sit amet dui. In leo magna, facilisis tincidunt cursus et, ultrices feugiat leo. Curabitur bibendum dui euismod enim fermentum scelerisque. Vestibulum sodales elit fringilla eros iaculis, in efficitur libero dignissim. Donec feugiat quis augue vel pharetra. </p> <!-- Boton para cerrar la Ventana modal --> <a href="" class="modal__close demo-close"> <svg class="" viewBox="0 0 24 24"><path d="M19 6.41l-1.41-1.41-5.59 5.59-5.59-5.59-1.41 1.41 5.59 5.59-5.59 5.59 1.41 1.41 5.59-5.59 5.59 5.59 1.41-1.41-5.59-5.59z"/><path d="M0 0h24v24h-24z" fill="none"/></svg> </a> </div> </div> </div>
Ahora necesitamos nuestro archivo CSS para darle estilo a los elementos html:
estilos.css
.modal { will-change: visibility, opacity; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; position: fixed; top: 0; left: 0; right: 0; bottom: 0; overflow-y: auto; overflow-x: hidden; z-index: 1000; visibility: hidden; opacity: 0; -webkit-transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); -webkit-transition-delay: $modal-delay; transition-delay: $modal-delay; } .modal--active { visibility: visible; opacity: 1; } .modal--align-top { -webkit-box-align: start; -webkit-align-items: flex-start; -ms-flex-align: start; align-items: flex-start; } .modal__bg { background: transparent; } .modal__dialog { max-width: 600px; padding: 1.2rem; } .modal__content { will-change: transform, opacity; position: relative; padding: 2.4rem; background: #fff; background-clip: padding-box; box-shadow: 0 12px 15px 0 rgba(0,0,0,0.25); opacity: 0; -webkit-transition: all 0.25s cubic-bezier(0.23, 1, 0.32, 1); transition: all 0.25s cubic-bezier(0.23, 1, 0.32, 1); } .modal__content--active { opacity: 1; } .modal__close { z-index: 1100; cursor: pointer; } .modal__trigger { position: relative; display: inline-block; padding: 1.2rem 2.4rem; color: #fff; line-height: 1; cursor: pointer; background: #4C9BD6; box-shadow: 0 2px 5px 0 rgba(0,0,0,0.26); -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); } .modal__trigger--active { z-index: 10; } .modal__trigger:hover { background: green; } #modal__temp { will-change: transform, opacity; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #DADDDE; -webkit-transform: none; transform: none; opacity: 1; -webkit-transition: opacity 0.1s ease-out, -webkit-transform 0.5s cubic-bezier(0.23, 1, 0.32, 1); transition: opacity 0.1s ease-out, -webkit-transform 0.5s cubic-bezier(0.23, 1, 0.32, 1); transition: opacity 0.1s ease-out, transform 0.5s cubic-bezier(0.23, 1, 0.32, 1); transition: opacity 0.1s ease-out, transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), -webkit-transform 0.5s cubic-bezier(0.23, 1, 0.32, 1); } body { height: 100vh; } img { max-width: 100%; } .demo-btns header { padding: 7vh 10vw; background: #ffebee; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; } .demo-btns header h1 { margin: 0; color: rgba(0,0,0,0.54); font-weight: 300; } .demo-btns .info { background: #fff; padding: 3vh 10vw; height: 70vh; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-flex-flow: column wrap; -ms-flex-flow: column wrap; flex-flow: column wrap; } .demo-btns p { text-align: center; color: #fff; } .demo-btns .link { font-size: 20px; } .demo-btns .modal__trigger { margin-right: 3px; } @media (max-width: 640px) { .demo-btns .modal__trigger { margin-bottom: 0.8rem; } } .demo-close { position: absolute; top: 0; right: 0; margin: 1.2rem; padding: 0.6rem; background: rgba(0,0,0,0.3); border-radius: 50%; -webkit-transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); } .demo-close svg { width: 24px; fill: #fff; pointer-events: none; vertical-align: top; } .demo-close:hover { background: rgba(0,0,0,0.6); }
Como pueden ver uso max-witdh como responsive design nativo y aplico estilos a los botones y a la ventana modal y demás elementos.
También necesitamos nuestro javascript para darle el efecto y la funcionalidad a nuestra ventana modal:
script.js
En los comentarios describo las acciones mas relevantes del código:
var Modal = (function() { var trigger = $qsa('.modal__trigger'); // Al hacer click activo la ventana modal var modals = $qsa('.modal'); var modalsbg = $qsa('.modal__bg'); var content = $qsa('.modal__content'); var closers = $qsa('.modal__close'); var w = window; var isOpen = false; var contentDelay = 400; // el tiempo duracion antes de cargar el cotenido de la ventana modal var len = trigger.length; function $qsa(el) { return document.querySelectorAll(el); } var getId = function(event) { event.preventDefault(); var self = this; // obtengo el valor y el atributo del botón var modalId = self.dataset.modal; var len = modalId.length; // remuevo el char # o numeral var modalIdTrimmed = modalId.substring(1, len); var modal = document.getElementById(modalIdTrimmed); makeDiv(self, modal); }; var makeDiv = function(self, modal) { var fakediv = document.getElementById('modal__temp'); if (fakediv === null) { var div = document.createElement('div'); div.id = 'modal__temp'; self.appendChild(div); moveTrig(self, modal, div); } }; var moveTrig = function(trig, modal, div) { var trigProps = trig.getBoundingClientRect(); var m = modal; var mProps = m.querySelector('.modal__content').getBoundingClientRect(); var transX, transY, scaleX, scaleY; var xc = w.innerWidth / 2; var yc = w.innerHeight / 2; // Le ingremento la propiedad z-index a esta clase, para superponer la ventana modal sobre el botón que hice click trig.classList.add('modal__trigger--active'); // Escalo la ventana modal scaleX = mProps.width / trigProps.width; scaleY = mProps.height / trigProps.height; scaleX = scaleX.toFixed(3); scaleY = scaleY.toFixed(3); transX = Math.round(xc - trigProps.left - trigProps.width / 2); transY = Math.round(yc - trigProps.top - trigProps.height / 2); // Centro al medio de la pantalla la ventana modal if (m.classList.contains('modal--align-top')) { transY = Math.round(mProps.height / 2 + mProps.top - trigProps.top - trigProps.height / 2); } // Muevo el botón al centro de la pantalla trig.style.transform = 'translate(' + transX + 'px, ' + transY + 'px)'; trig.style.webkitTransform = 'translate(' + transX + 'px, ' + transY + 'px)'; // Escalo el div contenedor de la ventana modal temporalmente div.style.transform = 'scale(' + scaleX + ',' + scaleY + ')'; div.style.webkitTransform = 'scale(' + scaleX + ',' + scaleY + ')'; window.setTimeout(function() { window.requestAnimationFrame(function() { open(m, div); }); }, contentDelay); }; var open = function(m, div) { if (!isOpen) { var content = m.querySelector('.modal__content'); m.classList.add('modal--active'); content.classList.add('modal__content--active'); content.addEventListener('transitionend', hideDiv, false); isOpen = true; } function hideDiv() { div.style.opacity = '0'; content.removeEventListener('transitionend', hideDiv, false); } }; // Cerramos la ventana modal var close = function(event) { event.preventDefault(); event.stopImmediatePropagation(); var target = event.target; var div = document.getElementById('modal__temp'); if (isOpen && target.classList.contains('modal__bg') || target.classList.contains('modal__close')) { div.style.opacity = '1'; div.removeAttribute('style'); for (var i = 0; i < len; i++) { modals[i].classList.remove('modal--active'); content[i].classList.remove('modal__content--active'); trigger[i].style.transform = 'none'; trigger[i].style.webkitTransform = 'none'; trigger[i].classList.remove('modal__trigger--active'); } div.addEventListener('transitionend', removeDiv, false); isOpen = false; } function removeDiv() { setTimeout(function() { window.requestAnimationFrame(function() { div.remove(); }); }, contentDelay - 50); } }; var bindActions = function() { for (var i = 0; i < len; i++) { trigger[i].addEventListener('click', getId, false); closers[i].addEventListener('click', close, false); modalsbg[i].addEventListener('click', close, false); } }; var init = function() { bindActions(); }; return { init: init }; }()); Modal.init();
Es importante recordar que estoy usando materialize.css el cual esta en el repositorio Git de esta demo, para que se vea bien el ejemplo en todos los navegadores.
Espero que les sirva de mucho el articulo.
Gracias por su atención.