비전공자 개발일기

Notification Bell 본문

Javascript

Notification Bell

HiroDaegu 2022. 7. 27. 00:36
728x90
SMALL

 

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>NOTIFICATION BELL</title>
  <link rel="stylesheet" href="style.css">
  <script defer src="main.js"></script>
</head>
<body>
  <button id="notifications" class="notifications notifications--active" type="button">  
    <span class="notifications__waves"></span>  
    <span class="notifications__waves"></span>  
    <span class="notifications__waves"></span>  
    <span class="notifications__waves"></span>  
    <span class="notifications__sr">Notifications</span>  
    <span class="notifications__badge" data-badge>1</span>  
  </button>  
</body>
</html>
* {  
  border: 0;  
  box-sizing: border-box;  
  margin: 0;  
  padding: 0;  
}  
:root {  
  --hue: 223;  
  --bg: hsl(var(--hue),10%,90%);  
  --fg: hsl(var(--hue),10%,10%);  
  font-size: calc(40px + (60 - 40) * (100vw - 320px) / (1280 - 320));  
}  
body, button {  
  color: var(--fg);  
  font: 1em/1.5 "DM Sans", sans-serif;       
}  
body {  
  background: var(--bg);  
  height: 100vh;  
  display: grid;  
  place-items: center;  
}  
.notifications {  
  background: transparent;  
  box-shadow: 0 0 0 0.1em transparent;  
  filter: brightness(1) grayscale(1);  
  position: relative;  
  width: 1.5em;  
  height: 1.5em;  
  transition: filter 0.15s 0.3s linear;  
  -webkit-appearance: none;  
  appearance: none;  
  -webkit-tap-highlight-color: transparent;  
}  
.notifications:focus {  
  outline: none;  
}  
.notifications:before,  
.notifications:after,  
.notifications__badge,  
.notifications__waves,  
.notifications__sr {  
  position: absolute;  
}  
.notifications:before,  
.notifications:after {  
  content: "";  
  display: block;  
}  
.notifications:before {  
  background: radial-gradient(0.4em 0.4em at 50% 1.1em,hsl(38,90%,55%) 47%,hsla(38,90%,55%,0) 50%);  
  top: 0.2em;  
  left: calc(50% - 0.2em);  
  width: 0.4em;  
  height: 1.3em;  
  transform-origin: 50% 0.2em;  
}  
.notifications:after {  
  background:  
       /* rim */  
       radial-gradient(0.4em 0.2em at 0.2em 1.2em,hsl(45,90%,55%) 46%,hsla(45,90%,55%,0) 50%),  
       linear-gradient(hsl(45,90%,55%),hsl(45,90%,55%)) 0.2em 1.1em / 1.1em 0.2em no-repeat,  



       radial-gradient(0.4em 0.2em at 1.3em 1.2em,hsl(45,90%,55%) 46%,hsla(45,90%,55%,0) 50%),  
       /* middle */  
       radial-gradient(1.2em 1.2em at 50% 0.75em,hsl(38,90%,55%) 49%,hsla(38,90%,55%,0) 50%) 0 0 / 100% 75% no-repeat,  
       linear-gradient(hsl(38,90%,55%),hsl(38,90%,55%)) 0.15em 0.75em / 1.2em 0.4em no-repeat,  
       /* top */  
       radial-gradient(0.3em 0.3em at 50% 0.15em,hsl(45,90%,55%) 48%,hsla(45,90%,55%,0) 50%);  
  top: 0;  
  left: 0;  
  width: 100%;  
  height: 100%;  
  transform-origin: 50% 0.15em;  
}  
.notifications__badge {  
  background: hsl(3,90%,55%);  
  border-radius: 0.375rem;  
  color: hsl(0,0%,100%);  
  font-size: 0.5em;  
  font-weight: bold;  
  padding: 0 0.125rem;  
  top: -0.125rem;  
  right: -0.125rem;  
  min-width: 0.75rem;  
  height: 0.75rem;  
  text-align: center;  
  transition: transform 0.3s 0.15s ease-out;  
  z-index: 1;  
}  
.notifications__badge:empty {  
  transform: scale(0);  
  transition-delay: 0s;  
}  
.notifications__waves,  
.notifications--active:before,  
.notifications--active:after {  
  animation-duration: 2s;  
  animation-timing-function: linear;  
  animation-iteration-count: infinite;  
}  
.notifications__waves {  
  animation-delay: 0.6s;  
  border-top: 0.1em solid transparent;  
  border-right: 0.1em solid hsla(var(--hue),10%,50%);  
  border-bottom: 0.1em solid transparent;  
  border-left: 0.1em solid hsla(var(--hue),10%,50%);  
  border-radius: 50%;  
  top: -50%;  
  left: -50%;  
  opacity: 0;  
  pointer-events: none;  
  width: 200%;  
  height: 200%;  
  transform: scale(0.3);  
}  
.notifications__waves:nth-child(2) { animation-delay: 0.75s; }  
.notifications__waves:nth-child(3) { animation-delay: 0.9s; }  



