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

5.6 KB · 365 lines · CSS Raw History
  1@keyframes transformRight {
  2  from {
  3    transform: scaleX(0);
  4  }
  5  to {
  6    transform: scaleX(1);
  7  }
  8}
  9
 10@keyframes transformLeft {
 11  from {
 12    transform: scaleX(1);
 13  }
 14  to {
 15    transform: scaleX(0);
 16  }
 17}
 18
 19@keyframes slideUp {
 20  from {
 21    opacity: 0;
 22    transform: translateX(-100vw);
 23  }
 24  to {
 25    opacity: 1;
 26    transform: translateX(0);
 27  }
 28}
 29
 30.background {
 31  position: fixed;
 32  top: 0;
 33  left: 0;
 34  right: 0;
 35  bottom: 0;
 36  background-color: white;
 37  z-index: -2;
 38}
 39
 40.grid {
 41  display: grid;
 42  grid-template-columns: 50vw 1fr;
 43  grid-template-rows: auto;
 44  grid-template-areas: "left right";
 45  margin-left: 60px;
 46  width: calc(100vw - 60px);
 47  transform: translateX(-100vw);
 48  animation: slideUp 750ms 500ms forwards;
 49}
 50
 51@media (max-width: 1023.98px) {
 52  .grid {
 53    margin-left: 0;
 54    width: 100%;
 55    grid-template-columns: 1fr;
 56    grid-template-rows: auto auto;
 57    grid-template-areas:
 58      "left"
 59      "right";
 60    margin-top: 60px;
 61  }
 62}
 63
 64.gridLeft {
 65  grid-area: left;
 66  background-color: rgba(0, 0, 0, 0.9);
 67  min-height: 100vh;
 68  display: flex;
 69  align-items: center;
 70}
 71
 72@media (max-width: 1023.98px) {
 73  .gridLeft {
 74    grid-column: 1;
 75    grid-row: 1;
 76    min-height: auto;
 77    align-items: flex-start;
 78  }
 79}
 80
 81.gridRight {
 82  grid-area: right;
 83  height: 100vh;
 84  width: 100%;
 85  display: flex;
 86  align-items: flex-end;
 87  overflow-y: auto;
 88  background-color: white;
 89}
 90
 91@media (max-width: 1023.98px) {
 92  .gridRight {
 93    grid-column: 1;
 94    grid-row: 2;
 95    height: auto;
 96    min-height: 50vh;
 97    overflow-y: visible;
 98    align-items: flex-start;
 99    padding-top: 20px;
100    padding-bottom: 30px;
101  }
102}
103
104.contactWrapper {
105  padding-left: 60px;
106}
107
108@media (max-width: 1023.98px) {
109  .contactWrapper {
110    min-height: auto;
111    padding: 10px 20px 30px;
112  }
113}
114
115.heading {
116  font-size: 3em;
117  margin-top: 10px;
118  margin-bottom: 20px;
119}
120
121.heading::before {
122  content: "";
123  display: block;
124  width: 60px;
125  height: 4px;
126  margin-bottom: 10px;
127  background-image: linear-gradient(
128    to right,
129    var(--color-blue) 0,
130    var(--color-purple) 100%
131  );
132}
133
134@media (max-width: 767.98px) {
135  .heading {
136    margin-top: 0;
137    margin-bottom: 10px;
138  }
139}
140
141.shoutOut {
142  text-transform: uppercase;
143  padding: 5px;
144  margin: 0 0 2px 0;
145  float: left;
146  clear: left;
147  font-size: 1.4em;
148  background-image: linear-gradient(
149    to right,
150    var(--color-blue) 0,
151    var(--color-purple) 100%
152  );
153}
154
155@media (max-width: 767.98px) {
156  .shoutOut {
157    font-size: 1.1em;
158  }
159}
160
161.contactList {
162  padding-top: 30px;
163  clear: both;
164}
165
166.contactKey {
167  text-transform: uppercase;
168  font-size: 0.75em;
169  font-weight: 700;
170  color: rgba(255, 255, 255, 0.4);
171  letter-spacing: 2px;
172  font-family: monospace;
173}
174
175.contactValue {
176  font-size: 1.5em;
177  margin-left: 0;
178  margin-bottom: 30px;
179}
180
181.contactLink {
182  color: white;
183  text-decoration: none;
184  position: relative;
185}
186
187.contactLink::before {
188  content: "";
189  position: absolute;
190  left: 0;
191  right: 0;
192  bottom: 0;
193  height: 2px;
194  background: rgba(255, 255, 255, 1);
195  transform-origin: left;
196  animation: transformLeft 300ms normal forwards;
197}
198
199.contactLink::after {
200  content: "";
201  position: absolute;
202  left: 0;
203  right: 0;
204  bottom: 0;
205  height: 2px;
206  background: rgba(255, 255, 255, 0.2);
207}
208
209.contactLink:hover::before {
210  animation: transformRight 300ms normal forwards;
211}
212
213.chat {
214  display: flex;
215  flex-direction: column;
216  justify-content: flex-end;
217  padding: 30px;
218  width: 100%;
219  min-height: 100%;
220}
221
222@media (max-width: 1023.98px) {
223  .chat {
224    justify-content: flex-start;
225  }
226}
227
228.chatLine {
229  display: flex;
230  margin-bottom: 12px;
231  align-items: flex-start;
232}
233
234.chatLineUser {
235  justify-content: flex-end;
236}
237
238.chatBubble {
239  font-size: 1.1em;
240  padding: 12px 18px;
241  background: rgba(0, 0, 0, 0.06);
242  border-radius: var(--radius-2);
243  color: black;
244  max-width: 75%;
245  line-height: 1.5;
246}
247
248@media (max-width: 767.98px) {
249  .chatBubble {
250    font-size: 1em;
251  }
252}
253
254.chatBubble span {
255  display: block;
256  font-size: 0.65em;
257  text-transform: uppercase;
258  margin-top: 8px;
259  color: var(--color-blue);
260  letter-spacing: 2px;
261  font-weight: 700;
262  font-family: monospace;
263}
264
265.chatAvatar {
266  margin-right: 16px;
267  width: 40px;
268  height: 40px;
269  display: inline-flex;
270  flex-shrink: 0;
271}
272
273@media (max-width: 767.98px) {
274  .chatAvatar {
275    margin-right: 10px;
276    width: 36px;
277    height: 36px;
278  }
279}
280
281.chatBubbleUser {
282  background-image: linear-gradient(
283    to right,
284    var(--color-blue) 0,
285    var(--color-purple) 100%
286  );
287  color: white;
288}
289
290.chatBubbleUser span {
291  display: none;
292}
293
294.chatOptions {
295  display: flex;
296  flex-wrap: wrap;
297  gap: 8px;
298  margin-top: 4px;
299  margin-bottom: 12px;
300  padding-left: 56px;
301}
302
303@media (max-width: 767.98px) {
304  .chatOptions {
305    padding-left: 0;
306  }
307}
308
309.chatOption {
310  padding: 8px 16px;
311  font-size: 0.9em;
312  font-weight: 600;
313  background: none;
314  border: 1px solid rgba(0, 0, 0, 0.2);
315  border-radius: var(--radius-2);
316  color: black;
317  cursor: none;
318  transition: border-color 200ms, background 200ms;
319  font-family: inherit;
320}
321
322.chatOption:hover {
323  border-color: var(--color-blue);
324  background: rgba(14, 63, 244, 0.05);
325}
326
327@keyframes dotPulse {
328  0%, 80%, 100% {
329    opacity: 0.3;
330  }
331  40% {
332    opacity: 1;
333  }
334}
335
336.typingDots {
337  display: inline-flex;
338  gap: 4px;
339  align-items: center;
340}
341
342.typingDots span {
343  display: inline-block;
344  width: 6px;
345  height: 6px;
346  background: rgba(0, 0, 0, 0.4);
347  border-radius: 50%;
348  animation: dotPulse 1.4s infinite;
349  margin-top: 0;
350  font-size: inherit;
351  letter-spacing: normal;
352  text-transform: none;
353  font-weight: normal;
354  font-family: inherit;
355  color: transparent;
356}
357
358.typingDots span:nth-child(2) {
359  animation-delay: 0.2s;
360}
361
362.typingDots span:nth-child(3) {
363  animation-delay: 0.4s;
364}