Skip to content

Instantly share code, notes, and snippets.

@shshaw
Last active June 1, 2018 18:11
Show Gist options
  • Save shshaw/26179995ab27113da9c08416a4a6a658 to your computer and use it in GitHub Desktop.
Save shshaw/26179995ab27113da9c08416a4a6a658 to your computer and use it in GitHub Desktop.
@keyframers 1.8.0 | Bike Blender 🚲🌪️
<a href="https://youtu.be/Wt5ENQj9FCQ" target="_blank" data-keyframers-credit style="color: #000"></a>
<script src="https://codepen.io/shshaw/pen/QmZYMG.js"></script>
<div id="app" data-state="bike">
<div class="ui-circle"></div>
<header class="ui-header">
<button id="back"></button>
</header>
<div data-scene="bike">
<h1 class="ui-heading _fade-up">Classic Bike X4</h1>
<div class="ui-hero _fade-up">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/39255/pink-bike_compressed.png" />
</div>
<div class="ui-details _fade-up">
<div class="ui-spec">
<div class="ui-label">Advised for height</div>
<div class="ui-data">155-170 cm</div>
</div>
<div class="ui-spec">
<div class="ui-label">Bike weight</div>
<div class="ui-data">12 kg</div>
</div>
<div class="ui-spec">
<div class="ui-label">Rating</div>
<div class="ui-data -rating">★★★☆☆</div>
</div>
<div class="ui-spec">
<div class="ui-label">Open bikes</div>
<div class="ui-data">34</div>
</div>
<div class="ui-description">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Blanditiis expedita in mollitia aliquid pariatur eveniet laboriosam, etc.
</div>
</div>
<footer class="ui-footer">
<button class="ui-button" id="cta">
<div class="ui-bg" data-flip-key="bg"></div>
<span>Rent from $2</span>
</button>
</footer>
</div>
<div data-scene="time">
<h1 class="ui-heading _fade-down">Buy Time</h1>
<p class="ui-description _fade-down">Choose your desired plan to get access to our bikes easily.</p>
<div class="ui-plans _fade-down" style="--total: 4">
<div class="ui-plan" style="--i: 0">
<div class="ui-bg"></div>
<div class="ui-time">30 Minutes</div>
<div class="ui-price">$2</div>
</div>
<div class="ui-plan" style="--i: 1">
<div class="ui-bg"></div>
<div class="ui-time">60 Minutes</div>
<div class="ui-price">$3</div>
</div>
<div class="ui-plan" style="--i: 2">
<div class="ui-bg"></div>
<div class="ui-time">120 Minutes</div>
<div class="ui-price">$4</div>
</div>
<div class="ui-plan -featured" style="--i: 3">
<div class="ui-bg" data-flip-key="bg"></div>
<div class="ui-time">1 Day</div>
<div class="ui-price">$20</div>
</div>
<div class="ui-plan" style="--i: 3">
<div class="ui-bg"></div>
<div class="ui-time">7 Days</div>
<div class="ui-price">$160</div>
</div>
</div>
</div>
<div data-scene="ride">
<h1 class="ui-heading _fade-up">My Ride</h1>
<div class="ui-card _fade-scale">
<div class="ui-label">Current Location</div>
<div class="ui-title">Houston<br />Texas</div>
<div class="ui-map"></div>
</div>
<div class="ui-details" style="--total: 3">
<div class="ui-spec" style="--i: 0">
<div class="ui-label">duration (h:m)</div>
<div class="ui-data">2:45</div>
</div>
<div class="ui-spec" style="--i: 0">
<div class="ui-label">calories (kcal)</div>
<div class="ui-data">183</div>
</div>
<div class="ui-spec" style="--i: 1">
<div class="ui-label">distance (km)</div>
<div class="ui-data">10,2</div>
</div>
<div class="ui-spec" style="--i: 1">
<div class="ui-label">carbon</div>
<div class="ui-data">2137</div>
</div>
<div class="ui-spec" style="--i: 2">
<div class="ui-label">speed (km/h)</div>
<div class="ui-data">9,5</div>
</div>
<div class="ui-spec" style="--i: 2">
<div class="ui-label">steps</div>
<div class="ui-data">12,584</div>
</div>
</div>
<footer class="ui-footer">
<button class="ui-button" id="edit">
<div class="ui-bg" data-flip-key="bg"></div>
<span>Go Back</span>
</button>
</footer>
</div>
</div>

