CSS&JS/👀Study and Copy

[CSS] 아쿠아 버튼(copy)

arancia_ 2023. 1. 10. 17:25

원본 : https://codepen.io/simeydotme/pen/MWXxKrP

 

Aqua Button (pure css)

Using Gradients, Variables and Filters / Blending to create a really convincing Aqua button as seen on Twitter...

codepen.io

색감과 효과가 너무 이쁘다...

HTML

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="en">
<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>Aqua Button</title>
    <link rel="stylesheet" href="./style.css">
    <script src="./main.js" type="module"></script>
</head>
<body>
    <a href="https://codepen.io/simeydotme/pen/MWXxKrP" target="blank">
        Aqua Button (pure css) by Simon Goellner
    </a>
 
    <main id="app">
        <!-- 아쿠아 버튼 -->
        <button class="btn-aqua">
            <span class="btn-aqua-txt">Aqua Button</span>
        </button>
 
        <!-- 조절 -->
        <fieldset id="custom">
            <!-- 리셋/랜덤 -->
            <button id="reset">reset</button>
            <button id="random">random</button>
            <!-- 커스텀 -->
            <label>
                <span>흐리게(blur)</span>
                <input id="blur" data-unit="px" type="range" min=0 max=10 step=0.2 value=0>
            </label>
            <label>
                <span>hue1</span>
                <input id="hue1" data-unit="deg" type="range" min=0 max=360 value=190>
            </label>
            <label>
                <span>hue2</span>
                <input id="hue2" data-unit="deg" type="range" min=0 max=360 value=250>
            </label>
            <label>
                <span>sat1</span>
                <input id="sat1" data-unit="%" type="range" min=0 max=100 value=50>
            </label>
            <label>
                <span>sat2</span>
                <input id="sat2" data-unit="%" type="range" min=0 max=100 value=60>
            </label>
            <label>
                <span>gradGap</span>
                <input id="gradgap" data-unit="%" type="range" orient="vertical" min="10" max="40" value=30>
            </label>
            <label>
                <span>gradOff</span>
                <input id="gradoffset"data-unit="%"  type="range" orient="vertical" min="20" max="120" value=45>
            </label>
        </fieldset>
    </main>
</body>
</html>
cs

CSS

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
@charset "utf-8";
:root{
    --black:#3b3d4c;
    --blur: 0px;
    --hue1: 190deg;
    --hue2: calc(var(--hue1) + 60deg);
    --sat1: 50%;
    --sat2: calc(var(--sat1) + 10%);
    --gradgap: 30%;
    --gradoffset: 45%;
    --clr1: hsl(var(--hue1), var(--sat1), 90%);
    --clr2: hsl(var(--hue2), var(--sat2), 85%);
    --text: hsla(var(--hue1), 70%, 10%, .9);
    --font: "Noto Sans", sans-serif;
}
*{margin:0;padding:0;box-sizing:border-box;}
html,body{
    background:var(--black);
    font-family:var(--font);
    color:#fff;
}
 
#app{
    --gap:5vmin;
    display:flex; flex-flow:column nowrap;
    justify-content:flex-end; align-items:center;
    gap:var(--gap);
    position:relative; overflow:hidden;
    width:90%;
    margin:10vmin auto; padding-top:var(--gap);
    background-color:hsl(var(--hue1), 20%, 95%);
    background-image: linear-gradient(33deg, transparent 60%, var(--clr1)), linear-gradient(210deg, transparent 60%, var(--clr2));
    background-size: 150%;
    background-position: center;
    border-radius:10px;
    box-shadow: rgba(0, 0, 0, 0.15) 0px 15px 25px, rgba(0, 0, 0, 0.05) 0px 5px 10px;
}
 
/* 📌[아쿠아 버튼] */
.btn-aqua{
    position:relative;
    padding: 1.1em 1.5em;
    background-color: var(--clr1);
    background-image: linear-gradient(180deg, var(--clr2) var(--gradgap), transparent calc(100% - var(--gradgap)));
    background-repeat: no-repeat;
    background-position: center var(--gradoffset);
    background-size: 100% 200%;
    border: none; border-radius: 2em;
    letter-spacing: -0.025em;
    font-size:6vmin;font-weight: 500; color:var(--black);
    box-shadow: 0 -0.5em 0.5em transparent, 0 0.5em 0.5em transparent, 0 0.25em 0.3em -0.2em hsla(var(--hue1), var(--sat1), 50%, 0.46), 0 0.25em 0.75em hsla(var(--hue1), calc(var(--sat1) - 10%), 40%, 0.3);
    transition: all 0.5s ease;
    cursor:pointer;
}
 
