<div class="app">
<div class="section color-section">
<article
data-swatch
class="colorswatch colorswatch--visible colorswatch--start"
style="--c-color: #f00; --c-shade0: #f01; --c-shade1: #f02;"
>
<div aria-hidden class="colorswatch__swatch">
<div class="colorswatch__shade"></div>
<div class="colorswatch__shade"></div>
<div class="colorswatch__shade"></div>
</div>
<header class="colorswatch__label">
<div class="colorswatch__info">
<h1 data-value class="colorswatch__row1">
Tap
</h1>
<h2 data-name class="colorswatch__row2">
Me
</h2>
</div>
</header>
</article>
</div>
<section data-info class="section color-tldr">
<h1>Random Color Explorer </h1>
<p>The names of color function like a thread attached to a frightfully slender needle, capable of stitching together our most delicate emotions and memories. When the needle hits the target, we feel either pleasure or empathy. <strong>Kenya Hara – White</strong></p>
<a
</section>
</div>
@import url('https://fonts.googleapis.com/css?family=Teko:300,500');
@import url('https://fonts.googleapis.com/css?family=Metrophobic:300,500');
:root {
font-family: 'Metrophobic', sans-serif;
font-size: calc(.7rem + 2.5vw);
background: #fff;
font-color: #000;
}
.app {
}
.section {
box-sizing: border-box;
padding: 2rem;
width: 50%;
}
.colorswatch--start .colorswatch__shade {
background: linear-gradient(-92deg, #EE7752, #E73C7E, #23A6D5, #23D5AB, #EE7752);
background-size: 400% 100%;
animation: gradient 15s ease infinite;
}
.colorswatch {
--s-label-height: 1.46em;
font-size: calc(.6rem + 5vmin);
cursor: pointer;
overflow: hidden;
//width: 80%;
position: absolute;
top: 2.5rem;
right: 2rem;
width: 100%;
max-width: 35vmin;
background: #212121;
&__swatch {
position: relative;
padding-top: calc(430% + 1px);
z-index: 1;
overflow: hidden;
}
&__shade {
position: absolute;
top: 0; right: 0; bottom: -1px; left: 0;
transform-origin: 50% 100%;
&:nth-child(1) {
background-color: var(--c-shade0);
}
&:nth-child(2) {
background-color: var(--c-shade1);
}
&:nth-child(3) {
background-color: var(--c-color);
}
}
&__label {
position: relative;
height: var(--s-label-height);
z-index: 2;
font-family: Teko;
margin-top: -1px;
background: #212121;
}
&__info {
position: absolute;
top: 0;
font-family: Teko;
left: 0;
right: 0;
background: #212121;
padding: 0 .3em;
color: #fff;
transform-origin: 50% 0;
span {
display: block;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: .2rem solid #212121;
pointer-events: none;
}
}
&__row1 {
font-weight: 900;
font-size: .55em;
height: 1.2em;
line-height: 1.2;
margin-top: 0.45em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&__row2 {
margin-top: -0.05em;
font-size: .57em;
font-weight: 300;
line-height: 1.2;
height: 1.2em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
// animation
.colorswatch {
--anim-appear-duration: 1100ms;
&__info {
height: 0;
transition: calc(var(--anim-appear-duration) * 0.2) height cubic-bezier(.7,.3,0,1);
transition-delay: calc(var(--anim-appear-duration) * 0.15);
overflow: hidden;
box-sizing: border-box;
will-change: height;
}
&__row1,
&__row2 {
opacity: 0;
transform: translateY(200%);
transition: calc(var(--anim-appear-duration) * 0.1) opacity linear,
calc(var(--anim-appear-duration) * 0.2) transform cubic-bezier(.7,.3,0,1);
}
&__row1 {
transition-delay: calc(var(--anim-appear-duration) * 0.05);
}
&__swatch {
transform: translateY(150%);
transition: calc(var(--anim-appear-duration) * 0.666) transform cubic-bezier(.8,.3,.25,1.75);
will-change: transform;
}
&__shade {
transform: scaleY(0);
transition: calc(var(--anim-appear-duration) * 0.2) transform ease-in;
&:nth-child(1) {
transition-delay: calc(var(--anim-appear-duration) * 0.06);
}
&:nth-child(2) {
transition-delay: calc(var(--anim-appear-duration) * 0.03);
}
&:nth-child(3) {
transition-delay: calc(var(--anim-appear-duration) * 0);
}
}
}
.colorswatch {
.colorswatch--visible & {
&__info {
height: var(--s-label-height);
transition: calc(var(--anim-appear-duration) * .6) height cubic-bezier(.7,.3,0,1);
transition-delay: var(--anim-appear-delay, 0ms);
}
&__row1,
&__row2 {
opacity: 1;
transform: translateY(0%);
transition: calc(var(--anim-appear-duration) * .05) opacity linear,
calc(var(--anim-appear-duration) * .7) height cubic-bezier(.8,.3,.25,1),
calc(var(--anim-appear-duration) * .7) transform cubic-bezier(.8,.3,.25,1);
transition-delay: calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * 0ms),
calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * 0ms);
transform-origin: 0 0;
}
&__row2 {
transition-delay: calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * .15),
calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * .15);
}
&__swatch {
transform: translateY(0);
transition: calc(var(--anim-appear-duration) * 0.566) transform cubic-bezier(.8,.3,.25,1);
will-change: transform;
transform-origin: 50% 0;
transition-delay: var(--anim-appear-delay, 0ms);
}
&__shade {
transition: calc(var(--anim-appear-duration) * 0.666) transform cubic-bezier(.7,.3,0,1);
transform: scaleY(1);
&:nth-child(1) {
transition-delay: calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * 0);
}
&:nth-child(2) {
transition-delay: calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * 0.1);
}
&:nth-child(3) {
transition-delay: calc(var(--anim-appear-delay, 0ms) + var(--anim-appear-duration) * 0.2);
}
}
}
}
@keyframes gradient {
100% {
background-position: 400% 50%;
}
}
.color-section {
position: fixed;
top: 0;
left: 0;
width: 50%;
}
.color-tldr {
margin-left: 50%;
padding-left: 0;
color: #000;
font-size: .45rem;
max-width: 13rem;
h1 {
font-weight: 900;
font-size: 1.5em;
margin-bottom: 1em;
margin-top: 2em;
font-family: Teko;
h2 {font-family: Teko;}
&:first-child {
margin-top: -.56ex;
}
}
b, strong {
font-weight: 900;
}
p + p {
margin-top: 1em;
}
line-height: 1.4;
a {
display: block;
color: #fff;
text-decoration: unerdline;
font-weight: bold;
margin-top: 1em;
}
img {
display: block;
float: left;
max-width: 60%;
margin: .3em 1em 1em 0;
position: relative;
}
.article {
clear: both;
& + .article {
padding-top: 1rem;
}
}
ul {
margin: 1em 0;
list-style-type: disc;
li {
margin: 1em;
}
}
*:first-child {
margin-top: 0;
}
}
View Compiled
const $el = document.querySelector('[data-swatch]');
const $name = document.querySelector('[data-name]');
const $val = document.querySelector('[data-value]');
function setColor(color) {
$el.style.setProperty('--c-color', color.hex());
if (color.luminance() < .5) {
$el.style.setProperty('--c-shade1', color.brighten(.75).hex());
$el.style.setProperty('--c-shade0', color.brighten(1.5).hex());
} else {
$el.style.setProperty('--c-shade1', color.darken(.75).hex());
$el.style.setProperty('--c-shade0', color.darken(1.5).hex());
}
}
$el.addEventListener('click', (e) => {
$el.classList.remove('colorswatch--visible');
const url = new URL('https://api.color.pizza/v1/');
const color = chroma.random();
const params = {
values: color.hex().replace('#', ''),
//goodnamesonly: true,
}
url.search = new URLSearchParams(params).toString();
document.querySelector('[data-info]').innerHTML = '';
fetch(url)
.then(response => response.json())
.then(data => {
colorMeaning(data.colors[0].name);
setTimeout(() => {
setColor(color, data.colors[0]);
$name.innerHTML = data.colors[0].name;
$val.innerHTML = color.hex();
$el.classList.remove('colorswatch--start');
$el.classList.add('colorswatch--visible');
}, 1100);
});
});
const nahWords = ['the', 'a', 'in', 'of', 'an', 'on'];
function nahWordsInExtremities (Word) {
const word = Word.toLowerCase();
return !!nahWords.find(nw => (word.startsWith(nw + ' ') || word.endsWith(' ' + nw)));
}
function splitWords (str) {
const arr = str.split(' ')
const min = 2
const result = new Set()
for (var i = arr.length; i >= min; i--) {
for (var j = 1; j <= i - min; j++) {
result.add(arr.slice(j, i).join(' '))
}
}
for (var k = arr.length - 1; k >= min; k--) {
result.add(arr.slice(0, k).join(' '))
}
arr.forEach(item => {
result.add(item)
})
const filtered = [...result].filter(e => !nahWordsInExtremities(e) && !nahWords.find(w => w === e.toLowerCase()));
return filtered;
}
/// wikipedia part
const unwantedProps = [
'dir',
'revision',
'tid',
'timestamp',
'pageid',
'namespace',
'titles',
'api_urls'
]
async function lookup (query, locale = 'en') {
const url = new URL(
`https://${locale}.wikipedia.org` +
`/api/rest_v1/page/summary/${encodeURIComponent(query.replace(/ /g, '_'))}?redirect=true`
)
let body;
try {
const res = await fetch(url).then(res => {
if (!res.ok) {
throw Error(res.statusText);
}
return res;
});
//console.log( res.headers.values() )
body = await res.json();
} catch (err) {
return null;
}
unwantedProps.forEach(prop => {
delete body[prop];
})
if (body.text) {
body.text = body.text
.trim()
.replace(/\[\d+\]/g, '')
} // remove footnotes like [1]
if (body.html) body.html = body.html.trim()
return Object.assign({}, { query: query }, body);
}
function extract(word) {
lookup(word).then(result => {
if (result && result.title !== "Not found.") {
populateInfo(result);
}
})
}
function colorMeaning (name) {
const splits = splitWords(name);
const lookupnames = [...new Set([name, ...splits])];
lookupnames.forEach(part =>
{
if( part.endsWith("'s") ) lookupnames.push(part.slice(0, -2));
if( !/\s/g.test(part) ) lookupnames.push(`${part} (color)`);
}
);
lookupnames.forEach(subWord => extract(subWord));
}
function populateInfo (result) {
document.querySelector('[data-info]').innerHTML +=
`<div class="article"><h1>${result.displaytitle}</h1>
${result.hasOwnProperty('thumbnail') ? `<img src="${result.thumbnail.source}" alt="${result.displaytitle}"/>` : ''}
<div>${result.extract_html}</div>
<a href="${result.content_urls.desktop.page}" target="_blank">Read more</a></div>
`;
}
// add definitions at some point: https://api.dictionaryapi.dev/api/v2/entries/en_US/rose
View Compiled
This Pen doesn't use any external CSS resources.