Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Frontend Practice Demo</title>
<style>
/* Micro-reset */
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
/* Gallery styles */
body {
font-family: sans-serif; font-size: 100%;
margin: 1em 2em;
}
h1 { font-size: 3em; margin-bottom: 0.3em; }
aside { font-size: 120%; }
code { font-family: Monaco, monospace; font-size: 95%; background: #eed; border: 1px solid #e9e9d9; padding: 0 3px; }
.images > li {
margin: 5.5em 0 60vh;
}
.image {
display: block;
max-width: 100%;
width: 500px; height: 258px; /* hardcoded to have <div>s match the example images */
cursor: pointer;
}
.image.image--text-example {
font-size: 500%;
line-height: 3;
font-weight: bold;
text-align: center;
}
.image.image--mbm {
mix-blend-mode: difference;
}
.slide-container {
position: relative;
}
.slider {
position: absolute;
left: 0; top: 0;
transform: translateX(520px);
transition: transform .8s ease, filter .8s ease, mix-blend-mode .8s ease;
}
/*
This is a *really* rudimentary step-by-step demo system,
driven by clicking on examples.
Each slide-container will have an animate-N class applied to it
every time one of its boxes/images are clicked. Accordingly, the class
.example-1.animate-1 describes what CSS rules to layer on when
either of the first example's red or blue box is clicked.
*/
/* The first thing any of the examples do is slide the right-hand image
on top of the left-hand image. */
.animate-1 .slider {
transform: translateX(0px);
}
/* Rules for specific examples, eg. the kittens in example 6. */
.example-6.animate-2,
.example-6b.animate-2 {
filter: invert(1);
}
.example-6b.animate-3 {
filter: invert(1) saturate(300%);
}
.example-6b.animate-4 {
filter: invert(1) saturate(2000%);
}
.example-7.animate-2 {
filter: invert(1);
}
.example-7.animate-3 {
filter: invert(1) saturate(500%);
}
.example-7.animate-4 {
height: 100vh; width: 100vw;
position: fixed;
top: 0; left: 0;
background: black;
border: 50px solid #222; /* because filter: invert(1), this #222 shows as #ddd. */
margin: 0 auto;
}
.example-7.animate-4 > .image {
width: 100%;
height: auto;
}
.example-7.animate-5 {
filter: none;
border-color: #ddd; /* keep the border *looking* the same as the previous value */
}
.example-7.animate-5 > .slider {
mix-blend-mode: normal;
display: none;
}
.example-7.animate-6 > .slider {
display: block;
}
.example-7.animate-7 > .slider {
display: none;
}
.example-7.animate-8 > .slider {
display: block;
}
</style>
</head>
<body>
<h1>Really Shitty Image Diffs™</h1>
<aside>
with CSS' <em>mix-blend-mode</em> and <em>filter</em>.
</aside>
<ul class="images">
<li>
<h3>Positioning</h3>
<div class="slide-container example-1">
<div class="image" style="background-color: #f00;"></div>
<div class="image slider" style="background-color: #00f;"></div>
</div>
</li>
<li>
<h3>Introducing <code>mix-blend-mode: difference</code> (currently applied to the <span style="color: #00f;">blue box</span>)</h3>
<div class="slide-container example-2">
<div class="image" style="background-color: #f00;"></div>
<div class="image image--mbm slider" style="background-color: #00f;"></div>
</div>
</li>
<li>
<h3>Using <code>mix-blend-mode: difference</code> with the same background and some shapes</h3>
<div class="slide-container example-3">
<div class="image" style="background-color: #f00; "></div>
<div class="image image--text-example image--mbm slider" style="background-color: #f00; color: #00f;">
Hello!
</div>
</div>
</li>
<li>
<h3>Using <code>mix-blend-mode: difference</code> with similar shapes</h3>
<div class="slide-container example-4">
<div class="image image--text-example" style="background-color: #eee; color: #00f;">
Hello!
</div>
<div class="image image--text-example image--mbm slider" style="background-color: #eee; color: #00f; padding-left: 13px;">
Jello!
</div>
</div>
</li>
<li>
<h3>Using <code>mix-blend-mode: difference</code> with an image</h3>
<div class="slide-container example-5">
<img class="image" src="500_comparison.png" />
<img class="image slider image--mbm" src="500_branch.png" />
</div>
</li>
<li>
<h3>Using <code>filter: invert(1)</code> on the container</h3>
<div class="slide-container example-6">
<img class="image" src="500_comparison.png" />
<img class="image slider image--mbm" src="500_branch.png" />
</div>
</li>
<li>
<h3>Using <code>filter: invert(1) saturate(2000%)</code> on the container</h3>
<div class="slide-container example-6b">
<img class="image" src="500_comparison.png" />
<img class="image slider image--mbm" src="500_branch.png" />
</div>
</li>
<li>
<h3>Here's one we made earlier</h3>
<div class="slide-container example-7">
<img class="image" src="empty_state__comparison.png" />
<img class="image image--mbm slider" src="empty_state__e8d898c3a3b0.png" />
</div>
</li>
<li>
<h3>References / Examples</h3>
<p><a href="https://css-tricks.com/almanac/properties/m/mix-blend-mode/">https://css-tricks.com/almanac/properties/m/mix-blend-mode/</a></p>
<p><a href="https://css-tricks.com/almanac/properties/f/filter/">https://css-tricks.com/almanac/properties/f/filter/</a></p>
</li>
</ul>
<script>
// Party like it's 2005... but with 2017 APIs.
for (const img of document.querySelectorAll('.image')) {
img.addEventListener('click', e => {
for (const i of Array.from(Array(10), (e, n) => n + 1)) {
const cls = 'animate-' + i;
const elt = e.target.parentElement;
if (!elt.classList.contains(cls)) {
elt.classList.add(cls);
break;
}
}
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment