Glowing Dropdown using pure HTML, CSS, JavaScript with free source code. - CodingAyush

Glowing Form Using HTML CSS & JavaScript with free source code. Get this glowing drpdown menu using html, css, JavaScript for free. become a frontend developer by doing our daily projectsget update in telegram: Join Telegram https://t.me/codingayush

Preview

HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>CodingAyush - Glowing Dropdown</title>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"
    />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <main>
      <header>
        <h3>Default:</h3>
      </header>
      <header>
        <h3>Accessible:</h3>
      </header>
      <header>
        <h3>Motion-reduced:</h3>
      </header>
      <div class="select" tabindex="0" role="button">
        <button tabindex="0">Components</button>

        <div>
          <a role="button" tabindex="0" href="#"><span>Artboards</span></a>
          <a role="button" tabindex="0" href="#"><span>Pages</span></a>
          <a role="button" tabindex="0" href="#"><span>Templates</span></a>
        </div>
      </div>
      <div
        class="select"
        tabindex="0"
        role="button"
        style="
          --a11y: 1;
          --outline-color: hsla(
            calc(var(--accent-color-hue) * 1deg) 100% 58% /
              calc(var(--a11y) * 100%)
          );
        "
      >
        <button tabindex="0">Components</button>

        <div>
          <a role="button" tabindex="0" href="#"><span>Artboards</span></a>
          <a role="button" tabindex="0" href="#"><span>Pages</span></a>
          <a role="button" tabindex="0" href="#"><span>Templates</span></a>
        </div>
      </div>

      <div class="select nomotion" tabindex="0" role="button">
        <button tabindex="0">Components</button>

        <div>
          <a role="button" tabindex="0" href="#"><span>Artboards</span></a>
          <a role="button" tabindex="0" href="#"><span>Pages</span></a>
          <a role="button" tabindex="0" href="#"><span>Templates</span></a>
        </div>
      </div>
    </main>
    <!-- partial -->
    <script src="./script.js"></script>
  </body>
</html>
CSS
@font-face {
  font-family: "Mona Sans";
  src: url("https://assets.codepen.io/64/Mona-Sans.woff2") format("woff2 supports variations"), url("https://assets.codepen.io/64/Mona-Sans.woff2") format("woff2-variations");
  font-weight: 100 1000;
}
@layer properties {
  @property --max-height {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
  }
  @property --bg-x {
    syntax: "<number>";
    inherits: true;
    initial-value: 50;
  }
  @property --bg-y {
    syntax: "<number>";
    inherits: true;
    initial-value: -200;
  }
  @property --scale {
    syntax: "<number>";
    inherits: true;
    initial-value: 1;
  }
  @property --accent-color-hue {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
  }
  @property --accent-color-hue {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
  }
  @property --item-y {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
  }
  @property --item-opacity {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
  }
  @property --accent-color {
    syntax: "<color>";
    inherits: true;
    initial-value: hsl(calc(var(--accent-color-hue)*1deg), 100%, 58%);
  }
  @property --radial-bg-color {
    syntax: "<color>";
    inherits: true;
    initial-value: black;
  }
}
:root {
  --background-color: hsl(222deg 17% 14%);
  --dark-color: hsl(227deg 37% 3%);
  --light-color: hsl(211deg 23% 51%);
  --accent-color-hue: 219;
  --accent-color: hsl(calc(var(--accent-color-hue)*1deg) 100% 58%);
  --radial-bg-color: var(--dark-color);
  --max-height: 0;
  --bg-y: -50;
  --bg-x: 200;
  --item-y: 20;
  --item-opacity: 0;
  /* Misc */
  --_inner-radius: 10;
  --_inner-padding: 6;
  --inner-radius: calc(var(--_inner-radius) * 1px);
  --inner-padding: calc(var(--_inner-padding) * 1px);
  --outer-radius: calc(calc(var(--_inner-radius) + var(--_inner-padding)) * 1px);
  --debug: 0;
  --a11y: 0;
  --outline-color: hsla(calc(var(--accent-color-hue)*1deg) 100% 58% / calc(var(--a11y)*100%));
}

*, *:before, *:after {
  box-sizing: border-box;
  outline: calc(var(--debug)*1px) dotted red;
  outline-offset: -1px;
}

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

body {
  background: var(--background-color);
  font-family: "Mona sans", sans-serif;
}

main {
  max-width: 800px;
  margin: 16em auto;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  grid-gap: 32px;
  place-items: center;
  align-items: start;
}

@media (min-width: 760px) {
  main {
    grid-template-columns: repeat(3, 1fr);
  }
}
header {
  color: white;
}
header h3 {
  letter-spacing: 0.15em;
}

