<ul class="c-shutter" style="--message: 'Hello'">
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
<li class="c-shutter__slat"></li>
</ul>
World
<!-- DEMO CONTROLS -->
<button class="c-demo"></button>
// Variables
$root: ".c-shutter";
$color-foreground: #0000dd;
$color-background: #fdfdfd;
// Imports
@import url("https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@700&display=swap");
// Styles
:root {
font-family: "Red Hat Display", sans-serif;
--color-foreground: #{$color-foreground};
--color-background: #{$color-background};
--delay: 10;
}
body {
margin: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
color: var(--color-foreground);
line-height: 1.5;
height: 100vh;
}
#{$root} {
--fill: forwards;
--message: '';
font-size: 3rem;
color: var(--color-foreground);
line-height: 1.5;
flex-direction: row;
display: flex;
position: fixed;
top: 0;
left: 0;
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
list-style: none;
user-select: none;
&__slat {
height: 100%;
overflow: hidden;
position: relative;
flex-grow: 1;
background-color: var(--color-foreground);
animation-name: var(--animation);
animation-duration: 1s;
animation-timing-function: ease-in-out;
animation-fill-mode: var(--fill);
animation-play-state: var(--state);
animation-direction: var(--direction);
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
animation-delay: calc(#{$i} / var(--delay) * 1s);
&:before {
margin-left: calc(#{$i - 1} * -10vw);
//padding-left: calc(50vw);
}
}
}
&:before {
content: var(--message);
color: var(--color-background);
position: absolute;
top: 0;
width: 100vw;
height: 100%;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
}
&--opened:not(&--closing) {
display: none;
}
&--opened &__slat {
height: 0%;
}
&--closed {
display: flex;
}
&--opening {
--animation: shutterOpening;
}
&--closing {
--animation: shutterClosing;
}
}
@keyframes shutterOpening {
0% {
height: 100%;
}
100% {
height: 0;
}
}
@keyframes shutterClosing {
0% {
height: 0%;
}
100% {
height: 100%;
}
}
// Demo controls
.c-demo {
position: fixed;
cursor: pointer;
font-family: "Red Hat Display", Arial, sans-serif;
font-size: 1rem;
background-color: var(--color-background);
color: var(--color-foreground);
bottom: 1rem;
left: 50%;
transform: translatex(-50%);
padding: 1rem 2rem;
border-radius: 0.25rem;
border: none;
transition: opacity .5s ease-in-out, outline .5s ease-in-out;
&:before {
content: "Open";
}
}
.c-shutter--opened ~ .c-demo {
background-color: var(--color-foreground);
color: var(--color-background);
&:before {
content: "Close";
}
}
.c-shutter--opening ~ .c-demo,
.c-shutter--closing ~ .c-demo,
.c-demo:disabled {
pointer-events: none;
opacity: 0;
&:before {
content: "Running...";
}
&:focus {
outline: none;
}
}
View Compiled
const CLASS = {
ROOT: 'c-shutter',
OPENED: 'c-shutter--opened',
OPENING: 'c-shutter--opening',
CLOSED: 'c-shutter--closed',
CLOSING: 'c-shutter--closing',
ITEMS: 'c-shutter__slat'
}
class Shutter {
constructor(dom) {
this.state = false;
this.container = dom;
}
open(){
this.state = true;
this.toggle(true);
}
close(){
this.state = false;
this.toggle(false);
}
toggle(visibility){
this.container.classList.toggle(CLASS.OPENING, visibility);
this.container.classList.toggle(CLASS.CLOSING, !visibility);
setTimeout(() => {
this.container.classList.remove(CLASS.OPENING);
this.container.classList.remove(CLASS.CLOSING);
this.container.classList.toggle(CLASS.OPENED, visibility);
this.container.classList.toggle(CLASS.CLOSED, !visibility);
}, 1999)
}
getState(){
return this.state;
}
}
const $shutter = document.querySelector('.c-shutter');
let shutter = new Shutter($shutter);
// Demo controls
let demoBtn = document.querySelector('.c-demo');
demoBtn.addEventListener('click', () => {
shutter.getState() ? shutter.close() : shutter.open();
})
// Force demo click
var click = function (elem) {
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
elem.dispatchEvent(evt);
};
demoBtn.disabled = true;
setTimeout(() => {
demoBtn.disabled = false;
click(demoBtn);
}, 2000);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.