@keyframers 1.8.0 | Bike Blender 🚲🌪️

Watch us code this live!

This week, David Khourshid and Stephen Shaw make a Bicycle App animation using mostly CSS and some dubious JavaScript. Streamed live on May 31, 2018.

Shownotes:

Additional Resources:

Like what we're doing? There are many ways you can support @keyframers so we can keep live coding awesome animations!

Topics covered:

  • CSS Variables
  • Staggering

A Pen by Shaw on CodePen.

License.

console.clear();
const elCta = document.querySelector("#cta");
const elApp = document.querySelector("#app");
const elBacko = document.querySelector("#back");
const elEdit = document.querySelector("#edit");
const losPlans = document.querySelectorAll(".ui-plan");
const flipping = new Flipping({
duration: 500
});
elCta.addEventListener(
"click",
flipping.wrap(() => {
app.setAttribute("data-state", "time");
})
);
elBacko.addEventListener(
"click",
flipping.wrap(() => {
app.setAttribute("data-state", app.dataset.state === "time" ? "bike" : "time");
})
);
elEdit.addEventListener(
"click",
flipping.wrap(() => {
app.setAttribute("data-state", "time");
})
);
Array.from(losPlans).forEach(elPlan => {
elPlan.addEventListener(
"click",
flipping.wrap(() => {
app.setAttribute("data-state", "ride");
})
);
});
<script src="https://unpkg.com/flipping@latest/dist/flipping.web.js"></script>
@import url('https://fonts.googleapis.com/css?family=Lato:400,700');
$color-primary: #6376FF;
$radius: 3px;
$duration: 0.4s;
*, *:before, *:after {
--last-index: (var(--total) - var(--i));
box-sizing: border-box;
position: relative;
}
img { max-width: 100%; height: auto; }
body {
display: flex;
justify-content: center;
align-items: center;
background-color: #EEF0FF;
}
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
html {
font-size: 2vmin;
}
// -----------------------------
#app {
font-family: 'Lato', sans-serif;
background-color: #fff;
height: 92vmin;
width: 55vmin;
box-shadow: 0 1rem 2rem rgba(black, 0.1);
padding: 2rem 1rem;
display: grid;
grid-template-rows: 1fr 90% 1fr;
overflow:hidden;
> [data-scene] {
grid-row: 2 / 3;
}
}
#back {
appearance: none;
-webkit-appearance: none;
border: none;
background: none;
padding: 0;
margin: 0;
height: 1rem;
width: 1rem;
transform: rotate(-45deg);
&:before, &:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 1px solid gray;
}
&:before, &:after {
border-bottom: none;
border-right: none;
}
&:before {
transform-origin: center left;
}
&:after {
border-left: none;
transform-origin: top left;
transform: rotate(45deg) translateY(-1px) scaleX(1.5);
}
}
[data-scene] {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: grid;
padding: 0 1rem;
$button-height: 3rem;
&[data-scene="bike"] {
grid-template-rows: 2rem 1fr 1fr $button-height;
grid-row-gap: 1rem;
}
&[data-scene="time"] {
grid-template-rows: 2rem 3rem 1fr;
}
&[data-scene="ride"] {
grid-template-rows: 2rem 10rem 1fr $button-height;
grid-row-gap: 1rem;
}
}
[data-scene] {
transition: visibility 0s linear;
}
// general transitions
._fade-up,
._fade-down,
._fade-scale {
transition-property: opacity, transform;
transition-duration: $duration;
visibility: visible !important;
}
[data-state="bike"] > [data-scene]:not([data-scene="bike"]),
[data-state="time"] > [data-scene]:not([data-scene="time"]),
[data-state="ride"] > [data-scene]:not([data-scene="ride"]) {
visibility: hidden;
transition-delay: $duration * 2;
pointer-events: none;
._fade-up {
transform: translateY(-1rem);
}
._fade-down {
transform: translateY(1rem);
}
._fade-scale {
transform: scale(.8);
}
[class*="_fade"] {
opacity: 0;
}
[data-flip-key] { display: none; }
}
// -----------------------------
.ui-heading {
margin: 0;
font-size: 1.5rem;
}
.ui-details {
display: grid;
grid-template-rows: 1fr 1fr auto;
grid-template-columns: 3fr 1fr;
}
.ui-spec {
margin-bottom: 1.5rem;
> .ui-label {
font-size: .6rem;
text-transform: uppercase;
font-weight: bold;
margin-bottom: .5rem;
}
}
.ui-data {
font-size: 1.5rem;
font-weight: bold;
&.-rating {
letter-spacing: .5rem;
}
}
.ui-description {
grid-column: 1 / -1;
font-size: 1rem;
}
.ui-button {
--bg: #{$color-primary};
appearance: none;
border: none;
border-radius: $radius;
color: white;
font-size: .75rem;
text-transform: uppercase;
letter-spacing: 2px;
font-weight: bold;
width: 100%;
height: 100%;
> .ui-bg {
box-shadow: 0 0 1rem rgba($color-primary, .5);
}
}
button:focus {
outline: none !important;
}
.ui-plans {
margin-top: 2rem;
}
.ui-plan {
--bg: #f1f1f1;
border-radius: $radius;
margin-bottom: 1rem;
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 1.5rem 2rem;
font-size: 1.25em;
&:last-child {
margin-bottom: 0;
}
> .ui-time, > .ui-price {
font-weight: bold;
}
> .ui-price {
color: #8b8b8b;
}
&.-featured {
background: none;
padding-top: 3rem;
--bg: #{$color-primary};
&, > * {
color: white;
}
&:after {
content: 'best value';
text-transform: uppercase;
display: block;
position: absolute;
top: 0;
width: 100%;
height: 2rem;
line-height: 2rem;
background-color: rgba(black, 0.2);
left: 0;
padding-left: 2rem;
font-size: .5rem;
letter-spacing: 2px;
font-weight: bold;
opacity: 0;
}
}
}
// -----------------------------
.ui-plan,
.ui-plan:after,
.ui-plan .ui-bg,
.ui-time,
.ui-price {
transition: all $duration linear;
transition-timing-function: ease-in-out,
cubic-bezier(.63,.0,.4,1);// cubic-bezier(.5, 0, .5, 1);
transition-property: transform, opacity;
--stagger: calc( #{$duration} + (.05s * var(--last-index)) );
transition-duration: calc( var(--stagger) );
// opacity: 0;
transform: translateY( 100% ); //150% * (var(--last-index) + 1)) );
}
.ui-plan .ui-bg { opacity: 0; }
.ui-plans .ui-plan.-featured {
opacity: 1;
transform: translateY(0);
}
.ui-time, .ui-price {
opacity: 0;
transform: translateY(-20%);
}
[data-state="time"] {
.ui-plan,
.ui-time,
.ui-price,
.ui-plan .ui-bg,
.ui-plan:after {
transform: translateY(0);
opacity: 1;
}
.ui-plan.-featured:after {
opacity: 1;
transition-delay: .2s;
}
}
// -----------------------------
.ui-bg {
background-color: var(--bg);
border-radius: inherit;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ui-circle {
position: absolute;
top: 0;
left: 0;
height: 50%;
width: 100%;
transform-origin: bottom left;
transform: rotate(0deg);
transition: transform ($duration * 1.25) cubic-bezier(.5, 0, .5, 1);
&:before {
content: '';
display: block;
position: absolute;
top: 10%; right: -15%; bottom: 0; left: 0;
margin-left: auto;
border-radius: 50%;
width: 80%;
padding-top: 80%;
height: 0;
background: #F6E38A;
}
[data-state="time"] & {
transform: rotate(-35deg);
}
[data-state="ride"] & {
transform: rotate(-120deg);
}
}
.ui-card {
display: grid;
grid-template-rows: 1rem 1fr;
grid-template-columns: 3fr 2fr;
padding: 1rem;
box-shadow: 0 1rem 2rem rgba(black, 0.1);
> .ui-label {
grid-row: 1 / 2;
grid-column: 1 / 2;
}
> .ui-title {
grid-row: 2 / 3;
grid-column: 1 / 2;
font-size: 2rem;
}
> .ui-map {
border-radius: $radius;
background-color: #ccc;
grid-row: 1 / -1;
grid-column: 2 / -1;
}
}
[data-scene="ride"] {
.ui-details {
padding: 1rem 0;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(2, 1fr);
}
.ui-spec {
opacity: 0;
transform: translateY(-2em);
transition: opacity $duration linear, transform $duration cubic-bezier(.25,.76,.4,1);
transition-duration: calc( #{$duration} + (.3s * var(--i)) );
[data-state="ride"] & {
opacity: 1;
transform: translateY(0%);
transition-delay: calc( .25s + (.05s * var(--i)) );
}
&:nth-child(2n) {
> * {
text-align: right;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment