En esta página:
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!-- 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
.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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
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.