Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="demo-btns">
		<header>
			<h1>Material Design Modals</h1>
		</header>

		<div class="info">
			<div class="buttons">
				<p>
					<a href="" data-modal="#modal" class="modal__trigger">Modal 1</a>
					<a href="" data-modal="#modal2" class="modal__trigger">Modal 2</a>
					<a href="" data-modal="#modal3" class="modal__trigger">Modal 3</a>
				</p>
			</div>
			<p>Click a button to activate a modal.</p>
		</div>
	</div>

	<!-- Modal -->
	<div id="modal" class="modal modal__bg" role="dialog" aria-hidden="true">
		<div class="modal__dialog">
			<div class="modal__content">
				<h1>Modal</h1>
				<p>Church-key American Apparel trust fund, cardigan mlkshk small batch Godard mustache pickled bespoke meh seitan. Wes Anderson farm-to-table vegan, kitsch Carles 8-bit gastropub paleo YOLO jean shorts health goth lo-fi. Normcore chambray locavore Banksy, YOLO meditation master cleanse readymade Bushwick.</p>
				
				<!-- modal close button -->
				<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>

	<div id="modal2" class="modal modal--align-top modal__bg" role="dialog" aria-hidden="true">
		<div class="modal__dialog">
			<div class="modal__content">
				<h1>Big Modal</h1>
				<h3>This modal is pretty tall.</h3>
				<p>Selfies normcore four dollar toast four loko listicle artisan. Hoodie Marfa authentic, wayfarers church-key tofu Banksy pop-up Kickstarter Brooklyn heirloom swag synth. Echo Park cray synth mixtape. Tofu gastropub squid readymade, trust fund Wes Anderson DIY PBR 8-bit try-hard +1 Shoreditch lo-fi tote bag.</p>
				<p><img src="http://unsplash.it/600/300" alt="" /></p>
				<p>Mumblecore cred selfies fingerstache. Tousled skateboard plaid lo-fi shabby chic salvia, swag Odd Future Etsy art party Austin cronut. Crucifix whatever Pinterest food truck, pickled viral cray 90's DIY chambray keffiyeh biodiesel Vice blog. Cred meh yr tofu.</p>
				<p>Mumblecore cred selfies fingerstache. Tousled skateboard plaid lo-fi shabby chic salvia, swag Odd Future Etsy art party Austin cronut. Crucifix whatever Pinterest food truck, pickled viral cray 90's DIY chambray keffiyeh biodiesel Vice blog. Cred meh yr tofu.</p>
				<!-- modal close button -->
				<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>

	<div id="modal3" class="modal modal__bg" role="dialog" aria-hidden="true">
		<div class="modal__dialog">
			<div class="modal__content">
				<h1>Modal 3</h1>
				<p>Church-key American Apparel trust fund, cardigan mlkshk small batch Godard mustache pickled bespoke meh seitan. Wes Anderson farm-to-table vegan, kitsch Carles 8-bit gastropub paleo YOLO jean shorts health goth lo-fi.</p>
				
				<!-- modal close button -->
				<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>

	<!-- Ettrics -->
	<a href="https://ettrics.com/" class="logo" target="_blank">
	 <img class="logo" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/45226/ettrics-logo.svg" alt="" /> 
	</a>
              
            
!

CSS

              
                $modal-z = 1000
$modal-bg = #FFEBEE
$modal-width = 600px

$space = 2.4rem
$red = #F44336

$t = .5s

$ease($s = $t)
	transition all $s cubic-bezier(0.23, 1, 0.32, 1)

*
	box-sizing border-box

body
	line-height 1.5
	font-family 'Lato'
	-webkit-font-smoothing antialiased
	overflow-x hidden

h1, h2, h3, p
	font-weight 300
	margin 0 0 ($space) 0

h1, h2, h3
	line-height 1.3

a
	text-decoration none
	color inherit
	font-weight 400

/**
 * Material Modal CSS
 */

.modal
	will-change visibility, opacity
	display flex
	align-items center
	justify-content center
	position fixed
	top 0
	left 0
	right 0
	bottom 0
	overflow-y auto
	overflow-x hidden
	z-index $modal-z
	// hide modal
	visibility hidden
	opacity 0
	$ease()
	transition-delay $modal-delay

	&--active
		// reveal modal
		visibility visible
		opacity 1

	&--align-top
		// align to top of window, useful if modal has a lot of content
		align-items flex-start

	&__bg
		// background color can be added as a backdrop for the modal
		background transparent

	&__dialog
		// controls the width and padding of modal
		max-width $modal-width
		padding ($space / 2)

	&__content
		will-change transform, opacity
		position relative
		padding $space
		background $modal-bg
		background-clip padding-box
		box-shadow 0 12px 15px 0 rgba(black, 0.25)
		opacity 0
		$ease(.25s)

		&--active
			opacity 1

	&__close
		z-index $modal-z+100
		cursor pointer

	&__trigger
		// modal trigger button
		position relative
		display inline-block;
		padding ($space / 2) $space
		color: rgba(black, 0.7)
		line-height 1
		cursor pointer
		background $modal-bg
		box-shadow 0 2px 5px 0 rgba(black, 0.26)
		-webkit-tap-highlight-color: rgba(0,0,0,0);		user-select none
		$ease()

		&--active
				z-index 10

		&:hover
				background mix(black, $modal-bg, 10)


