250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 백엔드
- react
- button
- jQuery
- ipad
- hover
- iOS 개발자
- html5
- IOS
- HTML
- 자바스크립트
- image
- 비전공자
- SWIFT
- CSS
- css3
- iPhone
- front-end
- xcode
- 프론트엔드
- MAC
- 풀스택
- effect
- 개발자
- keyframes
- Animation
- php
- javascript
- 애니메이션
- 비전공 개발자
Archives
- Today
- Total
비전공자 개발일기
Notification Bell 본문
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 |