div.select {
  color: white;
  background: var(--dark-color) radial-gradient(ellipse 70% 70% at calc(var(--bg-x)*1%) calc(var(--bg-y)*1%), var(--radial-bg-color) 0%, var(--dark-color) 100%);
  padding: var(--inner-padding);
  border-radius: var(--outer-radius);
  position: relative;
  width: 200px;
  z-index: 1;
  transition: background 0.3s ease, --bg-y 0.4 ease, --bg-x 0.4s ease;
  /*
  * :focus-within or :has(button:focus) */
}
div.select:hover {
  animation: glow 1.2s ease-in-out;
}
div.select:hover > button:after {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='58' height='98' fill='none'%3E%3Cpath fill='hsl(219deg 100% 58%)' d='M25.536 6c1.54-2.667 5.388-2.667 6.928 0l18.187 31.5c1.54 2.667-.385 6-3.465 6H10.814c-3.079 0-5.003-3.333-3.464-6L25.536 6ZM25.536 92c1.54 2.667 5.388 2.667 6.928 0l18.187-31.5c1.54-2.667-.385-6-3.465-6H10.814c-3.079 0-5.003 3.333-3.464 6L25.536 92Z'/%3E%3C/svg%3E") no-repeat center center/0.6em;
}
div.select:before {
  content: "";
  display: block;
  position: absolute;
  width: calc(100% - 2px);
  height: calc(100% - 2px);
  top: 1px;
  left: 1px;
  background: var(--dark-color);
  border-radius: var(--outer-radius);
  z-index: -1;
}
div.select > button {
  padding: calc(var(--inner-padding)*2) calc(var(--inner-padding)*2);
  background: var(--background-color);
  border-radius: var(--inner-radius);
  border: 0;
  color: white;
  text-align: left;
  font-size: 1em;
  width: 100%;
  cursor: pointer;
  position: relative;
  box-shadow: inset 0 2px 1px -1px rgba(255, 255, 255, 0.1);
  transform: scale(var(--scale));
  animation-duration: 0.2s;
  animation-timing-function: cubic-bezier(0.66, -0.82, 0.33, 1.73);
}
div.select > button:focus {
  outline: 1px solid var(--accent-color);
  outline-offset: -1px;
}
div.select > button:after {
  content: "";
  position: absolute;
  right: 8px;
  height: 100%;
  width: 1em;
  top: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='58' height='98' fill='none'%3E%3Cpath fill='hsl(211deg 23% 51%)' d='M25.536 6c1.54-2.667 5.388-2.667 6.928 0l18.187 31.5c1.54 2.667-.385 6-3.465 6H10.814c-3.079 0-5.003-3.333-3.464-6L25.536 6ZM25.536 92c1.54 2.667 5.388 2.667 6.928 0l18.187-31.5c1.54-2.667-.385-6-3.465-6H10.814c-3.079 0-5.003 3.333-3.464 6L25.536 92Z'/%3E%3C/svg%3E") no-repeat center center/0.6em;
}
div.select > div {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  height: 0;
  /* transition: --max-height .2s ease; ?? not working ?? */
  transition: height 0.3s ease-in-out;
}
div.select > div > a {
  display: block;
  padding: calc(var(--inner-padding)*1.6) calc(var(--inner-padding)*1.2);
  color: var(--light-color);
  cursor: pointer;
  margin-top: 8px;
  text-decoration: none;
  border-radius: var(--inner-radius);
  position: relative;
}
div.select > div > a > span {
  position: relative;
  display: block;
  transform: translateY(calc(var(--item-y)*1px));
  opacity: var(--item-opacity);
  transition: --item-y 0.2s ease 0.1s, --item-opacity 0.2s 0.1s;
}
div.select > div > a:nth-child(1) span {
  transition-delay: 0.1s;
}
div.select > div > a:nth-child(2) span {
  transition-delay: 0.15s;
}
div.select > div > a:nth-child(3) span {
  transition-delay: 0.2s;
}
div.select > div > a:focus {
  outline: 1px solid var(--outline-color);
  outline-offset: -1px;
}
div.select > div > a:hover, div.select > div > a:focus {
  color: var(--accent-color);
}
div.select:focus-within {
  outline: 1px dashed var(--outline-color);
}
div.select:hover > div, div.select:has(button:focus) > div, div.select:focus-within > div {
  height: calc(var(--max-height)*1px);
  --item-y: 0;
  --item-opacity: 1;
}

.select.nomotion {
  transition: none !important;
  animation: none !important;
}
.select.nomotion:before, .select.nomotion:after,
.select.nomotion *, .select.nomotion *:before, .select.nomotion *:after {
  transition: none !important;
  animation: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .select {
    transition: none !important;
    animation: none !important;
  }
  .select:before, .select:after,
.select *, .select *:before, .select *:after {
    transition: none !important;
    animation: none !important;
  }
}
@keyframes glow {
  from {
    --radial-bg-color: var(--accent-color);
    --bg-x: 100;
    --bg-y: 0;
  }
  50% {
    --radial-bg-color: hsl(290deg 100% 58%);
    --bg-x: 60;
    --bg-y: 120;
  }
  to {
    --radial-bg-color: var(--dark-color);
    --bg-x: 60;
    --bg-y: 120;
  }
}
@keyframes popOut {
  from {
    --scale: 1;
  }
  50% {
    --scale: 1.02;
  }
  to {
    --scale: 1;
  }
}
JS
const selects = document.querySelectorAll('.select');

window.addEventListener('DOMContentLoaded', () => {
  selects.forEach(select => {
    const button = select.querySelector('button');
    const full_height = [];
    
    [...select.querySelectorAll('div > a')].map(link => {
      const styles = window.getComputedStyle(link);
      const box = link.getBoundingClientRect();
      const margin = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom) || 0;
      const height = box.height + margin;
      full_height.push(height);

      link.addEventListener('click', () => {
        const link_text = link.textContent;
        const button_text = button.textContent;
        button.textContent = link_text;
        button.style.animationName="popOut";
        button.addEventListener("animationend", () => {
          button.style.animationName="none"
        });
        const span = document.createElement('span');
        span.textContent = button_text;
        link.innerHTML = "";
        link.appendChild(span)
        link.blur()
      })
    });
    
    const totalHeight = full_height.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
    select.dataset.totalHeight = totalHeight;
    select.style.setProperty('--max-height', totalHeight);  
  });
});

Post a Comment

Previous Post Next Post