Animation-heavy personal portfolio on Next.js: a custom cursor, a page-transition loader, and canvas backgrounds.
canvas-animationscss-modulesdark-themehandcodednextjspersonal-websiteportfolioreact
1.hamburger {
2 position: fixed;
3 top: 30px;
4 right: 0;
5 padding: 20px 15px;
6 background: white;
7 z-index: 5001;
8 border: none;
9}
10
11.hamburger:hover * {
12 width: 30px !important;
13}
14
15@media (max-width: 1023.98px) {
16 .hamburger {
17 top: 0;
18 padding-bottom: 21px;
19 }
20}
21
22.patty {
23 background: black;
24 width: 30px;
25 height: 3px;
26 margin-bottom: 5px;
27 margin-left: auto;
28 transition: width 250ms;
29}
30
31.patty:last-child {
32 margin-bottom: 0;
33}
34
35.overlay {
36 position: fixed;
37 top: 0;
38 right: 0;
39 bottom: 0;
40 left: 0;
41 z-index: -5000;
42 background: transparent;
43}
44
45.overlay:global(.menu-enter),
46.overlay:global(.menu-enter-active),
47.overlay:global(.menu-enter-done),
48.overlay:global(.menu-exit),
49.overlay:global(.menu-exit-active) {
50 z-index: 5000;
51}
52
53.overlay:global(.menu-exit-done) {
54 z-index: -5000;
55}
56
57.overlayGrid {
58 display: grid;
59 grid-template-columns: 60% 40%;
60}
61
62@media (max-width: 767.98px) {
63 .overlayGrid {
64 grid-template-columns: 100%;
65 }
66}
67
68.overlayGridLeft {
69 grid-area: 1/1;
70 display: flex;
71 flex-direction: column;
72 justify-content: center;
73 align-items: center;
74 background: white;
75 transition: transform 500ms;
76 transform: translateX(-100%);
77}
78
79.overlayGridLeft:global(.menu-enter),
80.overlayGridLeft:global(.menu-enter-active),
81.overlayGridLeft:global(.menu-enter-done) {
82 transform: translateX(0);
83}
84
85.overlayGridLeft:global(.menu-exit),
86.overlayGridLeft:global(.menu-exit-active),
87.overlayGridLeft:global(.menu-exit-done) {
88 transform: translateX(-100%);
89}
90
91.overlayGridRight {
92 grid-area: 1/2;
93 position: relative;
94 width: 100%;
95 height: 100vh;
96 overflow: hidden;
97 transition: transform 500ms;
98 transform: translateX(100%);
99}
100
101.overlayGridRight:global(.menu-enter),
102.overlayGridRight:global(.menu-enter-active),
103.overlayGridRight:global(.menu-enter-done) {
104 transform: translateX(0);
105}
106
107.overlayGridRight:global(.menu-exit),
108.overlayGridRight:global(.menu-exit-active),
109.overlayGridRight:global(.menu-exit-done) {
110 transform: translateX(100%);
111}
112
113.overlayGridRight img {
114 object-fit: cover;
115 height: 100vh;
116}
117
118.overlayLink {
119 font-weight: 900;
120 text-decoration: none;
121 margin-bottom: 10px;
122 font-size: 3em;
123 color: black;
124 position: relative;
125}
126
127.overlayLink:last-child {
128 margin-bottom: 0;
129}
130
131.overlayLink::before {
132 content: attr(data-text);
133 color: white;
134 position: absolute;
135 width: 0;
136 left: 0;
137 bottom: 3px;
138 height: 27px;
139 background-color: black;
140 transition: width 200ms;
141 line-height: 0;
142 overflow: hidden;
143}
144
145.overlayLink:hover::before {
146 width: 100%;
147}
148
149.topBar {
150 display: flex;
151 width: 100%;
152 position: absolute;
153 left: 20px;
154 top: 20px;
155 align-items: center;
156 justify-content: flex-start;
157}
158
159.topLink {
160 text-decoration: none;
161 color: white;
162 background-color: rgba(0, 0, 0, 1);
163 padding: 0.25rem 0.5rem;
164 margin-left: 1rem;
165 transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
166 font-family: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
167 "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
168 "Fira Mono", "Droid Sans Mono", "Courier New", monospace;
169}
170
171.topLink:hover {
172 background-color: rgba(0, 0, 0, 0.1);
173 color: black;
174}
175
176@media (max-width: 767.98px) {
177 .topLink {
178 font-size: 0.8em;
179 margin-left: 0.5rem;
180 }
181}
182
183.bottomBar {
184 display: flex;
185 width: 100%;
186 position: absolute;
187 left: 20px;
188 bottom: 20px;
189 align-items: center;
190}
191
192.bar {
193 width: 100%;
194 height: 1px;
195 background: rgba(0, 0, 0, 0.3);
196 margin-left: 40px;
197 margin-right: 60px;
198}