├── images
├── codepen.GIF
├── preview.png
├── profile-pic-8.png
├── abstract-portrait.png
├── terminal-preview.jpg
├── logo-simple.svg
└── logo-text.svg
├── script.js
├── README.md
├── styles.css
└── index.html
/images/codepen.GIF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alekzandriia/neufolio/HEAD/images/codepen.GIF
--------------------------------------------------------------------------------
/images/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alekzandriia/neufolio/HEAD/images/preview.png
--------------------------------------------------------------------------------
/images/profile-pic-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alekzandriia/neufolio/HEAD/images/profile-pic-8.png
--------------------------------------------------------------------------------
/images/abstract-portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alekzandriia/neufolio/HEAD/images/abstract-portrait.png
--------------------------------------------------------------------------------
/images/terminal-preview.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alekzandriia/neufolio/HEAD/images/terminal-preview.jpg
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | function themeToggle () {
2 | const root = document.documentElement
3 | root.classList.toggle('dark')
4 | const footer = document.getElementById('logo-text')
5 | footer
6 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Portfolio Project Overview
2 |
3 | ## Purpose
4 |
5 | I created this project to flex my web development skills by coding a quick little portfolio website from scratch.
6 |
7 | The design was inspired by the neubrutlism trend I've been seeing everywhere recently-- a style that is generally characterized by solid clashing colours, black strokes, drop shadows without blur and quirky animations. (It looks a lot better than it sounds, trust me!) A really great example of neubrutalism design done well is [Gumroad's website](https://gumroad.com).
8 |
9 | > Read more about [Neubrutalism](https://uxdesign.cc/why-im-excited-about-the-neubrutalism-style-in-web-design-4ab800c2bb80)
10 |
11 | ## Colours
12 |
13 | These are the colours that I decided to go with:
14 |
15 |
16 |
17 | Since the overall colour scheme was so bright, it was very obvious (almost blindingly-so) that I needed to add dark mode functionality as well. This was as simple as adding some JavaScript that toggles the class of the root element between light and dark, and using CSS variables for the colours. Since my logo text in the footer is an SVG I was able to dynamically change the colour of the fill as well.
18 |
19 | I outlined most sections of the page with black strokes, and used a solid drop-shadow for the navigation menu.
20 |
21 | ## Animations
22 | I incorporated animation into the design by adding CSS hover animations on the logo, navigation buttons, hero photo, and the marquee areas.
23 |
24 | I decided to deviate from the standard flat style typical of neubrutalist designs by adding an animated CSS background to the hero and footer areas.
25 |
26 | ## Responsiveness
27 |
28 | [More than half](https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-web-traffic-statistics/) of web traffic comes from mobile devices these days so the portfolio needed to be designed and coded with mobile-first design principles. I achieved this by laying out the projects section using CSS grid so that I could take advantage of repeat, minmax, and autofill.
29 |
30 | ## Technologies
31 |
32 | The whole site was written by hand in VSCode using only HTML, CSS & JavaScript.
33 |
34 | ## Challenges
35 |
36 | This project took about 4 hours to make, mostly because I spent a lot of tie playing with colours and fiddling with little deciding whether to use pixels or rems in certain places. 🤪
37 |
38 | I thought that I had fully learned CSS grid prior to this, but when it came time to create a responsive grid layout for the projects section I struggled to make the layout cautomatically change the number of columns to fit the screen size. After some trial and error on my own I found this [article](https://ishadeed.com/article/css-grid-minmax/) by Ahmed, which did a great job explaining how to utilize minmax and auto-fill to achieve the result that I was looking for. I'm feeling a lot more comfortable using grid to create responsive layouts now.
39 |
40 | This was also my first time implementing a theme switcher, which I found to be very simple. However, since I decided to implement this feature after I had coded most of the website, I had to go back and switch the hard-coded colour values to custom CSS variables, which was a pain. In the future, to make my designs more flexible I'm going to default to using variables for colours.
41 |
--------------------------------------------------------------------------------
/images/logo-simple.svg:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | /* reset */
2 | * {
3 | margin:0;
4 | padding:0;
5 | box-sizing: border-box;
6 | scroll-behavior: smooth;
7 | }
8 | /* global */
9 | :root {
10 | --main-bg-color: #fef7e5;
11 | --animated-bg-color: #EEFF7D;
12 | --primary-color: #dadafe;
13 | --secondary-color: #FFA9A1;
14 | --link-color: black;
15 | --font-color:black;
16 | --body-color:#B9E4F7;
17 | }
18 |
19 | :root.dark {
20 | --main-bg-color: #aaa1c8;
21 | --primary-color: #dadafe;
22 | --secondary-color: #14213d;
23 | --animated-bg-color: rgb(27, 27, 27);
24 | --link-color: white;
25 | --font-color:#dadafe;
26 | --body-color: black;
27 | }
28 | .theme-toggle {
29 | background: transparent;
30 | padding:.5rem;
31 | border: none;
32 | font-size:3vmin;
33 | color: var(--font-color);
34 | cursor: pointer;
35 | }
36 |
37 | body {
38 | font-family: system-ui;
39 | font-size:3vmin;
40 | background: var(--body-color);
41 | width:100vw;
42 | overflow-x: hidden;
43 | }
44 | p::selection,
45 | h1::selection,
46 | h2::selection {
47 | background: var(--secondary-color);
48 | }
49 | p {
50 | line-height: 1.5;
51 | }
52 |
53 | /* header & nav */
54 | header {
55 | display:flex;
56 | padding:1rem;
57 | align-items: center;
58 | position:sticky;
59 | background: var(--animated-bg-color);
60 | top:0;
61 | border: 1px solid black;
62 | width:100vw;
63 | z-index: 1000;
64 | overflow-x: hidden;
65 | }
66 | #header-logo {
67 | margin-right: 1rem;
68 | width:18vmin;
69 | height:auto;
70 | }
71 | #logo-text {
72 | width:40vmin;
73 | fill: var(--font-color);
74 | }
75 | nav {
76 | margin-left: auto;
77 |
78 | }
79 | nav ul {
80 | display:flex;
81 | gap:.75rem;
82 | list-style: none;
83 | }
84 | nav li {
85 | background: var(--main-bg-color);
86 | padding:.5rem;
87 | border: .1rem solid;
88 | border-color: var(--font-color);
89 | border-radius: 0.5rem 0 0.5rem 0;
90 | box-shadow: .2rem .2rem;
91 | }
92 | nav a {
93 | text-decoration: none;
94 | color: var(--link-color)
95 | }
96 | nav li:hover {
97 | transform: scale(1.1);
98 | background: var(--secondary-color);
99 | }
100 | #header-logo {
101 | transition: transform 1s;
102 | border: .1rem solid black;
103 | border-radius: 50%;
104 | margin-left: 1.5rem;
105 |
106 | }
107 | #header-logo:hover {
108 | transform: rotateZ(360deg) scale(1.2);
109 | border: .2rem dotted black;
110 | }
111 |
112 | /* marquee */
113 | .marquee {
114 | overflow: hidden;
115 | padding:0.5rem;
116 | background: var(--primary-color);
117 | border: .1rem solid black;
118 | z-index: 1;
119 | }
120 | .marquee span {
121 | will-change: transform;
122 | animation: marquee 30s linear infinite;
123 | animation-delay: 2s;
124 | display: inline-block;
125 | white-space:nowrap;
126 | font-variant: small-caps;
127 | z-index: -1000;
128 | }
129 | .marquee span:hover {
130 | animation-play-state: paused;
131 | }
132 | @keyframes marquee {
133 | from {
134 | transform: translateX(0%);
135 | }
136 | to {
137 | transform: translateX(-100%);
138 | }
139 | }
140 |
141 | /*parallax sections */
142 | div.container {
143 | position:relative;
144 | overflow-x: hidden;
145 | }
146 | div.yellow {
147 | min-height:100vh;
148 | max-height: fit-content;
149 | position:sticky;
150 | top:0px;
151 | display:grid;
152 | grid-template-columns: repeat( auto-fit, minmax(20rem, 1fr));
153 | padding:4rem;
154 | align-items: center;
155 | justify-items: center;
156 | border: 1px solid black;
157 | overflow-x: hidden;
158 | }
159 | div.blue {
160 | background-color:var(--primary-color);
161 | min-height:100vh;
162 | max-height: fit-content;
163 | position:sticky;
164 | top:0px;
165 | overflow:hidden;
166 | display: flex;
167 | align-items: center;
168 | justify-content: center;
169 | border: 1px solid black;
170 | padding:2rem;
171 | overflow-x: hidden;
172 |
173 | }
174 | #projects {
175 | background:var(--secondary-color);
176 | min-height:100vh;
177 | max-height: fit-content;
178 | position:sticky;
179 | top:0px;
180 | overflow:hidden;
181 | display:grid;
182 | grid-template-columns: repeat( auto-fit, minmax(50ch, 1fr) );
183 | border: 1px solid black;
184 | padding-top: 100px;
185 | overflow-x: hidden;
186 | }
187 |
188 | /* hero section */
189 | #profile-pic {
190 | border: 0.4rem dotted black;
191 | border-radius: 50%;
192 | background:var(--main-bg-color);
193 | width:20rem;
194 | filter: grayscale(0%);
195 | transition: filter 1s ease;
196 | aspect-ratio: 1/1;
197 | }
198 | #profile-pic:hover {
199 | filter: grayscale(100%);
200 | }
201 | .intro h1 {
202 | font-size: 12vmin;
203 | color: var(--font-color)
204 | }
205 | .intro h2 {
206 | font-size: 8vmin;
207 | color: var(--font-color);
208 | line-height: 1.5;
209 | font-style: oblique;
210 | font-weight: lighter;
211 | }
212 | u {
213 | color:var(--font-color)
214 | text-decoration-color: black;
215 | text-decoration-thickness: 0.2rem;
216 | text-decoration-style: wavy;
217 | text-underline-offset: 1rem;
218 |
219 | }
220 | /* typography section */
221 | blockquote {
222 | font-size: 16vmin;
223 | line-height: 0.95;
224 | font-style: oblique;
225 | }
226 | q {
227 | font-size: 2.5vmin;
228 | font-style: italic;
229 | }
230 |
231 | /* cards */
232 | .card {
233 | padding: 3rem;
234 | background: var(--main-bg-color);
235 | border: .1rem solid black;
236 | border-radius: 0.5rem 0 0.5rem 0;
237 | overflow-wrap: break-word;
238 | min-width: 20rem;
239 | max-width: 420rem;
240 | line-height: 2.5rem;
241 | margin:3vmin;
242 | }
243 | .card::first-line {
244 | background: var(--primary-color);
245 | }
246 | .card h1 {
247 | font-size: 8vmin;
248 | font-weight:300;
249 |
250 | }
251 | .card h2 {
252 | color: var(--secondary-color);
253 | font-size: 1rem;
254 | font-style: italic;
255 | text-decoration:overline;
256 | margin-top: 1ch;
257 | }
258 | .card .links {
259 | display:flex;
260 | margin:1rem;
261 | }
262 | .card li {
263 | list-style: none;
264 | }
265 | .card .links a {
266 | background: var(--animated-bg-color);
267 | padding:.5rem;
268 | border: .1rem solid black;
269 | border-radius: 0.5rem 0 0.5rem 0;
270 | box-shadow: .2rem .2rem;
271 | text-decoration: none;
272 | color: var(--link-color);
273 | margin:0.5rem;
274 | }
275 | .card li:hover {
276 | transform: scale(1.1);
277 | }
278 | .card img {
279 | width:100%;
280 | height:auto;
281 | border-style: dashed;
282 | border-color: var(--font-color);
283 | transition: all 1s ease;
284 | padding:1rem;
285 | margin-top: 2rem;
286 | margin-bottom:2rem;
287 | }
288 | .card img:hover {
289 | padding:2rem;
290 | cursor: pointer;
291 | }
292 |
293 | /* footer */
294 | footer {
295 | border: 1px solid;
296 | border-color: black;
297 | color: var(--font-color);
298 | padding:2rem;
299 | display: flex;
300 | align-items: center;
301 | justify-content: center;
302 | flex-direction: column;
303 | gap:1rem;
304 | }
305 |
306 | #footer-logo {
307 | width:10vmin;
308 | height:auto;
309 | border: 1px solid black;
310 | border-radius: 50%;
311 | }
312 |
313 | /*footer marquee */
314 | #skills {
315 | font-size:3rem;
316 | }
317 | #skills:hover {
318 | animation-play-state: paused;
319 | }
320 |
321 | /* tooltips */
322 | .tooltip {
323 | position: relative; /* allows for precise control of the tooltip location. */
324 | text-decoration-line: underline; /* indicate interactive element*/
325 | text-decoration-color: tomato;
326 | text-decoration-style: wavy;
327 | text-decoration-thickness: 0.15em;
328 | text-underline-position: under;
329 | }
330 | .tooltip::after {
331 | position: absolute;
332 | bottom: 1rem; /* positions the tooltip right above the text */
333 | min-width: 4rem;
334 | max-width: 50ch; /* limit the width to 20 characters per line */
335 | background: pink;
336 | border:1px solid black;
337 | border-radius: 0.5rem;
338 | will-change: transform; /* added because the animation was leaving a ghost of junk pixels behind after running the animation */
339 | transform: scale(0);
340 | transition: 0.5s ease;
341 | transform-origin: bottom left;
342 | }
343 | .tooltip::after {
344 | content: attr(data-tooltip);
345 | font-size: 14px; /* locks the font size so that the tooltip font remains the same regardless of the parent font size */
346 | }
347 | .tooltip:hover::after {
348 | transform: scale(1);
349 | padding: 0.5rem;
350 | }
351 |
352 | /* animated background via https://wweb.dev/resources/animated-css-background-generator */
353 | @keyframes move {
354 | 100% {
355 | transform: translate3d(0, 0, 1px) rotate(360deg);
356 | }
357 | }
358 | .background {
359 | position: fixed;
360 | width: 100vw;
361 | height: 100vh;
362 | top: 0;
363 | left: 0;
364 | background: var(--animated-bg-color);
365 | overflow: hidden;
366 | z-index: -1000;
367 | }
368 | .background span {
369 | width: 46vmin;
370 | height: 46vmin;
371 | border-radius: 46vmin;
372 | backface-visibility: hidden;
373 | position: absolute;
374 | will-change:auto;
375 | animation: move;
376 | animation-duration: 45;
377 | animation-timing-function: linear;
378 | animation-iteration-count: infinite;
379 | }
380 | .background span:nth-child(0) {
381 | color: var(--secondary-color);
382 | top: 13%;
383 | left: 38%;
384 | animation-duration: 11s;
385 | animation-delay: -27s;
386 | transform-origin: -7vw 3vh;
387 | box-shadow: -92vmin 0 12.329126313955616vmin currentColor;
388 | }
389 | .background span:nth-child(1) {
390 | color: var(--secondary-color);
391 | top: 44%;
392 | left: 8%;
393 | animation-duration: 46s;
394 | animation-delay: -2s;
395 | transform-origin: 19vw 24vh;
396 | box-shadow: 92vmin 0 12.055993421996787vmin currentColor;
397 | }
398 | .background span:nth-child(2) {
399 | color: var(--primary-color);
400 | top: 28%;
401 | left: 79%;
402 | animation-duration: 7s;
403 | animation-delay: -37s;
404 | transform-origin: -10vw 10vh;
405 | box-shadow: 92vmin 0 11.927667725426126vmin currentColor;
406 | }
407 | .background span:nth-child(3) {
408 | color: var(--primary-color);
409 | top: 39%;
410 | left: 57%;
411 | animation-duration: 20s;
412 | animation-delay: -3s;
413 | transform-origin: 13vw -19vh;
414 | box-shadow: 92vmin 0 11.935095694618038vmin currentColor;
415 | }
416 | .background span:nth-child(4) {
417 | color: var(--secondary-color);
418 | top: 32%;
419 | left: 42%;
420 | animation-duration: 41s;
421 | animation-delay: -34s;
422 | transform-origin: -11vw 10vh;
423 | box-shadow: -92vmin 0 12.321440867291019vmin currentColor;
424 | }
425 | .background span:nth-child(5) {
426 | color: var(--primary-color);
427 | top: 37%;
428 | left: 54%;
429 | animation-duration: 38s;
430 | animation-delay: -17s;
431 | transform-origin: -8vw 4vh;
432 | box-shadow: -92vmin 0 11.555504281175715vmin currentColor;
433 | }
434 | .background span:nth-child(6) {
435 | color: var(--main-bg-color);
436 | top: 37%;
437 | left: 15%;
438 | animation-duration: 34s;
439 | animation-delay: -26s;
440 | transform-origin: 17vw 25vh;
441 | box-shadow: 92vmin 0 12.038185662965873vmin currentColor;
442 | }
443 |
444 | #ampersand {
445 | letter-spacing: -.5ch;
446 | font-size: larger;
447 | font-weight: bold;
448 | padding: .5ch;
449 | -webkit-text-stroke-width: 2px;
450 | -webkit-text-stroke-color: var(--body-color);
451 | }
452 |
453 | .projects {
454 | font-size: 4rem;
455 | font-weight:lighter;
456 | padding: .5ch;
457 | text-align: center;
458 | }
459 |
460 |
461 |
--------------------------------------------------------------------------------
/images/logo-text.svg:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Alekzandriia Portfolio
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 | 🌈
21 |
22 |
23 | Hello! Welcome to my website. Thanks for stopping by. Please have a look around. if you have any questions feel free to reach out and let me know. Have a nice day! =)
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
Hi, I'm Alekz
39 | Creative Designer && Developer
40 |
41 |
42 |
43 |
44 |
You know all those amazing ideas you have? Let's bring them to life.
45 |
46 |
47 |
48 |
Projects
49 |
50 | Attica
51 | VS Code Extension
52 | A simple light pastel theme extension with syntax highlighting for Visual Studio Code. Dark mode options coming soon.
53 |
57 |
58 | Everyone should learn to program, because it teaches you to think.
59 |
60 |
61 | Terminus
62 | Terminal-themed links page
63 | A different take on the typical links page for a social media bio. Basing the design on a ubiquitous software application (the terminal) communicates the type of content the user can expect when interacting with the links. I also added a "skip" button to the bottom right so that repeat visitors do not need to wait for the animation to play before accessing the links.
64 |
68 |
69 | If you are working on something that you really care about, you don’t have to be pushed. The vision pulls you.
70 |
71 |
72 | Sketchbook
73 | Digital Illustration
74 | I love designing & creating illustrations by hand. Incorporating hand-drawn elements into your designs adds warmth & makes your site stand out against a sea of generic templates.
75 |
78 |
79 | A beautiful project that doesn’t work very well is ugly.
80 |
81 |
82 | Creative Coding
83 | Code Snippet
84 | This is a typewriter effect made sans JavaScript. Just 100% pure CSS goodness. CodePen is my favourite place to quickly test out new or exciting coding concepts. Check out some of my other work below.
85 |
88 |
89 | The art of debugging is figuring out what you really told your program to do rather than what you thought you told it to do.
90 |
91 |
92 |
93 |
94 |
95 | html | css | javascript | node | wordpress | figma | photoshop | jekyll | gatsby | git | command line | docker | linux | aws
96 |
97 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------