Celebration waterfall exercise

by AntowaKartowa

HTML

<main>
  <div class="emojiWrapper">
    <div class="emojiSpaceContainer">
      <div class="emojiSpace">
      </div>
    </div>
  </div>
  <img
    class="avatar"
    src="https://sandpack-bundler.vercel.app/img/avatars/002.png"
    alt="user avatar"
  />
  <h1>Someone Bought You A Coffee!</h1>
</main>

CSS

:root {
  --emojis: 'πŸŽ‰πŸ‘β˜•πŸŽŠπŸ’ΈπŸŽ‰πŸ‘β˜•πŸŽŠ';
  --emojis-qty: 5;
  --emoji-i: 0;
  --emoji-height: 1.5em;
  --emoji-width: 1.5em;
  --emoji-wrapper-height: 120px;
  --fall-duration: 3s;
  --deviation: .4em;
}
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}
html,
body {
  height: 100%;
}
body {
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}
input,
button,
textarea,
select {
  font: inherit;
}
p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}
#root,
#__next {
  isolation: isolate;
}

/* Basic theme styles */
body {
  padding: 16px;
  font-family: "Wotfard", sans-serif;
}

table {
  width: 100%;
  border-collapse: collapse;
}
th {
  text-align: left;
  border-bottom: 3px solid hsl(0deg 0% 25%);
}
th[scope="col"] {
  text-align: right;
  border-right: 3px solid hsl(0deg 0% 25%);
  border-bottom: none;
  padding-right: 8px;
}
tr:not(:last-of-type) th[scope="col"],
tr:not(:last-of-type) td {
  border-bottom: 1px solid hsl(0deg 0% 50%);
}

/* Custom fonts */
@font-face {
  font-family: "Wotfard";
  src: url("https://sandpack-bundler.vercel.app/fonts/wotfard/wotfard-semibold-webfont.woff2")
    format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: fallback;
}

@font-face {
  font-family: "Wotfard";
  src: url("https://sandpack-bundler.vercel.app/fonts/wotfard/wotfard-medium-webfont.woff2")
    format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: fallback;
}

@font-face {
  font-family: "Wotfard";
  src: url("https://sandpack-bundler.vercel.app/fonts/wotfard/wotfard-regular-webfont.woff2")
    format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: fallback;
}

:root {
  --font-family: "Wotfard", sans-serif;
}

body {
  background: hsl(210deg 30% 90%);
  padding: 16px;
}
main {
  background:...

JavaScript

const EMOJI_RANGE = 5;
const EMOJI_WIDTH_EM = 1.5;
const MIN_GAP_EM = 0.3;
const MAX_GAP_EM = 1;

const space = document.querySelector('.emojiSpace');

const width = space.getBoundingClientRect().width;
const em = parseFloat(getComputedStyle(space).fontSize)
var sections_qty = Math.floor(width / (em * (EMOJI_WIDTH_EM + MIN_GAP_EM)));
var gap = width / sections_qty - em * EMOJI_WIDTH_EM;

if (gap / em > MAX_GAP_EM) sections_qty++;

var shiftPercent = (100 / sections_qty).toFixed(2, 10);

_.range(sections_qty + 1).forEach((__, i) => {
  const isOdd = i % 2;
  const emoji = document.createElement('span');
  emoji.classList.add('emoji');
  emoji.ariaHidden = true;

  emoji.style.setProperty('--left', i * shiftPercent + '%');
  emoji.style.setProperty('--emoji-i', _.random(0, 4));
  const fallDuration = isOdd ? _.random(1.5, 2) : _.random(0.9, 1.4);
  emoji.style.setProperty('--fall-duration', fallDuration.toFixed(1, 10) + 's');

  space.appendChild(emoji);
});