repos

isaacbythewood.com-nextjs

mirror archived upstream

Animation-heavy personal portfolio on Next.js: a custom cursor, a page-transition loader, and canvas backgrounds.

canvas-animationscss-modulesdark-themehandcodednextjspersonal-websiteportfolioreact

3.8 KB · 242 lines · CSS Raw History
  1@keyframes fadeStart {
  2  from {
  3    opacity: 0;
  4  }
  5  to {
  6    opacity: 1;
  7  }
  8}
  9
 10@keyframes slideUp {
 11  from {
 12    opacity: 0;
 13    transform: translateY(30px);
 14  }
 15  to {
 16    opacity: 1;
 17    transform: translateY(0);
 18  }
 19}
 20
 21.imageWrapper {
 22  position: fixed;
 23  top: 0;
 24  left: 0;
 25  right: 0;
 26  bottom: 0;
 27  width: 100%;
 28  height: 100vh;
 29  z-index: 0;
 30  pointer-events: none;
 31}
 32
 33.words {
 34  position: fixed;
 35  top: 0;
 36  bottom: 0;
 37  left: 0;
 38  right: 0;
 39  width: 100%;
 40  height: 100vh;
 41  display: flex;
 42  align-items: center;
 43  justify-content: center;
 44  z-index: 10;
 45  mix-blend-mode: darken;
 46  background: rgba(0, 0, 0, 0.8);
 47}
 48
 49.word {
 50  opacity: 0.2;
 51  font-size: 11vw;
 52  text-transform: uppercase;
 53  margin: 0;
 54  position: absolute;
 55}
 56
 57.wordAppear,
 58.wordEnter {
 59  opacity: 0;
 60  transform: translateY(-200px);
 61}
 62
 63.wordAppearActive,
 64.wordEnterActive {
 65  opacity: 0.2;
 66  transform: translateY(0);
 67  transition-duration: 1000ms;
 68  transition-property: opacity, transform;
 69}
 70
 71.wordAppearDone,
 72.wordEnterDone {
 73  opacity: 0.2;
 74}
 75
 76.wordExit {
 77  transform: translateY(0);
 78  opacity: 0.2;
 79}
 80
 81.wordExitActive {
 82  opacity: 0;
 83  transform: translateY(200px);
 84  transition-duration: 1000ms;
 85  transition-property: opacity, transform;
 86}
 87
 88.hero {
 89  position: relative;
 90  z-index: 20;
 91  opacity: 0;
 92  animation-name: fadeStart;
 93  animation-duration: 1500ms;
 94  animation-fill-mode: forwards;
 95  animation-play-state: paused;
 96}
 97
 98.hero::before {
 99  content: "";
100  display: block;
101  width: 60px;
102  height: 4px;
103  margin-bottom: 24px;
104  background-image: linear-gradient(
105    to right,
106    var(--color-blue) 0,
107    var(--color-purple) 100%
108  );
109}
110
111.name {
112  margin: 0 0 16px 0;
113  line-height: 0.9;
114  overflow: visible;
115}
116
117.firstName {
118  display: block;
119  font-size: clamp(2.8em, 6.5vw, 5em);
120  font-weight: 800;
121  text-transform: uppercase;
122  letter-spacing: -0.02em;
123}
124
125.lastName {
126  display: block;
127  font-size: clamp(2.8em, 6.5vw, 5em);
128  font-weight: 800;
129  text-transform: uppercase;
130  letter-spacing: -0.02em;
131  background-image: linear-gradient(
132    to right,
133    var(--color-blue) 0,
134    var(--color-purple) 100%
135  );
136  -webkit-background-clip: text;
137  background-clip: text;
138  -webkit-text-fill-color: transparent;
139  filter: drop-shadow(0 0 20px rgba(0, 0, 0, 0.8));
140}
141
142.role {
143  display: flex;
144  align-items: baseline;
145  gap: 10px;
146  font-family: monospace;
147  font-size: 1.5em;
148  letter-spacing: 2px;
149  text-transform: uppercase;
150}
151
152.roleTitle {
153  color: white;
154  font-weight: 700;
155}
156
157.roleAt {
158  color: rgba(255, 255, 255, 0.4);
159  font-weight: 400;
160}
161
162.roleCompany {
163  color: rgba(255, 255, 255, 0.6);
164  font-weight: 400;
165}
166
167.notice {
168  display: block;
169  margin-top: 32px;
170  padding: 16px 20px;
171  border-left: 3px solid var(--color-purple);
172  background: rgba(0, 0, 0, 0.5);
173  text-decoration: none;
174  transition: background 250ms ease, border-color 250ms ease;
175  max-width: 420px;
176}
177
178.notice:hover {
179  background: rgba(0, 0, 0, 0.65);
180  border-color: var(--color-blue);
181}
182
183.noticeLabel {
184  display: inline-block;
185  font-family: monospace;
186  font-size: 0.85em;
187  font-weight: 700;
188  text-transform: uppercase;
189  letter-spacing: 3px;
190  color: rgba(255, 255, 255, 0.6);
191  margin-bottom: 6px;
192}
193
194.noticeTitle {
195  display: block;
196  font-size: 1.3em;
197  font-weight: 800;
198  text-transform: uppercase;
199  letter-spacing: 1px;
200  color: white;
201  margin-bottom: 4px;
202}
203
204.noticeDesc {
205  display: block;
206  font-size: 0.85em;
207  line-height: 1.5;
208  color: rgba(255, 255, 255, 0.7);
209  font-style: italic;
210}
211
212@media (max-width: 767.98px) {
213  .firstName,
214  .lastName {
215    font-size: 10vw;
216  }
217
218  .role {
219    flex-direction: column;
220    gap: 2px;
221    font-size: 0.85em;
222  }
223
224  .notice {
225    margin-top: 20px;
226    padding: 10px 14px;
227  }
228
229  .noticeLabel {
230    font-size: 0.6em;
231    letter-spacing: 2px;
232  }
233
234  .noticeTitle {
235    font-size: 0.9em;
236  }
237
238  .noticeDesc {
239    font-size: 0.75em;
240  }
241}