#modal__temp
	// this is the div that expands when the button is clicked
	will-change transform, opacity
	position absolute
	top 0
	left 0
	right 0
	bottom 0
	background $modal-bg
	transform none
	opacity 1
	transition opacity 0.1s ease-out, transform $t cubic-bezier(0.23, 1, 0.32, 1)

/**
 * Demo specific CSS
 */

body
	height 100vh
	background $red

img
	max-width 100%

.demo-btns

	header
		padding 7vh 10vw
		background $modal-bg
		display flex
		align-items center

		h1
			margin 0
			color rgba(black, 0.54)
			font-weight 300

	.info
		background $red
		padding 3vh 10vw
		height 70vh
		display flex
		align-items center
		justify-content center
		flex-flow column wrap

	p
		text-align: center
		color white

	.link
		font-size 20px

	.modal__trigger
		margin-right 3px
		@media (max-width 640px)
			margin-bottom ($space / 3)

.demo-close
	position absolute
	top 0
	right 0
	margin: ($space / 2)
	padding: ($space / 4)
	background rgba(black, 0.3)
	border-radius 50%
	$ease()

	svg
		width 24px
		fill: white
		pointer-events none
		vertical-align top

	&:hover
		background rgba(black, 0.6);

.logo
	position: fixed
	bottom: 3vh
	right: 3vw
	z-index: 2

	img
		width: 45px
		transform: rotate(0)
		$ease()

		&:hover
			transform: rotate(180deg) scale(1.1)
              
            
!

JS

              
                var Modal = (function() {

  var trigger = $qsa('.modal__trigger'); // what you click to activate the modal
  var modals = $qsa('.modal'); // the entire modal (takes up entire window)
  var modalsbg = $qsa('.modal__bg'); // the entire modal (takes up entire window)
  var content = $qsa('.modal__content'); // the inner content of the modal
	var closers = $qsa('.modal__close'); // an element used to close the modal
  var w = window;
  var isOpen = false;
	var contentDelay = 400; // duration after you click the button and wait for the content to show
  var len = trigger.length;

  // make it easier for yourself by not having to type as much to select an element
  function $qsa(el) {
    return document.querySelectorAll(el);
  }

  var getId = function(event) {

    event.preventDefault();
    var self = this;
    // get the value of the data-modal attribute from the button
    var modalId = self.dataset.modal;
    var len = modalId.length;
    // remove the '#' from the string
    var modalIdTrimmed = modalId.substring(1, len);
    // select the modal we want to activate
    var modal = document.getElementById(modalIdTrimmed);
    // execute function that creates the temporary expanding div
    makeDiv(self, modal);
  };

  var makeDiv = function(self, modal) {

    var fakediv = document.getElementById('modal__temp');

    /**
     * if there isn't a 'fakediv', create one and append it to the button that was
     * clicked. after that execute the function 'moveTrig' which handles the animations.
     */

    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;

    // this class increases z-index value so the button goes overtop the other buttons
    trig.classList.add('modal__trigger--active');

    // these values are used for scale the temporary div to the same size as the modal
    scaleX = mProps.width / trigProps.width;
    scaleY = mProps.height / trigProps.height;

    scaleX = scaleX.toFixed(3); // round to 3 decimal places
    scaleY = scaleY.toFixed(3);


    // these values are used to move the button to the center of the window
    transX = Math.round(xc - trigProps.left - trigProps.width / 2);
    transY = Math.round(yc - trigProps.top - trigProps.height / 2);

		// if the modal is aligned to the top then move the button to the center-y of the modal instead of the window
    if (m.classList.contains('modal--align-top')) {
      transY = Math.round(mProps.height / 2 + mProps.top - trigProps.top - trigProps.height / 2);
    }


		// translate button to center of screen
		trig.style.transform = 'translate(' + transX + 'px, ' + transY + 'px)';
		trig.style.webkitTransform = 'translate(' + transX + 'px, ' + transY + 'px)';
		// expand temporary div to the same size as the modal
		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) {
      // select the content inside the modal
      var content = m.querySelector('.modal__content');
      // reveal the modal
      m.classList.add('modal--active');
      // reveal the modal content
      content.classList.add('modal__content--active');

      /**
       * when the modal content is finished transitioning, fadeout the temporary
       * expanding div so when the window resizes it isn't visible ( it doesn't
       * move with the window).
       */

      content.addEventListener('transitionend', hideDiv, false);

      isOpen = true;
    }

    function hideDiv() {
      // fadeout div so that it can't be seen when the window is resized
      div.style.opacity = '0';
      content.removeEventListener('transitionend', hideDiv, false);
    }
  };

  var close = function(event) {

		event.preventDefault();
    event.stopImmediatePropagation();

    var target = event.target;
    var div = document.getElementById('modal__temp');

    /**
     * make sure the modal__bg or modal__close was clicked, we don't want to be able to click
     * inside the modal and have it close.
     */

    if (isOpen && target.classList.contains('modal__bg') || target.classList.contains('modal__close')) {

      // make the hidden div visible again and remove the transforms so it scales back to its original size
      div.style.opacity = '1';
      div.removeAttribute('style');

			/**
			* iterate through the modals and modal contents and triggers to remove their active classes.
      * remove the inline css from the trigger to move it back into its original position.
			*/

			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');
			}

      // when the temporary div is opacity:1 again, we want to remove it from the dom
			div.addEventListener('transitionend', removeDiv, false);

      isOpen = false;

    }

    function removeDiv() {
      setTimeout(function() {
        window.requestAnimationFrame(function() {
          // remove the temp div from the dom with a slight delay so the animation looks good
          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();
              
            
!
999px

Console