HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
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.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
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.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
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.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<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>
$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)
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();
Also see: Tab Triggers