.notifications__waves:nth-child(4) { animation-delay: 1.05s; }  
.notifications--active {  
  filter: brightness(1) grayscale(0);  
  transition-delay: 0s;  
}  
.notifications--active:before,  
.notifications--active:after {  
  animation-delay: 0.3s;  
}  
.notifications--active:before {animation-name: ringBefore; }  
.notifications--active:after {animation-name: ringAfter; }  
.notifications--active .notifications__waves {animation-name: waves; }  
.notifications__sr {  
  clip: rect(1px,1px,1px,1px);  
  overflow: hidden;  
  width: 1px;  
  height: 1px;  
}  
/* Dark theme */  
@media (prefers-color-scheme: dark) {  
  :root {  
       --bg: hsl(var(--hue),10%,10%);  
       --fg: hsl(var(--hue),10%,90%);  
  }  
}  
/* Animations */  
@keyframes ringBefore {  
  from { transform: rotate(0); }  
  15% { transform: rotate(-3deg); }  
  20% { transform: rotate(6deg); }  
  25% { transform: rotate(-6deg); }  
  30% { transform: rotate(18deg); }  
  35% { transform: rotate(-18deg); }  
  40% { transform: rotate(22deg); }  
  45% { transform: rotate(-20deg); }  
  50% { transform: rotate(18deg); }  
  55% { transform: rotate(-16deg); }  
  60% { transform: rotate(14deg); }  
  65% { transform: rotate(-12deg); }  
  70% { transform: rotate(10deg); }  
  75% { transform: rotate(-8deg); }  
  80% { transform: rotate(6deg); }  
  85% { transform: rotate(-4deg); }  
  90% { transform: rotate(2deg); }  
  95% { transform: rotate(-1deg); }  
}  
@keyframes ringAfter {  
  from,  
  40%,  
  to {  
       transform: rotate(0);  
  }  
  5%,  
  35% {  
       transform: rotate(10deg);  
  }  
  10%,  
  30% {  
       transform: rotate(-10deg);  
  }  
  15%,  
  25% {  
       transform: rotate(20deg);  
  }  
  20% {  
       transform: rotate(-20deg);  
  }  
}  
@keyframes waves {  
  from {  
       opacity: 1;  
       transform: scale(0.3);  
  }  
  20%,  
  to {  
       opacity: 0;  
       transform: scale(1);  
  }  
}
window.addEventListener("DOMContentLoaded",() => {  
  const n = new Notifications("#notifications");       
});  
class Notifications {  
  constructor(qs) {  
       this.el = document.querySelector(qs);  
       this.badge = null;  
       this.items = 0;  
       this.timeout = null;  
       this.init();  
  }  
  init() {  
       if (this.el) {  
            this.el.addEventListener("click",this.read.bind(this));  
            this.badge = this.el.querySelector("[data-badge]");  
            this.reset(1);  
       }  
  }  
  read() {  
       if (this.items > 0) {  
            this.items = 0;  
            this.el.classList.remove("notifications--active");  
            this.badge.innerHTML = "";  
            const items = this.random(1,10,true);  
            clearTimeout(this.timeout);  
            this.timeout = setTimeout(this.reset.bind(this,items),2e3);  
       }  
  }  
  reset(items) {  
       this.items = items;  
       if (this.items > 0) {  
            this.el.classList.add("notifications--active");  
            this.badge.innerHTML = this.items;  
       }  
  }  
  random(min,max,round = false) {  
       const percent = crypto.getRandomValues(new Uint32Array(1))[0] / 2**32;  
       const relativeValue = (max - min) * percent;  
       return min + (round === true ? Math.round(relativeValue) : +relativeValue.toFixed(2));  
  }  
}
728x90
LIST

'Javascript' 카테고리의 다른 글

Search Filter  (0) 2022.08.02
ColorFul Rain  (0) 2022.07.31
Tic Tae Toc  (0) 2022.07.09
Chatbot  (0) 2022.07.08
QR code Generator  (0) 2022.07.07