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.
html
head
body.demo-1.loading.cda-alignright.cda-naked
main
.page.page--layout-2(data-scroll='')
.content.content--full.content--alternate
.content__item.content__item--wide
span.content__item-number 11
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/2007_tours_de_roles.png);')
.content__item-deco
h2.content__item-title 2007
p.content__item-description Acteurs et actrices d'un film à l'autre
.content__item.content__item--wide
span.content__item-number 10
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/2004_prejuge_de_la_rampe.png);')
.content__item-deco
h2.content__item-title 2004
p.content__item-description Pour un cinéma déchaîné
.content__item.content__item--t3--wide
span.content__item-number 09
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/2003_mecanic_cinema.png);')
.content__item-deco
h2.content__item-title 2003
p.content__item-description Technologies, machines, outils, objets divers
.content__item.content__item--t2--wide
span.content__item-number 08
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/2002_derriere_la_porteII.png);')
.content__item-deco
h2.content__item-title 2002
p.content__item-description Pouvoirs du secret au cinéma
.content__item.content__item--t1--wide
span.content__item-number 07
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/2001_derriere_la_porteI.png);')
.content__item-deco
h2.content__item-title 2001
p.content__item-description Secrets de famille au cinéma
.content__item.content__item--wide
span.content__item-number 06
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/2000_epreuve_du_monde.png);')
.content__item-deco
h2.content__item-title 2000
p.content__item-description Entre réel et fiction
.content__item.content__item--wide
span.content__item-number 05
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/1999_raison_en_feu.jpg);')
.content__item-deco
h2.content__item-title 1999
p.content__item-description La fascination du cinéma pour la folie
.content__item.content__item--wide
span.content__item-number 04
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/1998_je_est_un_film.png);')
.content__item-deco
h2.content__item-title 1998
p.content__item-description Autour de l'autobiographie
.content__item.content__item--wide
span.content__item-number 03
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/1997_plaisir_des_larmes.png);')
.content__item-deco
h2.content__item-title 1997
p.content__item-description Autour du mélo
.content__item.content__item--wide
span.content__item-number 02
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/1996_violences_du_cinema.jpg);')
.content__item-deco
h2.content__item-title 1996
p.content__item-description
.content__item.content__item--wide
span.content__item-number 01
.content__item-imgwrap
.content__item-img(style='background-image: url(https://www.lacor.info/accueil/galerie-livres/img/1995_cinema_meurtri.jpg);')
.content__item-deco
h2.content__item-title 1995
p.content__item-description Un siècle de censure au cinéma
p.credits
| Éditions de l'
a(href='https://www.lacor.info/cinemas-ouest/index.php/livres/livres-edites-par-l-acor', target="_top") ACOR
script(src='https://www.lacor.info/accueil/galerie-livres/js/imagesloaded.pkgd.min.js')
script(src='https://www.lacor.info/accueil/galerie-livres/js/demo.js')
script(src='https://www.lacor.info/accueil/galerie-livres/js/TweenMax.min.js')
*,
*::after,
*::before
box-sizing border-box
:root
font-size 16px
$scroll--shadow=rgba(5,5,5,0.2)
$scroll--bg=hsla(270,47%,10%,0)
$scroll--bar=rgba(5,5,5,0.5)
body
margin 0
--color-text white
--color-bg transparent
--color-link hsla(270,47%,40%,.7)
--color-link-hover white
--aspect-ratio 1/1.5
--size-title 10rem
--font-weight-title 400
color var(--color-text)
background-color var(--color-bg)
background-repeat no-repeat
background-position center 2vh
background-size 5%
font-family 'Pt sans narrow', sans-serif
font-size 1.5rem
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
animation:blink 2s cubic-bezier(1,2.33,1,-2.33) 4 backwards
&.cda-naked
#cdawrap
top 5vw
right 5vw
--cda-text-color var(--color-link)
--cda-text-weight inherit
font-size 14px
--cda-width 220px
padding 0
@keyframes blink
to
background-image url(https://www.lacor.info/accueil/galerie-livres/img/arrow-16-512.png)
::-webkit-scrollbar-track
-webkit-box-shadow inset 0 0 1px $scroll--shadow
background-color $scroll--bg
border-radius 10px
::-webkit-scrollbar
width 5px
background-color $scroll--bg
::-webkit-scrollbar-thumb
border-radius: 10px
background-color $scroll--bg
background-image -webkit-gradient(linear, 40% 0%, 75% 84%, from($scroll--shadow), to($scroll--shadow), color-stop(0.6, $scroll--bar))
.demo-1
--color-text hsl(240,51%,31%)
--color-bg hsl(240,51%,21%)
--color-bg rgba(5,5,5,0.2)
--color-link-hover #5c4541
font-size 1.25rem
font-family ivymode, sans-serif
--size-title 10vw
--blendmode-title overlay
--font-title ivymode
--aspect-ratio 1/1.5
--imgwidthmax 35vw
.content__item-imgwrap
outline 1px solid hsl(240,21%,11%)
box-shadow 0 0 10px 0 hsl(240,41%,11%)
.js
.loading
&::before
content ''
position fixed
z-index 100000
top 0
left 0
width 100%
height 100vh
background var(--color-bg)
&::after
content ''
position fixed
z-index 100000
top 50%
left 50%
width 60px
height 60px
margin -30px 0 0 -30px
pointer-events none
border-radius 50%
opacity 0.4
background var(--color-link)
animation:loaderAnim 0.7s linear infinite alternate forwards
@keyframes loaderAnim
to
opacity 1
transform scale3d(0.5,0.5,1)
a
text-decoration none
color var(--color-link)
outline none
a:hover,
a:focus
color var(--color-link-hover)
outline none
.page
display grid
padding 5vw
max-width 700px
margin 0 auto
grid-template-columns 100%
grid-template-areas 'header' 'meta' 'grid'
will-change transform
.page__title
grid-area header
margin 0 0 1rem
font-size inherit
font-weight 400
.credits
text-align center
.credits--fixed
position fixed
bottom 1vh
margin 0
left 5vw
width 90vw
text-align right
&::before
content ''
background currentColor
position absolute
left 0
bottom 0
height 1rem
width 1px
.meta
grid-area meta
.meta--center
justify-self center
padding-top 20vh
.meta__links
display flex
flex-wrap wrap
line-height 1.5
a
margin 0 1.5rem 0 0
.meta__links--column
flex-direction column
.meta__demos
margin-top 1rem
.meta__demo
display inline-block
margin-right 0.75rem
.meta__demo--current
color var(--color-link-hover)
pointer-events none
.content
grid-area grid
margin 50vh 0 2vh
.content--offset
display grid
grid-template-columns repeat(2, minmax(100px, 1fr))
grid-gap 30vh 10vw
.content__item
margin 0 auto 15vh
&:nth-child(even)
align-self end
margin-bottom -20vh
.content--full
width 70vw
justify-self center
.content--padded
padding 0 10vw
.content__item
--imgwidth calc(var(--imgwidthmax) * var(--aspect-ratio))
width var(--imgwidth)
max-width 100%
position relative
will-change transform
margin-bottom 32vh
display grid
grid-template-columns 50% 50%
&:nth-child(even)
.content__item-number
right auto
left -20vw
&:nth-child(odd)
.content__item-number
left auto
right -20vw
.content__item--wide
grid-template-columns 20% 80%
&:nth-child(even)
grid-template-columns 80% 20%
.content--center
.content__item
margin 0 auto 60vh
.content__item-title
grid-area 1 / 1 / 3 / 3
margin auto
.content__item--expand
width 100%
grid-template-columns minmax(0, var(--imgwidth)) 1fr
&:nth-child(even)
grid-template-columns 1fr minmax(0, var(--imgwidth))
.content__item-imgwrap
grid-area 1 / 2 / 3 / 3
justify-self end
.content__item-description
grid-area 1 / 1 / 3 / 2
justify-self end
.content__item-imgwrap
grid-area 1 / 1 / 3 / 2
.content__item-description
grid-area 1 / 2 / 3 / 3
justify-self start
text-align center
align-self start
padding 0 2rem
width 250px
font-size 0.9rem
.content--alternate
.content__item
max-width 90vw
&:nth-child(even)
margin-left auto
.content__item-imgwrap
position relative
--imgwidth 100%
margin 0 auto
grid-area 1 / 1 / 3 / 3
overflow hidden
width var(--imgwidth)
padding-bottom calc(var(--imgwidth) / (var(--aspect-ratio)))
will-change transform
.content__item-img
--overflow 40px
height calc(100% + (2 * var(--overflow)))
top calc( -1 * var(--overflow))
width 100%
position absolute
background-size cover
background-repeat no-repeat
background-position 50% 150%
will-change transform
opacity 0.8
.content__item-img--t1
--overflow 60px
.content__item-img--t2
--overflow 80px
.content__item-img--t3
--overflow 120px
.content__item-number
opacity 0.07
font-size 25vw
position absolute
top -7vw
right -10vw
line-height 1
.content__item-title
position relative
font-size var(--size-title)
padding 0 3vw
margin calc(var(--size-title) * -1/2) 0 0 0
align-self start
line-height 1
font-family var(--font-title)
font-weight var(--font-weight-title)
color var(--color-title)
will-change transform
mix-blend-mode var(--blendmode-title)
.content__item-title--layer
padding 0
z-index 10
grid-area 1 / 1 / 2 / 3
width 100%
text-align center
.content__item-description
grid-area 3 / 1 / 3 / 3
width 100%
position relative
margin 0
padding 1rem 0 0 0
color var(--color-description)
.content--alternate .content__item-title,
.content__item--wide:nth-child(even) .content__item-description
grid-area 3 / 1 / 4 / 2
justify-self start
.content--alternate .content__item:nth-child(even) .content__item-title,
.content__item--wide .content__item-description
grid-area 3 / 2 / 4 / 3
justify-self end
width auto
.content__item-deco
position absolute
height 30%
width 0
right -10vw
line-height 1
background blue
opacity 0.07
.content__item-decobar
width 140%
height 25%
top 20%
left -20%
position absolute
background red
mix-blend-mode color-burn
@media screen and (min-width: 53em)
.page--layout-1
grid-template-columns 30% 70%
grid-template-areas 'header header' '... meta' 'grid grid'
.page--layout-2
grid-template-columns 1fr 1fr
grid-template-areas 'header meta' '... meta' 'grid grid'
@media screen and (max-width: 40em)
.content__item--expand .content__item-imgwrap,
.content__item--expand:nth-child(even) .content__item-imgwrap
grid-area 1 / 1 / 3 / 3
@media screen and (max-width: 40em)
.content__item--expand .content__item-description,
.content__item--expand:nth-child(even) .content__item-description,
.content__item--wide .content__item-description,
.content__item--wide:nth-child(even) .content__item-description
grid-area 3 / 1 / 4 / 3
padding 1rem 0
width 100%
text-align center
@media screen and (max-width: 40em)
.content__item--wide
.content__item-description
padding 1rem
@media screen and (max-width: 40em)
.content--alternate .content__item-title,
.content--alternate .content__item:nth-child(even) .content__item-title
grid-area 1 / 1 / 4 / 2
/**
* demo.js
* http://www.codrops.com
*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright 2019, Codrops
* http://www.codrops.com
*/
{
// helper functions
const MathUtils = {
// map number x from range [a, b] to [c, d]
map: (x, a, b, c, d) => (x - a) * (d - c) / (b - a) + c,
// linear interpolation
lerp: (a, b, n) => (1 - n) * a + n * b,
// Random float
getRandomFloat: (min, max) => (Math.random() * (max - min) + min).toFixed(2)
};
// body element
const body = document.body;
// calculate the viewport size
let winsize;
const calcWinsize = () => winsize = {width: window.innerWidth, height: window.innerHeight};
calcWinsize();
// and recalculate on resize
window.addEventListener('resize', calcWinsize);
// scroll position
let docScroll;
// for scroll speed calculation
let lastScroll;
let scrollingSpeed = 0;
// scroll position update function
const getPageYScroll = () => docScroll = window.pageYOffset || document.documentElement.scrollTop;
window.addEventListener('scroll', getPageYScroll);
// Item
class Item {
constructor(el) {
// the .item element
this.DOM = {el: el};
// the inner image
this.DOM.image = this.DOM.el.querySelector('.content__item-img');
this.DOM.imageWrapper = this.DOM.image.parentNode;
this.DOM.title = this.DOM.el.querySelector('.content__item-title');
this.renderedStyles = {
// here we define which property will change as we scroll the page and the item is inside the viewport
// in this case we will be:
// - scaling the inner image
// - translating the item's title
// we interpolate between the previous and current value to achieve a smooth effect
imageScale: {
// interpolated value
previous: 0,
// current value
current: 0,
// amount to interpolate
ease: 0.1,
// current value setter
setValue: () => {
const toValue = 1.5;
const fromValue = 1;
const val = MathUtils.map(this.props.top - docScroll, winsize.height, -1 * this.props.height, fromValue, toValue);
return Math.max(Math.min(val, toValue), fromValue);
}
},
titleTranslationY: {
previous: 0,
current: 0,
ease: 0.1,
fromValue: Number(MathUtils.getRandomFloat(30,100)),
setValue: () => {
const fromValue = this.renderedStyles.titleTranslationY.fromValue;
const toValue = -1*fromValue;
const val = MathUtils.map(this.props.top - docScroll, winsize.height, -1 * this.props.height, fromValue, toValue);
return fromValue < 0 ? Math.min(Math.max(val, fromValue), toValue) : Math.max(Math.min(val, fromValue), toValue);
}
}
};
// gets the item's height and top (relative to the document)
this.getSize();
// set the initial values
this.update();
// use the IntersectionObserver API to check when the element is inside the viewport
// only then the element styles will be updated
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => this.isVisible = entry.intersectionRatio > 0);
});
this.observer.observe(this.DOM.el);
// init/bind events
this.initEvents();
}
update() {
// sets the initial value (no interpolation)
for (const key in this.renderedStyles ) {
this.renderedStyles[key].current = this.renderedStyles[key].previous = this.renderedStyles[key].setValue();
}
// apply changes/styles
this.layout();
}
getSize() {
const rect = this.DOM.el.getBoundingClientRect();
this.props = {
// item's height
height: rect.height,
// offset top relative to the document
top: docScroll + rect.top
}
}
initEvents() {
window.addEventListener('resize', () => this.resize());
}
resize() {
// gets the item's height and top (relative to the document)
this.getSize();
// on resize reset sizes and update styles
this.update();
}
render() {
// update the current and interpolated values
for (const key in this.renderedStyles ) {
this.renderedStyles[key].current = this.renderedStyles[key].setValue();
this.renderedStyles[key].previous = MathUtils.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].ease);
}
// and apply changes
this.layout();
}
layout() {
// scale the image
this.DOM.image.style.transform = `scale3d(${this.renderedStyles.imageScale.previous},${this.renderedStyles.imageScale.previous},1)`;
// translate the title
this.DOM.title.style.transform = `translate3d(0,${this.renderedStyles.titleTranslationY.previous}px,0)`;
}
}
// SmoothScroll
class SmoothScroll {
constructor() {
// the <main> element
this.DOM = {main: document.querySelector('main')};
// the scrollable element
// we translate this element when scrolling (y-axis)
this.DOM.scrollable = this.DOM.main.querySelector('div[data-scroll]');
// the items on the page
this.items = [];
this.DOM.content = this.DOM.main.querySelector('.content');
[...this.DOM.content.querySelectorAll('.content__item')].forEach(item => this.items.push(new Item(item)));
// here we define which property will change as we scroll the page
// in this case we will be translating on the y-axis
// we interpolate between the previous and current value to achieve the smooth scrolling effect
this.renderedStyles = {
translationY: {
// interpolated value
previous: 0,
// current value
current: 0,
// amount to interpolate
ease: 0.1,
// current value setter
// in this case the value of the translation will be the same like the document scroll
setValue: () => docScroll
}
};
// set the body's height
this.setSize();
// set the initial values
this.update();
// the <main> element's style needs to be modified
this.style();
// init/bind events
this.initEvents();
// start the render loop
requestAnimationFrame(() => this.render());
}
update() {
// sets the initial value (no interpolation) - translate the scroll value
for (const key in this.renderedStyles ) {
this.renderedStyles[key].current = this.renderedStyles[key].previous = this.renderedStyles[key].setValue();
}
// translate the scrollable element
this.layout();
}
layout() {
this.DOM.scrollable.style.transform = `translate3d(0,${-1*this.renderedStyles.translationY.previous}px,0)`;
}
setSize() {
// set the heigh of the body in order to keep the scrollbar on the page
body.style.height = `${this.DOM.scrollable.scrollHeight}px`;
}
style() {
// the <main> needs to "stick" to the screen and not scroll
// for that we set it to position fixed and overflow hidden
this.DOM.main.style.position = 'fixed';
this.DOM.main.style.width = this.DOM.main.style.height = '100%';
this.DOM.main.style.top = this.DOM.main.style.left = 0;
this.DOM.main.style.overflow = 'hidden';
}
initEvents() {
// on resize reset the body's height
window.addEventListener('resize', () => this.setSize());
}
render() {
// Get scrolling speed
// Update lastScroll
scrollingSpeed = Math.abs(docScroll - lastScroll);
lastScroll = docScroll;
// update the current and interpolated values
for (const key in this.renderedStyles ) {
this.renderedStyles[key].current = this.renderedStyles[key].setValue();
this.renderedStyles[key].previous = MathUtils.lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].ease);
}
// and translate the scrollable element
this.layout();
// for every item
for (const item of this.items) {
// if the item is inside the viewport call it's render function
// this will update item's styles, based on the document scroll value and the item's position on the viewport
if ( item.isVisible ) {
if ( item.insideViewport ) {
item.render();
}
else {
item.insideViewport = true;
item.update();
}
}
else {
item.insideViewport = false;
}
}
// loop..
requestAnimationFrame(() => this.render());
}
}
/***********************************/
/********** Preload stuff **********/
// Preload images
const preloadImages = () => {
return new Promise((resolve, reject) => {
imagesLoaded(document.querySelectorAll('.content__item-img'), {background: true}, resolve);
});
};
// And then..
preloadImages().then(() => {
// Remove the loader
document.body.classList.remove('loading');
// Get the scroll position and update the lastScroll variable
getPageYScroll();
lastScroll = docScroll;
// Initialize the Smooth Scrolling
new SmoothScroll();
});
}
Also see: Tab Triggers