.btn-aqua::before,
.btn-aqua::after{
    content: "";
    inset: 0;
    position: absolute;
    border-radius: 5em;
}
 
.btn-aqua::before {
    background-image: radial-gradient(ellipse, hsla(var(--hue1), 100%, 90%, 0.8) 20%, transparent 50%, transparent 200%), linear-gradient(90deg, #404040 -10%, transparent 30%, transparent 70%, #404040 110%);
    background-repeat: no-repeat;
    background-position: center 220%;
    background-size: 200% 80%, cover;
    box-shadow: inset 0 0.25em 0.75em rgba(0, 0, 0, 0.8), inset 0 -0.05em 0.2em rgba(255, 255, 255, 0.4), inset 0 -1px 3px hsla(var(--hue1), 80%, 50%, 0.75);
    background-blend-mode: overlay;
    mix-blend-mode: overlay;
    filter: blur(calc(var(--blur) * 0.5));
}
 
.btn-aqua::after {
    top: 0.075em;
    left: 0.75em;
    right: 0.75em;
    bottom: 1.4em;
    background: linear-gradient(180deg, hsla(var(--hue2), 100%, 90%, 0.9), hsla(var(--hue2), 70%, 50%, 1) 40%, transparent 80%);
    filter: blur(var(--blur));
    mix-blend-mode: screen;
}
 
 
 
/* 📌[form] */
#custom{
    display:flex;flex-flow:row wrap;
    justify-content:center; align-items:center;
    gap:20px;
    position:relative;
    width:100%;
    padding:4vmin 5vmin;
    background:rgba(0,0,0,.3);
    border:none;
}
 
input[type="range"]{
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
 
    accent-color: var(--clr1);
    height: calc(1em + 2px * 2);
    padding: 0 5px;
    background: var(--black);
    border: none;
    border-radius: 1em;
    font-family: inherit;
    color: white;
    box-shadow: 0 3px 2px -3px var(--clr1);
    transition: border 0.3s ease-in, outline 0.6s ease-in, box-shadow 0.6s ease-in;
}
 
#reset,
#random{
    text-transform:uppercase;
    padding:.5em 2em; font-size:20px;}
cs

JS

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class AquaButtonCtrl{
    constructor(){
        this.$aqua = document.getElementsByClassName('btn-aqua')[0];
        this.$reset = document.getElementById('reset');
        this.$random = document.getElementById('random');
        this.$custom = document.getElementById('custom');
        this.default = Object.freeze({
            blur : {val:0, unit:"px"},
            hue1 : {val:190, unit:"deg"}, 
            hue2 : {val:250, unit:"deg"},
            sat1 : {val:50, unit:"%"}, 
            sat2 : {val:60, unit:"%"},
            gradgap : {val:30, unit:"%"}, 
            gradoffset : {val:45, unit:"%"}
        });
        this.init();
    }//constructor
 
    /** 아쿠아버튼 조절 가능 시작 */
    init(){
        //리셋 이벤트 추가
        this.$reset.addEventListener('click'this.reset);
 
        //랜덤 이벤트 추가
        this.$random.addEventListener('click'this.random);
 
        //인풋값 변화 이벤트 추가
        this.$custom.addEventListener('change'this.change);
    }//init
 
    /** 디폴트 값 으로 리셋 */
    reset = () =>{
        for(const key in this.default){
            const {val,unit} = this.default[key];
            document.documentElement.style.setProperty(`--${key}`, `${val}${unit}`);
        }
    }//reset
 
    /** 랜덤하게 바꿈 */
    random = () => {
        for(const key in this.default){
            const $range = document.getElementById(key);
            const {unit} = this.default[key];
            let val;
            switch(key){
                case "hue1" :
                case "sat1" :{
                    val = Math.floor(Math.random() * 360);
                }break;
                case "hue2" :
                case "sat2" :{
                    val = Math.floor(Math.random() * 70+ 15;
                }break;
 
                case "gradgap" : {
                    val = Math.floor(Math.random() * 10+ 20;
                }break;
                case "gradoffset" : {
                    val = Math.floor(Math.random() * 20+ 40;
                }break;
            }
            document.documentElement.style.setProperty(`--${key}`, `${val}${unit}`);
            $range.value = val;
        }//for
    }//random
 
    /** 컨트롤 변경시 */
    change = (e) =>{
        if(e.target.tagName != "INPUT"return;
        const $range = e.target;
        const key = $range.id;
        const unit = $range.dataset.unit;
        const val = $range.value;
        document.documentElement.style.setProperty(`--${key}`, `${val}${unit}`);
    }//change
}//class-AquaButton
 
/* ======================================================== */
new AquaButtonCtrl();
cs