├── 000
├── index.html
├── script.js
└── style.css
├── 001-expanding-cards
├── index.html
├── output.gif
├── script.js
└── style.css
├── 002-progress-steps
├── index.html
├── output.gif
├── script.js
└── style.css
├── 003-rotating-navigation
├── index.html
├── output.gif
├── script.js
└── style.css
├── 004-hidden-search-widget
├── index.html
├── output.gif
├── script.js
└── style.css
├── 005-blurry-loading
├── index.html
├── output.gif
├── script.js
└── style.css
├── 006-scroll-animation
├── index.html
├── output.gif
├── script.js
└── style.css
├── 007-split-landing-page
├── index.html
├── output.gif
├── ps.jpg
├── script.js
├── style.css
└── xbox.jpg
├── 008-form-wave-animation
├── index.html
├── output.gif
├── script.js
└── style.css
├── 009-sound-board
├── index.html
├── output.gif
├── script.js
├── sounds
│ ├── applause.mp3
│ ├── boo.mp3
│ ├── gasp.mp3
│ ├── tada.mp3
│ ├── victory.mp3
│ └── wrong.mp3
└── style.css
├── 010-dad-jokes
├── index.html
├── output.gif
├── script.js
└── style.css
├── 011-event-keycodes
├── index.html
├── output.gif
├── script.js
└── style.css
├── 012-faq-collapse
├── index.html
├── output.gif
├── script.js
└── style.css
├── 013-random-choice-picker
├── index.html
├── output.gif
├── script.js
└── style.css
├── 014-animated-navigation
├── index.html
├── output.gif
├── script.js
└── style.css
├── 015-increment-counter
├── index.html
├── output.gif
├── script.js
└── style.css
├── 016-drink-water
├── index.html
├── output.gif
├── script.js
└── style.css
├── 017-movie-app
├── index.html
├── output.gif
├── script.js
└── style.css
├── 018-background-slider
├── index.html
├── output.gif
├── script.js
└── style.css
├── 019-theme-clock
├── index.html
├── output.gif
├── script.js
└── style.css
├── 020-button-ripple-effect
├── index.html
├── output.gif
├── script.js
└── style.css
├── 021-drag-n-drop
├── index.html
├── output.gif
├── script.js
└── style.css
├── 022-drawing-app
├── index.html
├── output.gif
├── script.js
└── style.css
├── 023-kinetic-css-loader
├── index.html
├── output.gif
├── script.js
└── style.css
├── 024-content-placeholder
├── index.html
├── output.gif
├── script.js
└── style.css
├── 025-sticky-navbar
├── index.html
├── output.gif
├── script.js
└── style.css
├── 026-vertical-slider
├── index.html
├── output.gif
├── script.js
└── style.css
├── 027-toast-notification
├── index.html
├── output.gif
├── script.js
└── style.css
├── 028-github-profiles
├── index.html
├── output.gif
├── script.js
└── style.css
├── 029-double-click-heart
├── index.html
├── output.gif
├── script.js
└── style.css
├── 030-auto-text-effect
├── index.html
├── output.gif
├── script.js
└── style.css
├── 031-random-password
├── index.html
├── output.gif
├── script.js
└── style.css
├── 032-good-cheap-fast
├── index.html
├── output.gif
├── script.js
└── style.css
├── 033-notes-app
├── index.html
├── output.gif
├── script.js
└── style.css
├── 034-animated-countdown
├── index.html
├── output.gif
├── script.js
└── style.css
├── 035-image-carousel
├── index.html
├── output.gif
├── script.js
└── style.css
├── 036-hoverboard
├── index.html
├── output.gif
├── script.js
└── style.css
├── 037-pokedex
├── index.html
├── output.gif
├── script.js
└── style.css
├── 038-mobile-tab-navigation
├── index.html
├── output.gif
├── script.js
└── style.css
├── 039-password-strength-background
├── index.html
├── output.gif
├── script.js
└── style.css
├── 040-3d-background-boxes
├── index.html
├── output.gif
├── script.js
└── style.css
├── 041-verify-account-ui
├── index.html
├── output.gif
├── script.js
└── style.css
├── 042-live-user-filter
├── index.html
├── output.gif
├── script.js
└── style.css
├── 043-feedback-ui-design
├── index.html
├── output.png
├── script.js
└── style.css
├── 044-custom-range-slider
├── index.html
├── output.png
├── script.js
└── style.css
├── 045-netflix-mobile-navigation
├── index.html
├── output.gif
├── output.png
├── script.js
└── style.css
├── 046-quiz-app
├── index.html
├── output.gif
├── script.js
└── style.css
├── 047-testimonial-box-switcher
├── index.html
├── output.gif
├── script.js
└── style.css
├── 048-random-image-generator
├── index.html
├── output.png
├── script.js
└── style.css
├── 049-todo-list
├── index.html
├── output.gif
├── script.js
└── style.css
├── 050-insect-catch-game
├── index.html
├── output.gif
├── script.js
└── style.css
└── README.md
/000/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | My Project
21 |
22 |
23 |
24 | Project Starter
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/000/script.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/000/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: "Mulish", sans-serif;
9 | display: flex;
10 | flex-direction: column;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
--------------------------------------------------------------------------------
/001-expanding-cards/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
14 | Expanding Cards
15 |
16 |
17 |
18 |
19 |
25 |
Explore The World
26 |
27 |
33 |
Wild Forest
34 |
35 |
41 |
Sunny Beach
42 |
43 |
49 |
City on Winter
50 |
51 |
57 |
Mountains - Clouds
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/001-expanding-cards/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/001-expanding-cards/output.gif
--------------------------------------------------------------------------------
/001-expanding-cards/script.js:
--------------------------------------------------------------------------------
1 | const panels = document.querySelectorAll(".panel");
2 |
3 | panels.forEach((panel) => {
4 | panel.addEventListener("click", () => {
5 | removeActiveClasses();
6 | panel.classList.add("active");
7 | });
8 | });
9 |
10 | function removeActiveClasses() {
11 | panels.forEach((panel) => {
12 | panel.classList.remove("active");
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/001-expanding-cards/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | body {
10 | font-family: "Mulish", sans-serif;
11 | display: flex;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | .container {
20 | display: flex;
21 | width: 90vw;
22 | }
23 |
24 | .panel {
25 | background-size: cover;
26 | background-position: center;
27 | background-repeat: no-repeat;
28 | height: 80vh;
29 | border-radius: 50px;
30 | color: white;
31 | cursor: pointer;
32 | flex: 0.5; /* ! Confusion */
33 | margin: 10px;
34 | position: relative;
35 | transition: flex 0.7s ease-in;
36 | }
37 |
38 | .panel h3 {
39 | font-size: 24px;
40 | position: absolute;
41 | bottom: 20px;
42 | left: 20px;
43 | margin: 0;
44 | opacity: 0;
45 | }
46 |
47 | .panel.active {
48 | flex: 5;
49 | }
50 |
51 | .panel.active h3 {
52 | opacity: 1;
53 | transition: opacity 0.3s ease-in 0.4s;
54 | }
55 |
56 | @media (max-width: 480px) {
57 | .container {
58 | width: 100vw;
59 | }
60 |
61 | /* ! Confusion */
62 | .panel:nth-of-type(4),
63 | .panel:nth-of-type(5) {
64 | display: none;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/002-progress-steps/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
14 | Progress Steps
15 |
16 |
17 |
18 |
19 |
20 |
21 |
1
22 |
2
23 |
3
24 |
4
25 |
26 |
27 |
Prev
28 |
Next
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/002-progress-steps/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/002-progress-steps/output.gif
--------------------------------------------------------------------------------
/002-progress-steps/script.js:
--------------------------------------------------------------------------------
1 | const progress = document.getElementById("progress");
2 | const prev = document.getElementById("prev");
3 | const next = document.getElementById("next");
4 | const circles = document.querySelectorAll(".circle");
5 |
6 | let currentActive = 1;
7 |
8 | next.addEventListener("click", () => {
9 | currentActive++;
10 | if (currentActive > circles.length) {
11 | currentActive = circles.length;
12 | }
13 |
14 | update();
15 | });
16 |
17 | prev.addEventListener("click", () => {
18 | currentActive--;
19 | if (currentActive < 1) {
20 | currentActive = 1;
21 | }
22 | update();
23 | });
24 |
25 | function update() {
26 | circles.forEach((circle, idx) => {
27 | if (idx < currentActive) {
28 | circle.classList.add("active");
29 | } else {
30 | circle.classList.remove("active");
31 | }
32 | });
33 |
34 | const actives = document.querySelectorAll(".active");
35 |
36 | progress.style.width =
37 | ((actives.length - 1) / (circles.length - 1)) * 100 + "%";
38 |
39 | if(currentActive === 1){
40 | prev.disabled = true;
41 | }else if (currentActive === circles.length){
42 | next.disabled = true;
43 | }else{
44 | prev.disabled = false;
45 | next.disabled = false;
46 | }
47 | }
--------------------------------------------------------------------------------
/002-progress-steps/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Mulish&display=swap");
2 |
3 | :root {
4 | --line-border-fill: #3498db;
5 | --line-border-empty: #383838;
6 | }
7 |
8 | * {
9 | box-sizing: border-box;
10 | }
11 |
12 | body {
13 | background-color: #1f1f1f;
14 | font-family: "Mulish", sans-serif;
15 | display: flex;
16 | align-items: center;
17 | justify-content: center;
18 | height: 100vh;
19 | overflow: hidden;
20 | margin: 0;
21 | }
22 |
23 | .container {
24 | text-align: center;
25 | }
26 |
27 | .progress-container {
28 | display: flex;
29 | justify-content: space-between;
30 | position: relative;
31 | margin-bottom: 30px;
32 | max-width: 100%;
33 | width: 350px;
34 | }
35 |
36 | .progress-container::before {
37 | content: "";
38 | background-color: var(--line-border-empty);
39 | position: absolute;
40 | top: 50%;
41 | left: 0;
42 | transform: translateY(-50%);
43 | height: 4px;
44 | width: 100%;
45 | z-index: -1;
46 | }
47 |
48 | .progress {
49 | background-color: var(--line-border-fill);
50 | position: absolute;
51 | top: 50%;
52 | left: 0;
53 | transform: translateY(-50%);
54 | height: 4px;
55 | width: 0%;
56 | z-index: -1;
57 | transition: 0.4s ease;
58 | }
59 |
60 | .circle {
61 | background-color: #1f1f1f;
62 | color: #e2e2e2;
63 | border-radius: 50%;
64 | height: 30px;
65 | width: 30px;
66 | display: flex;
67 | align-items: center;
68 | justify-content: center;
69 | border: 3px solid var(--line-border-empty);
70 | transition: 0.4s ease;
71 | }
72 |
73 | .circle.active {
74 | border-color: var(--line-border-fill);
75 | }
76 |
77 | .btn {
78 | background-color: var(--line-border-fill);
79 | color: #fff;
80 | border: 0;
81 | border-radius: 6px;
82 | cursor: pointer;
83 | font-family: inherit;
84 | padding: 8px 30px;
85 | margin: 5px;
86 | font-size: 14px;
87 | }
88 |
89 | .btn:active {
90 | transform: scale(0.98);
91 | }
92 |
93 | .btn:focus {
94 | outline: 0;
95 | }
96 |
97 | .btn:disabled {
98 | background-color: var(--line-border-empty);
99 | cursor: not-allowed;
100 | }
101 |
--------------------------------------------------------------------------------
/003-rotating-navigation/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/003-rotating-navigation/output.gif
--------------------------------------------------------------------------------
/003-rotating-navigation/script.js:
--------------------------------------------------------------------------------
1 | const open = document.getElementById("open");
2 | const close = document.getElementById("close");
3 | const container = document.querySelector(".container");
4 |
5 | open.addEventListener("click", () => container.classList.add("show-nav"));
6 |
7 | close.addEventListener("click", () => container.classList.remove("show-nav"));
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/003-rotating-navigation/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Lato&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: 'Lato', sans-serif;
9 | background-color: #333;
10 | color: #222;
11 | overflow-x: hidden;
12 | margin: 0;
13 | }
14 |
15 | .container {
16 | background-color: #fafafa;
17 | transform-origin: top left;
18 | transition: transform 0.5s linear;
19 | width: 100vw;
20 | min-height: 100vh;
21 | padding: 50px;
22 | }
23 |
24 | .container.show-nav {
25 | transform: rotate(-20deg);
26 | }
27 |
28 | .circle-container {
29 | position: fixed;
30 | top: -100px;
31 | left: -100px;
32 | }
33 |
34 | .circle {
35 | background-color: #ff7979;
36 | height: 200px;
37 | width: 200px;
38 | border-radius: 50%;
39 | position: relative;
40 | transition: transform 0.5s linear;
41 | }
42 |
43 | .container.show-nav .circle {
44 | transform: rotate(-70deg);
45 | }
46 |
47 | .circle button {
48 | cursor: pointer;
49 | position: absolute;
50 | top: 50%;
51 | left: 50%;
52 | height: 100px;
53 | background: transparent;
54 | border: 0;
55 | font-size: 26px;
56 | color: #fff;
57 | }
58 |
59 | .circle button:focus {
60 | outline: none;
61 | }
62 |
63 | .circle button#open {
64 | left: 60%;
65 | }
66 |
67 | .circle button#close {
68 | top: 60%;
69 | transform: rotate(90deg);
70 | transform-origin: top left;
71 | }
72 |
73 | .container.show-nav + nav li {
74 | transform: translateX(0);
75 | transition-delay: 0.3s;
76 | }
77 |
78 | nav {
79 | position: fixed;
80 | bottom: 40px;
81 | left: 0;
82 | z-index: 100;
83 | }
84 |
85 | nav ul {
86 | list-style-type: none;
87 | padding-left: 30px;
88 | }
89 |
90 | nav ul li {
91 | text-transform: uppercase;
92 | color: #fff;
93 | margin: 40px 0;
94 | transform: translateX(-100%);
95 | transition: transform 0.4s ease-in;
96 | }
97 |
98 | nav ul li i {
99 | font-size: 20px;
100 | margin-right: 10px;
101 | }
102 |
103 | nav ul li + li {
104 | margin-left: 15px;
105 | transform: translateX(-150%);
106 | }
107 |
108 | nav ul li + li + li {
109 | margin-left: 30px;
110 | transform: translateX(-200%);
111 | }
112 |
113 | nav a{
114 | color: #fafafa;
115 | text-decoration: none;
116 | transition: all 0.5s;
117 | }
118 |
119 | nav a:hover {
120 | color: #FF7979;
121 | font-weight: bold;
122 | }
123 |
124 | .content img {
125 | max-width: 100%;
126 | }
127 |
128 | .content {
129 | max-width: 1000px;
130 | margin: 50px auto;
131 | }
132 |
133 | .content h1 {
134 | margin: 0;
135 | }
136 |
137 | .content small {
138 | color: #555;
139 | font-style: italic;
140 | }
141 |
142 | .content p {
143 | color: #333;
144 | line-height: 1.5;
145 | }
--------------------------------------------------------------------------------
/004-hidden-search-widget/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 | Hidden Search Widget
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/004-hidden-search-widget/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/004-hidden-search-widget/output.gif
--------------------------------------------------------------------------------
/004-hidden-search-widget/script.js:
--------------------------------------------------------------------------------
1 | const search = document.querySelector(".search");
2 | const btn = document.querySelector(".btn");
3 | const input = document.querySelector(".input");
4 |
5 | btn.addEventListener("click", () => {
6 | search.classList.toggle("active");
7 | input.focus();
8 | });
9 |
--------------------------------------------------------------------------------
/004-hidden-search-widget/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-image: linear-gradient(90deg, #7d5fff, #7158e2);
9 | font-family: "Roboto", sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
18 | .search {
19 | position: relative;
20 | height: 50px;
21 | }
22 |
23 | .search .input {
24 | background-color: white;
25 | border: 0;
26 | font-size: 18px;
27 | padding: 15px;
28 | height: 50px;
29 | width: 50px;
30 | transition: width 0.3s ease;
31 | }
32 |
33 | .btn{
34 | background-color: white;
35 | border: 0;
36 | cursor: pointer;
37 | font-size: 24px;
38 | position: absolute;
39 | top:0;
40 | left: 0;
41 | height: 50px;
42 | width: 50px;
43 | transition: transform 0.3s ease;
44 | }
45 |
46 | .btn:focus, .input:focus{
47 | outline: none;
48 | }
49 |
50 | .search.active .input{
51 | width: 200px;
52 | }
53 |
54 | .search.active .btn{
55 | transform: translateX(198px);
56 | }
57 |
--------------------------------------------------------------------------------
/005-blurry-loading/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Blurry Loading
21 |
22 |
23 |
24 |
25 |
26 | 0%
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/005-blurry-loading/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/005-blurry-loading/output.gif
--------------------------------------------------------------------------------
/005-blurry-loading/script.js:
--------------------------------------------------------------------------------
1 | const loadText = document.querySelector(".loading-text");
2 | const bg = document.querySelector(".bg");
3 |
4 | let load = 0;
5 |
6 | let int = setInterval(blurring, 30);
7 |
8 | function blurring() {
9 | load++;
10 | if (load > 99) {
11 | clearInterval(int);
12 | }
13 |
14 | loadText.innerText = `${load}%`;
15 | loadText.style.opacity = scale(load, 0, 100, 1, 0);
16 | bg.style.filter = `blur(${scale(load, 0, 100, 30, 0)}px)`;
17 | }
18 |
19 |
20 | // https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers
21 | const scale = (num, in_min, in_max, out_min, out_max) => {
22 | return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
23 | }
--------------------------------------------------------------------------------
/005-blurry-loading/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Ubuntu");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: "Ubuntu", sans-serif;
9 | display: flex;
10 | align-items: center;
11 | justify-content: center;
12 | height: 100vh;
13 | overflow: hidden;
14 | margin: 0;
15 | }
16 |
17 | .bg {
18 | background: url('https://images.unsplash.com/photo-1576161787924-01bb08dad4a4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2104&q=80')
19 | no-repeat center center/cover;
20 | position: absolute;
21 | top: -30px;
22 | left: -30px;
23 | width: calc(100vw + 60px);
24 | height: calc(100vh + 60px);
25 | z-index: -1;
26 | filter: blur(0px);
27 | }
28 |
29 | .loading-text {
30 | font-size: 50px;
31 | color: #fff;
32 | }
--------------------------------------------------------------------------------
/006-scroll-animation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Scroll Animation
21 |
22 |
23 |
24 | Scroll to see the animation
25 |
26 |
Content
27 |
28 |
29 |
Content
30 |
31 |
32 |
Content
33 |
34 |
35 |
Content
36 |
37 |
38 |
Content
39 |
40 |
41 |
Content
42 |
43 |
44 |
Content
45 |
46 |
47 |
Content
48 |
49 |
50 |
Content
51 |
52 |
53 |
Content
54 |
55 |
56 |
Content
57 |
58 |
59 |
Content
60 |
61 |
62 |
Content
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/006-scroll-animation/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/006-scroll-animation/output.gif
--------------------------------------------------------------------------------
/006-scroll-animation/script.js:
--------------------------------------------------------------------------------
1 | const boxes = document.querySelectorAll(".box");
2 |
3 | window.addEventListener("scroll", checkBoxes);
4 |
5 | checkBoxes();
6 |
7 | function checkBoxes() {
8 | const triggerBottom = (window.innerHeight / 5) * 4;
9 |
10 | boxes.forEach((box) => {
11 | const boxTop = box.getBoundingClientRect().top;
12 |
13 | if (boxTop < triggerBottom) {
14 | box.classList.add("show");
15 | } else {
16 | box.classList.remove("show");
17 | }
18 | });
19 | }
20 |
--------------------------------------------------------------------------------
/006-scroll-animation/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #efedd6;
9 | font-family: "Roboto", sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | margin: 0;
15 | overflow-x: hidden;
16 | }
17 |
18 | h1 {
19 | margin: 10px;
20 | }
21 |
22 | .box {
23 | background-color: steelblue;
24 | color: #fff;
25 | display: flex;
26 | align-items: center;
27 | justify-content: center;
28 | width: 400px;
29 | height: 200px;
30 | margin: 10px;
31 | border-radius: 10px;
32 | box-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3);
33 | transform: translateX(400%);
34 | transition: transform 0.4s ease;
35 | }
36 |
37 | .box:nth-of-type(even) {
38 | transform: translateX(-400%);
39 | }
40 |
41 | .box.show {
42 | transform: translateX(0);
43 | }
44 |
45 | .box h2 {
46 | font-size: 45px;
47 | }
48 |
--------------------------------------------------------------------------------
/007-split-landing-page/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Split Landing Page
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
Playstation 5
29 |
Buy Now
30 |
31 |
32 |
33 |
XBox Series X
34 |
Buy Now
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/007-split-landing-page/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/007-split-landing-page/output.gif
--------------------------------------------------------------------------------
/007-split-landing-page/ps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/007-split-landing-page/ps.jpg
--------------------------------------------------------------------------------
/007-split-landing-page/script.js:
--------------------------------------------------------------------------------
1 | const left = document.querySelector(".left");
2 | const right = document.querySelector(".right");
3 | const container = document.querySelector(".container");
4 |
5 | left.addEventListener("mouseenter", () => container.classList.add("hover-left"));
6 | left.addEventListener('mouseleave', () => container.classList.remove("hover-left"));
7 |
8 | right.addEventListener("mouseenter", () => container.classList.add("hover-right"));
9 | right.addEventListener('mouseleave', () => container.classList.remove("hover-right"));v
--------------------------------------------------------------------------------
/007-split-landing-page/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 |
3 | :root {
4 | --left-bg-color: rgba(87, 84, 236, 0.7);
5 | --right-bg-color: rgba(43, 43, 43, 0.8);
6 | --left-btn-hover-color: rgba(87, 84, 236, 1);
7 | --right-btn-hover-color: rgba(28, 122, 28, 1);
8 | --hover-width: 75%;
9 | --other-width: 25%;
10 | }
11 |
12 | * {
13 | box-sizing: border-box;
14 | }
15 |
16 | body {
17 | font-family: "Roboto", sans-serif;
18 | height: 100vh;
19 | overflow: hidden;
20 | margin: 0;
21 | }
22 |
23 | h1{
24 | font-size: 4rem;
25 | color: white;
26 | position: absolute;
27 | left: 50%;
28 | top: 20%;
29 | transform: translateX(-50%);
30 | white-space: nowrap;
31 | }
32 |
33 | .btn{
34 | position: absolute;
35 | display: flex;
36 | justify-content: center;
37 | align-items: center;
38 | left: 50%;
39 | top: 40%;
40 | transform: translateX(-50%);
41 | text-decoration: none;
42 | color: white;
43 | border: #fff solid 0.2rem;
44 | font-size: 1rem;
45 | font-weight: bold;
46 | text-transform: uppercase;
47 | width: 15rem;
48 | padding: 1.5rem;
49 | }
50 |
51 | .split.left .btn:hover{
52 | background-color: var(--left-btn-hover-color);
53 | border-color: var(--left-btn-hover-color);
54 | }
55 |
56 | .split.right .btn:hover{
57 | background-color: var(--right-btn-hover-color);
58 | border-color: var(--right-btn-hover-color);
59 | }
60 |
61 | .container {
62 | position: relative;
63 | width: 100%;
64 | height: 100%;
65 | background: #333;
66 | }
67 |
68 | .split {
69 | position: absolute;
70 | width: 50%;
71 | height: 100%;
72 | overflow: hidden;
73 | transition: all 2s ease;
74 | }
75 |
76 | .split.left {
77 | left: 0;
78 | background: url("./ps.jpg");
79 | background-repeat: no-repeat;
80 | background-size: cover;
81 | }
82 |
83 | .split.left::before {
84 | content: "";
85 | position: absolute;
86 | width: 100%;
87 | height: 100%;
88 | background-color: var(--left-bg-color);
89 | }
90 |
91 | .split.right {
92 | right: 0;
93 | background: url("./xbox.jpg");
94 | background-repeat: no-repeat;
95 | background-size: cover;
96 | }
97 |
98 | .split.right::before{
99 | content: "";
100 | position: absolute;
101 | width: 100%;
102 | height: 100%;
103 | background-color: var(--right-bg-color);
104 | }
105 |
106 | .hover-left .left{
107 | width: var(--hover-width);
108 | }
109 |
110 | .hover-left .right{
111 | width: var(--other-width);
112 | }
113 |
114 | .hover-right .right{
115 | width: var(--hover-width);
116 | }
117 |
118 | .hover-right .left{
119 | width: var(--other-width);
120 | }
121 |
122 |
--------------------------------------------------------------------------------
/007-split-landing-page/xbox.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/007-split-landing-page/xbox.jpg
--------------------------------------------------------------------------------
/008-form-wave-animation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
15 |
16 |
17 | Form Input Wave
18 |
19 |
20 |
21 |
22 |
Please Login
23 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/008-form-wave-animation/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/008-form-wave-animation/output.gif
--------------------------------------------------------------------------------
/008-form-wave-animation/script.js:
--------------------------------------------------------------------------------
1 | const labels = document.querySelectorAll(".form-control label");
2 |
3 | console.log(labels);
4 |
5 | labels.forEach((label) => {
6 | label.innerHTML = label.innerText
7 | .split("")
8 | .map((letter, idx) => `${letter} `)
9 | .join("");
10 | });
11 |
--------------------------------------------------------------------------------
/008-form-wave-animation/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: steelblue;
9 | color: white;
10 | font-family: "Mulish", sans-serif;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: center;
15 | height: 100vh;
16 | overflow: hidden;
17 | margin: 0;
18 | }
19 |
20 | .container {
21 | background-color: rgba(0, 0, 0, 0.4);
22 | padding: 20px 40px;
23 | border-radius: 5px;
24 | }
25 |
26 | .container h1 {
27 | text-align: center;
28 | margin-bottom: 30px;
29 | }
30 |
31 | .container a {
32 | text-decoration: none;
33 | color: lightblue;
34 | }
35 |
36 | .btn {
37 | cursor: pointer;
38 | display: inline-block;
39 | width: 100%;
40 | background-color: lightblue;
41 | padding: 15px;
42 | font-family: inherit;
43 | font-size: 16px;
44 | border: 0;
45 | border-radius: 5px;
46 | }
47 |
48 | .btn:focus {
49 | outline: 0;
50 | }
51 |
52 | .btn:active {
53 | transform: scale(0.98);
54 | }
55 |
56 | .text {
57 | margin-top: 30px;
58 | }
59 |
60 | .form-control {
61 | position: relative;
62 | margin: 20px 0 40px;
63 | width: 300px;
64 | }
65 |
66 | .form-control input {
67 | background-color: transparent;
68 | border: 0;
69 | border-bottom: 2px #fff solid;
70 | display: block;
71 | width: 100%;
72 | padding: 15px 0;
73 | font-size: 18px;
74 | color: #fff;
75 | }
76 |
77 | .form-control input:focus,
78 | .form-control input:valid {
79 | outline: 0;
80 | border-bottom-color: lightblue;
81 | }
82 |
83 | .form-control label {
84 | position: absolute;
85 | top: 15px;
86 | left: 0;
87 | }
88 |
89 | .form-control label span {
90 | display: inline-block;
91 | font-size: 18px;
92 | min-width: 5px;
93 | transition: 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
94 | }
95 |
96 | .form-control input:focus + label span,
97 | .form-control input:valid + label span {
98 | color: lightblue;
99 | transform: translateY(-30px);
100 | }
101 |
--------------------------------------------------------------------------------
/009-sound-board/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Sound Board
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/009-sound-board/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/output.gif
--------------------------------------------------------------------------------
/009-sound-board/script.js:
--------------------------------------------------------------------------------
1 | const sounds = ["applause", "boo", "gasp", "tada", "victory", "wrong"];
2 |
3 | sounds.forEach((sound) => {
4 | const btn = document.createElement("button");
5 | btn.classList.add("btn");
6 |
7 | btn.innerText = sound;
8 |
9 | btn.addEventListener("click", () => {
10 | stopSongs();
11 | document.getElementById(sound).play();
12 | });
13 |
14 | document.getElementById("buttons").appendChild(btn);
15 | });
16 |
17 | function stopSongs() {
18 | sounds.forEach((sound) => {
19 | const song = document.getElementById(sound);
20 | song.pause();
21 | song.currentTime = 0;
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/009-sound-board/sounds/applause.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/sounds/applause.mp3
--------------------------------------------------------------------------------
/009-sound-board/sounds/boo.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/sounds/boo.mp3
--------------------------------------------------------------------------------
/009-sound-board/sounds/gasp.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/sounds/gasp.mp3
--------------------------------------------------------------------------------
/009-sound-board/sounds/tada.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/sounds/tada.mp3
--------------------------------------------------------------------------------
/009-sound-board/sounds/victory.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/sounds/victory.mp3
--------------------------------------------------------------------------------
/009-sound-board/sounds/wrong.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/009-sound-board/sounds/wrong.mp3
--------------------------------------------------------------------------------
/009-sound-board/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: rgb(161, 100, 223);
9 | font-family: "Poppins", sans-serif;
10 | display: flex;
11 | flex-wrap: wrap;
12 | align-items: center;
13 | justify-content: center;
14 | text-align: center;
15 | height: 100vh;
16 | overflow: hidden;
17 | margin: 0;
18 | }
19 |
20 | .btn {
21 | background-color: rebeccapurple;
22 | border-radius: 5px;
23 | border: none;
24 | color: white;
25 | margin: 1rem;
26 | padding: 1.5rem 3rem;
27 | font-size: 1.2rem;
28 | font-family: inherit;
29 | cursor: pointer;
30 | }
31 |
32 | .btn:hover {
33 | opacity: 0.9;
34 | }
35 |
36 | .btn:focus {
37 | outline: none;
38 | }
39 |
--------------------------------------------------------------------------------
/010-dad-jokes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Dad Jokes
21 |
22 |
23 |
24 |
25 |
26 |
Don't Laugh Challenge
27 |
28 | //joke goes here
29 |
30 |
31 |
Get Another Joke
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/010-dad-jokes/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/010-dad-jokes/output.gif
--------------------------------------------------------------------------------
/010-dad-jokes/script.js:
--------------------------------------------------------------------------------
1 | const jokeEl = document.getElementById("joke");
2 | const jokeBtn = document.getElementById("jokeBtn");
3 |
4 | generateJoke();
5 |
6 |
7 | // using .then
8 | // ---------------
9 |
10 | // function generateJoke() {
11 | // const config = {
12 | // headers: {
13 | // Accept: "application/json",
14 | // },
15 | // };
16 | // fetch("https://icanhazdadjoke.com/", config)
17 | // .then((res) => res.json())
18 | // .then((data) => {
19 | // jokeEl.innerHTML = data.joke;
20 | // });
21 | // }
22 |
23 |
24 | // using async await
25 | // -----------------
26 | async function generateJoke() {
27 | const config = {
28 | headers: {
29 | Accept: "application/json",
30 | },
31 | };
32 | const res = await fetch("https://icanhazdadjoke.com/", config);
33 | const data = await res.json();
34 | jokeEl.innerHTML = data.joke;
35 | }
36 |
37 | jokeBtn.addEventListener("click", generateJoke);
38 |
--------------------------------------------------------------------------------
/010-dad-jokes/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #686de0;
9 | font-family: "Roboto", sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | padding: 20px;
18 | }
19 |
20 | .container {
21 | background-color: #fff;
22 | border-radius: 10px;
23 | box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.1), 0 6px 6px rgba(0, 0, 0, 0.1);
24 | padding: 50px 20px;
25 | text-align: center;
26 | max-width: 100%;
27 | width: 800px;
28 | }
29 |
30 | h3 {
31 | margin: 0;
32 | opacity: 0.5;
33 | letter-spacing: 2px;
34 | }
35 |
36 | .joke {
37 | font-size: 30px;
38 | letter-spacing: 1px;
39 | line-height: 40px;
40 | margin: 50px auto;
41 | max-width: 600px;
42 | }
43 |
44 | .btn {
45 | background-color: #9f68e0;
46 | border: 0;
47 | border-radius: 10px;
48 | color: white;
49 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.1), 0 6px 6px rgba(0, 0, 0, 0.1);
50 | padding: 14px 40px;
51 | font-size: 16px;
52 | cursor: pointer;
53 | }
54 |
55 | .btn:active {
56 | transform: scale(0.98);
57 | }
58 |
59 | .btn:focus {
60 | outline: 0;
61 | }
62 |
--------------------------------------------------------------------------------
/011-event-keycodes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Event Key Codes
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | Press any key to get the Key Code
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/011-event-keycodes/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/011-event-keycodes/output.gif
--------------------------------------------------------------------------------
/011-event-keycodes/script.js:
--------------------------------------------------------------------------------
1 | const insert = document.getElementById("insert");
2 |
3 | window.addEventListener("keydown", (event) => {
4 | insert.innerHTML = `
5 |
6 | ${event.key === " " ? "space" : event.key}
7 | event.key
8 |
9 |
10 | ${event.keyCode}
11 | event.keyCode
12 |
13 |
14 | ${event.code}
15 | event.code
16 |
17 | `;
18 | });
19 |
--------------------------------------------------------------------------------
/011-event-keycodes/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #e1e1e1;
9 | font-family: "Mulish", sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | text-align: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | .key {
20 | border: 1px solid #999;
21 | background-color: #eee;
22 | box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
23 | display: inline-flex;
24 | align-items: center;
25 | font-size: 20px;
26 | padding: 20px;
27 | flex-direction: column;
28 | margin: 10px;
29 | font-weight: bold;
30 | min-width: 150px;
31 | position: relative;
32 | }
33 |
34 | .key small {
35 | position: absolute;
36 | top: -24px;
37 | left: 0;
38 | text-align: center;
39 | width: 100%;
40 | color: #555;
41 | font-size: 14px;
42 | }
43 |
--------------------------------------------------------------------------------
/012-faq-collapse/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/012-faq-collapse/output.gif
--------------------------------------------------------------------------------
/012-faq-collapse/script.js:
--------------------------------------------------------------------------------
1 | const toggles = document.querySelectorAll(".faq-toggle");
2 |
3 | toggles.forEach((toggle) => {
4 | toggle.addEventListener("click", () => {
5 | toggle.parentNode.classList.toggle("active");
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/012-faq-collapse/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: "Mulish", sans-serif;
9 | background-color: #f0f0f0;
10 | }
11 |
12 | h1 {
13 | margin: 50px 0 30px;
14 | text-align: center;
15 | }
16 |
17 | .faq-container {
18 | max-width: 600px;
19 | margin: 0 auto;
20 | }
21 |
22 | .faq {
23 | background-color: transparent;
24 | border: 1px solid #9fa4a8;
25 | border-radius: 10px;
26 | margin: 20px 0;
27 | padding: 30px;
28 | position: relative;
29 | overflow: hidden;
30 | transition: all 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
31 | }
32 |
33 | .faq.active {
34 | background-color: white;
35 | box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1), 0 3px 6px rgba(0, 0, 0, 0.1);
36 | }
37 |
38 | .faq.active::before,
39 | .faq.active::after {
40 | content: "\f075";
41 | font-family: "Font Awesome 5 Free";
42 | color: #2ecc71;
43 | font-size: 7rem;
44 | position: absolute;
45 | opacity: 0.2;
46 | top: 20px;
47 | left: 20px;
48 | z-index: 0;
49 | }
50 |
51 | .faq.active::before {
52 | color: #3498db;
53 | top: -10px;
54 | left: -10px;
55 | transform: rotateY(180deg);
56 | }
57 |
58 | .faq-title {
59 | margin: 0 35px 0 0;
60 | }
61 |
62 | .faq-text {
63 | display: none;
64 | margin: 30px 0 0;
65 | }
66 |
67 | .faq.active .faq-text {
68 | display: block;
69 | }
70 |
71 | .faq-toggle {
72 | background-color: transparent;
73 | border: 0;
74 | border-radius: 50%;
75 | cursor: pointer;
76 | display: flex;
77 | align-items: center;
78 | justify-content: center;
79 | font-size: 16px;
80 | position: absolute;
81 | padding: 0;
82 | top: 30px;
83 | right: 30px;
84 | height: 30px;
85 | width: 30px;
86 | }
87 |
88 | .faq-toggle:focus {
89 | outline: 0;
90 | }
91 |
92 | .faq-toggle .fa-times {
93 | color: white;
94 | display: none;
95 | }
96 |
97 | .faq.active .faq-toggle .fa-times {
98 | display: block;
99 | }
100 |
101 | .faq.active .faq-toggle .fa-chevron-down {
102 | display: none;
103 | }
104 |
105 | .faq.active .faq-toggle {
106 | background-color: #9fa4a8;
107 | }
108 |
--------------------------------------------------------------------------------
/013-random-choice-picker/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Random Choice Picker
21 |
22 |
23 |
24 |
25 |
Enter all of the choices divided by a comma (',')
26 | Press Enter when you are done.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/013-random-choice-picker/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/013-random-choice-picker/output.gif
--------------------------------------------------------------------------------
/013-random-choice-picker/script.js:
--------------------------------------------------------------------------------
1 | const tagsEl = document.getElementById("tags");
2 | const textarea = document.getElementById("textarea");
3 |
4 | textarea.focus();
5 |
6 | textarea.addEventListener("keyup", (e) => {
7 | createTags(e.target.value);
8 | if (e.key === "Enter") {
9 | setTimeout(() => {
10 | e.target.value = "";
11 | }, 10);
12 | randomSelect();
13 | }
14 | });
15 |
16 | function createTags(input) {
17 | const tags = input
18 | .split(",")
19 | .filter((tag) => tag.trim() != "")
20 | .map((tag) => tag.trim());
21 |
22 | tagsEl.innerHTML = "";
23 | tags.forEach((tag) => {
24 | const tagEl = document.createElement("span");
25 | tagEl.classList.add("tag");
26 | tagEl.innerText = tag;
27 | tagsEl.appendChild(tagEl);
28 | });
29 | }
30 |
31 | function randomSelect() {
32 | const times = 30;
33 | const interval = setInterval(() => {
34 | const randomTag = pickRandomTag();
35 | highlightTag(randomTag);
36 | setTimeout(() => {
37 | unHighlightTag(randomTag);
38 | }, 100);
39 | }, 100);
40 |
41 | setTimeout(() => {
42 | clearInterval(interval);
43 | setTimeout(() => {
44 | const randomTag = pickRandomTag();
45 | highlightTag(randomTag);
46 | }, 100);
47 | }, times * 100);
48 | }
49 |
50 | function pickRandomTag() {
51 | const tags = document.querySelectorAll(".tag");
52 | return tags[Math.floor(Math.random() * tags.length)];
53 | }
54 |
55 | function highlightTag(tag) {
56 | tag.classList.add("highlight");
57 | }
58 |
59 | function unHighlightTag(tag) {
60 | tag.classList.remove("highlight");
61 | }
62 |
--------------------------------------------------------------------------------
/013-random-choice-picker/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Mulish&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #2b88f0;
9 | font-family: 'Mulish', sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | h3 {
20 | color: white;
21 | margin: 10px 0 20px;
22 | text-align: center;
23 | }
24 |
25 | .container {
26 | width: 500px;
27 | }
28 |
29 | textarea {
30 | border: none;
31 | display: block;
32 | width: 100%;
33 | height: 100px;
34 | font-family: inherit;
35 | padding: 10px;
36 | margin: 0 0 20px;
37 | font-size: 16px;
38 | }
39 |
40 | .tag{
41 | background-color: #f0932b;
42 | color: white;
43 | border-radius: 50px;
44 | padding: 10px 20px;
45 | margin: 0 5px 10px 0;
46 | font-size: 14px;
47 | display: inline-block;
48 | }
49 |
50 | .tag.highlight{
51 | background-color: #273c75;
52 | }
53 |
--------------------------------------------------------------------------------
/014-animated-navigation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Animated Navigation
21 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/014-animated-navigation/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/014-animated-navigation/output.gif
--------------------------------------------------------------------------------
/014-animated-navigation/script.js:
--------------------------------------------------------------------------------
1 | const toggle = document.getElementById("toggle");
2 | const nav = document.getElementById("nav");
3 |
4 | toggle.addEventListener("click", () => {
5 | nav.classList.toggle("active");
6 | });
7 |
--------------------------------------------------------------------------------
/014-animated-navigation/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #eafbff;
9 | background-image: linear-gradient(
10 | to bottom,
11 | #eafbff 0%,
12 | #eafbff 50%,
13 | #5290f9 50%,
14 | #5290f9 100%
15 | );
16 | font-family: "Mulish", sans-serif;
17 | display: flex;
18 | align-items: center;
19 | justify-content: center;
20 | height: 100vh;
21 | margin: 0;
22 | }
23 |
24 | nav{
25 | background-color: white;
26 | padding: 20px;
27 | width: 80px;
28 | display: flex;
29 | align-items: center;
30 | justify-content: center;
31 | border-radius: 3px;
32 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
33 | transition: width 0.6s linear;
34 | }
35 |
36 | nav.active{
37 | width: 350px;
38 | }
39 |
40 | nav ul{
41 | display: flex;
42 | list-style: none;
43 | padding: 0;
44 | margin: 0;
45 | width: 0;
46 | transition: width 0.6s linear;
47 | }
48 |
49 | nav.active ul {
50 | width: 100%;
51 | }
52 |
53 | nav ul li {
54 | transform: rotateY(0deg);
55 | opacity: 0;
56 | transition: transform 0.6s linear, opacity 0.6s linear;
57 | }
58 |
59 | nav.active ul li {
60 | opacity: 1;
61 | transform: rotateY(360deg);
62 | }
63 |
64 | nav ul a{
65 | position: relative;
66 | color: black;
67 | text-decoration: none;
68 | margin: 0 10px;
69 | }
70 |
71 | .icon {
72 | background-color: #fff;
73 | border: 0;
74 | cursor: pointer;
75 | padding: 0;
76 | position: relative;
77 | height: 30px;
78 | width: 30px;
79 | }
80 |
81 | .icon:focus{
82 | outline: 0;
83 | }
84 |
85 | .icon .line{
86 | background-color: #5290f9;
87 | height: 2px;
88 | width: 20px;
89 | position: absolute;
90 | top: 10px;
91 | left: 5px;
92 | transition: transform 0.6s linear;
93 | }
94 |
95 | .icon .line2{
96 | top: auto;
97 | bottom: 10px;
98 | }
99 |
100 | nav.active .icon .line1{
101 | transform: rotate(-765deg) translateY(5.5px);
102 | }
103 |
104 | nav.active .icon .line2{
105 | transform: rotate(765deg) translateY(-5.5px);
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/015-increment-counter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Increment Counter
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
Twitter Follower
29 |
30 |
31 |
32 |
33 |
34 |
Youtube Subscriber
35 |
36 |
37 |
38 |
39 |
40 |
Facebook Follower
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/015-increment-counter/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/015-increment-counter/output.gif
--------------------------------------------------------------------------------
/015-increment-counter/script.js:
--------------------------------------------------------------------------------
1 | const counters = document.querySelectorAll(".counter");
2 |
3 | counters.forEach((counter) => {
4 | counter.innerText = "0";
5 |
6 | const updateCounter = () => {
7 | const target = +counter.getAttribute("data-target");
8 | const c = +counter.innerText;
9 |
10 | const increment = target / 200;
11 |
12 | if(c < target){
13 | counter.innerText = `${Math.ceil(c + increment)}`;
14 | setTimeout(updateCounter, 1);
15 | }else{
16 | counter.innerText = target;
17 | }
18 | };
19 |
20 | updateCounter();
21 | });
22 |
--------------------------------------------------------------------------------
/015-increment-counter/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #8e44ad;
9 | color: white;
10 | font-family: 'Roboto Mono', monospace;
11 | display: flex;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | .counter-container{
20 | display: flex;
21 | flex-direction: column;
22 | align-items: center;
23 | justify-content: center;
24 | text-align: center;
25 | margin: 30px 50px;
26 | }
27 |
28 | .counter{
29 | font-size: 60px;
30 | margin-top: 10px;
31 | }
32 |
33 | @media (max-width: 700px) {
34 | body{
35 | flex-direction: column;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/016-drink-water/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Drink Water
21 |
22 |
23 |
24 |
25 | Drink Water
26 | Goal: 2 Liters
27 |
28 |
29 |
30 |
31 | Remained
32 |
33 |
34 |
35 |
36 | Select how many glasses of water that you have drink
37 |
38 |
39 |
250 ml
40 |
250 ml
41 |
250 ml
42 |
250 ml
43 |
250 ml
44 |
250 ml
45 |
250 ml
46 |
250 ml
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/016-drink-water/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/016-drink-water/output.gif
--------------------------------------------------------------------------------
/016-drink-water/script.js:
--------------------------------------------------------------------------------
1 | const smallCups = document.querySelectorAll(".cup-small");
2 | const liters = document.getElementById("liters");
3 | const percentage = document.getElementById("percentage");
4 | const remained = document.getElementById("remained");
5 |
6 | updateBigCup();
7 |
8 | smallCups.forEach((cup, idx) => {
9 | cup.addEventListener("click", () => highlightCups(idx));
10 | });
11 |
12 | function highlightCups(idx) {
13 | if (idx != smallCups.length - 1) {
14 | if (
15 | smallCups[idx].classList.contains("full") &&
16 | !smallCups[idx].nextElementSibling.classList.contains("full")
17 | ) {
18 | idx--;
19 | }
20 | }
21 |
22 | smallCups.forEach((cup, idx2) => {
23 | if (idx2 <= idx) {
24 | cup.classList.add("full");
25 | } else {
26 | cup.classList.remove("full");
27 | }
28 | });
29 |
30 | updateBigCup();
31 | }
32 |
33 | function updateBigCup() {
34 | const fullCups = document.querySelectorAll(".cup-small.full").length;
35 | const totalCups = smallCups.length;
36 |
37 | if (fullCups == 0) {
38 | percentage.style.visibility = "hidden";
39 | percentage.style.height = 0;
40 | } else {
41 | percentage.style.visibility = "visible";
42 | percentage.style.height = `${(fullCups / totalCups) * 330}px`;
43 | percentage.innerText = `${(fullCups / totalCups) * 100}%`;
44 | }
45 |
46 | if (fullCups === totalCups) {
47 | remained.style.visibility = "hidden";
48 | remained.style.height = 0;
49 | } else {
50 | remained.style.visibility = "visible";
51 | liters.innerText = `${2 - (250 * fullCups) / 1000} L`;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/016-drink-water/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap');
2 |
3 | :root{
4 | --border-color: #144fc6;
5 | --fill-color: #6ab3f8;
6 | }
7 |
8 | * {
9 | box-sizing: border-box;
10 | }
11 |
12 | body {
13 | background-color: #3494e4;
14 | color: #fff;
15 | font-family: "Montserrat", sans-serif;
16 | display: flex;
17 | flex-direction: column;
18 | align-items: center;
19 | margin-bottom: 40px;
20 | }
21 |
22 | h1{
23 | margin: 10px 0 0;
24 | }
25 |
26 | h3{
27 | font-weight: 400;
28 | margin: 10px 0;
29 | }
30 |
31 | .cup{
32 | background-color: white;
33 | border: 4px solid var(--border-color);
34 | color: var(--border-color);
35 | border-radius: 0 0 40px 40px;
36 | height: 330px;
37 | width: 150px;
38 | margin: 30px 0;
39 | display: flex;
40 | flex-direction: column;
41 | overflow: hidden;
42 | }
43 |
44 | .cup.cup-small{
45 | width: 50px;
46 | height: 95px;
47 | border-radius: 0 0 15px 15px;
48 | background-color: rgba(255, 255, 255, 0.9);
49 | cursor: pointer;
50 | font-size: 14px;
51 | align-items: center;
52 | justify-content: center;
53 | text-align: center;
54 | margin: 5px;
55 | transition: all 0.3s ease;
56 | }
57 |
58 | .cup.cup-small.full{
59 | background-color: var(--fill-color);
60 | color: white;
61 | }
62 |
63 | .cups{
64 | display: flex;
65 | flex-wrap: wrap;
66 | width: 280px;
67 | justify-content: center;
68 | align-content: center;
69 | }
70 |
71 | .remained{
72 | display: flex;
73 | flex-direction: column;
74 | align-items: center;
75 | justify-content: center;
76 | text-align: center;
77 | flex: 1;
78 | transition: all 0.3s ease;
79 | }
80 |
81 | .remained span{
82 | font-size: 20px;
83 | font-weight: bold;
84 | }
85 |
86 | .remained small{
87 | font-size: 12px;
88 | }
89 |
90 | .percentage{
91 | background-color: var(--fill-color);
92 | font-size: 30px;
93 | display: flex;
94 | align-items: center;
95 | justify-content: center;
96 | font-weight: bold;
97 | font-size: 30px;
98 | height: 0;
99 | transition: 0.3s ease;
100 | }
101 |
102 | .text{
103 | text-align: center;
104 | margin: 0 0 5px;
105 | }
--------------------------------------------------------------------------------
/017-movie-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Movie App
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/017-movie-app/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/017-movie-app/output.gif
--------------------------------------------------------------------------------
/017-movie-app/script.js:
--------------------------------------------------------------------------------
1 | const API_URL =
2 | "https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=3fd2be6f0c70a2a598f084ddfb75487c&page=1";
3 | const IMG_PATH = "https://image.tmdb.org/t/p/w1280";
4 | const SEARCH_API =
5 | 'https://api.themoviedb.org/3/search/movie?api_key=3fd2be6f0c70a2a598f084ddfb75487c&query="';
6 |
7 | const form = document.getElementById("form");
8 | const search = document.getElementById("search");
9 | const main = document.getElementById("main");
10 |
11 | getMovies(API_URL);
12 |
13 | async function getMovies(url) {
14 | const res = await fetch(url);
15 | const data = await res.json();
16 | console.log(data.results);
17 | showMovies(data.results);
18 | }
19 |
20 | form.addEventListener("submit", (e) => {
21 | e.preventDefault();
22 |
23 | const searchTerm = search.value;
24 |
25 | if (searchTerm && searchTerm !== "") {
26 | getMovies(SEARCH_API + searchTerm);
27 | search.value = "";
28 | } else {
29 | window.location.reload();
30 | }
31 | });
32 |
33 | function showMovies(movies) {
34 | main.innerHTML = "";
35 | movies.forEach((movie) => {
36 | const { title, poster_path, vote_average, overview } = movie;
37 | const movieEl = document.createElement("div");
38 | movieEl.classList.add("movie");
39 |
40 | movieEl.innerHTML = `
41 |
42 |
43 |
${title}
44 | ${vote_average}
45 |
46 |
47 | ${title}
48 |
Overview
49 | ${overview}
50 |
51 | `;
52 |
53 | main.appendChild(movieEl);
54 | });
55 | }
56 |
57 | function getClassByRate(vote) {
58 | if (vote >= 8) {
59 | return "green";
60 | } else if (vote >= 5) {
61 | return "orange";
62 | } else {
63 | return "red";
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/017-movie-app/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins&display=swap");
2 | :root {
3 | --primary-color: #22254b;
4 | --secondary-color: #373b69;
5 | }
6 |
7 | * {
8 | box-sizing: border-box;
9 | }
10 |
11 | body {
12 | background-color: var(--primary-color);
13 | font-family: "Poppins", sans-serif;
14 | margin: 0;
15 | }
16 |
17 | header {
18 | padding: 1rem;
19 | display: flex;
20 | justify-content: flex-end;
21 | background-color: var(--secondary-color);
22 | }
23 |
24 | .search {
25 | background-color: transparent;
26 | border: 2px solid var(--primary-color);
27 | border-radius: 50px;
28 | font-family: inherit;
29 | font-size: 1rem;
30 | padding: 0.5rem 1rem;
31 | color: white;
32 | }
33 |
34 | .search::placeholder {
35 | color: #7378c5;
36 | }
37 |
38 | .search:focus {
39 | outline: none;
40 | background-color: var(--primary-color);
41 | }
42 |
43 | main {
44 | display: flex;
45 | justify-content: center;
46 | align-items: center;
47 | flex-wrap: wrap;
48 | gap: 1rem;
49 | padding: 2rem;
50 | }
51 |
52 | .movie {
53 | width: 300px;
54 | height: 600px;
55 | background-color: var(--secondary-color);
56 | box-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
57 | overflow: hidden;
58 | position: relative;
59 | border-radius: 3px;
60 | cursor: pointer;
61 | }
62 |
63 | .movie img {
64 | width: 100%;
65 | }
66 |
67 | .movie-info {
68 | color: #eee;
69 | display: flex;
70 | align-items: center;
71 | justify-content: space-between;
72 | padding: 0.5rem 1rem 1rem;
73 | letter-spacing: 0.5px;
74 | }
75 |
76 | .movie-info span {
77 | background-color: var(--primary-color);
78 | padding: 0.25rem;
79 | border-radius: 3px;
80 | font-weight: bold;
81 | }
82 |
83 | .movie-info span.green {
84 | color: greenyellow;
85 | }
86 |
87 | .movie-info span.orange {
88 | color: orange;
89 | }
90 |
91 | .movie-info span.red {
92 | color: red;
93 | }
94 |
95 | .overview {
96 | background-color: #fff;
97 | padding: 2rem;
98 | position: absolute;
99 | left: 0;
100 | bottom: 0;
101 | right: 0;
102 | max-height: 100%;
103 | transform: translateY(101%);
104 | transition: transform 0.3s ease-in;
105 | }
106 |
107 | .movie:hover .overview {
108 | transform: translateY(0);
109 | }
110 |
--------------------------------------------------------------------------------
/018-background-slider/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Background Slider
21 |
22 |
23 |
24 |
25 |
28 |
31 |
32 |
35 |
36 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/018-background-slider/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/018-background-slider/output.gif
--------------------------------------------------------------------------------
/018-background-slider/script.js:
--------------------------------------------------------------------------------
1 |
2 | const body = document.body;
3 | const slides = document.querySelectorAll(".slide");
4 | const leftBtn = document.getElementById("left");
5 | const rightBtn = document.getElementById("right");
6 |
7 | let activeSlide = 0;
8 |
9 | rightBtn.addEventListener("click", () => {
10 | activeSlide++;
11 |
12 | if (activeSlide > slides.length - 1) {
13 | activeSlide = 0;
14 | }
15 |
16 | setBgToBody();
17 | setActiveSlide();
18 | });
19 |
20 | leftBtn.addEventListener("click", () => {
21 | activeSlide--;
22 |
23 | if (activeSlide < 0) {
24 | activeSlide = slides.length - 1;
25 | }
26 |
27 | setBgToBody();
28 | setActiveSlide();
29 | });
30 |
31 | setBgToBody();
32 |
33 | function setBgToBody() {
34 | body.style.backgroundImage = slides[activeSlide].style.backgroundImage;
35 | }
36 |
37 | function setActiveSlide() {
38 | slides.forEach((slide) => slide.classList.remove("active"));
39 |
40 | slides[activeSlide].classList.add("active");
41 | }
--------------------------------------------------------------------------------
/018-background-slider/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: 'Roboto', sans-serif;
9 | display: flex;
10 | flex-direction: column;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | background-position: center center;
17 | background-size: cover;
18 | transition: 0.4s;
19 | }
20 |
21 | body::before {
22 | content: '';
23 | position: absolute;
24 | top: 0;
25 | left: 0;
26 | width: 100%;
27 | height: 100vh;
28 | background-color: rgba(0, 0, 0, 0.7);
29 | z-index: -1;
30 | }
31 |
32 | .slider-container {
33 | box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
34 | height: 70vh;
35 | width: 70vw;
36 | position: relative;
37 | overflow: hidden;
38 | }
39 |
40 | .slide {
41 | opacity: 0;
42 | height: 100vh;
43 | width: 100vw;
44 | background-position: center center;
45 | background-size: cover;
46 | position: absolute;
47 | top: -15vh;
48 | left: -15vw;
49 | transition: 0.4s ease;
50 | z-index: 1;
51 | }
52 |
53 | .slide.active {
54 | opacity: 1;
55 | }
56 |
57 | .arrow {
58 | position: fixed;
59 | background-color: transparent;
60 | color: #fff;
61 | padding: 20px;
62 | font-size: 30px;
63 | border: 2px solid orange;
64 | top: 50%;
65 | transform: translateY(-50%);
66 | cursor: pointer;
67 | }
68 |
69 | .arrow:focus {
70 | outline: 0;
71 | }
72 |
73 | .left-arrow {
74 | left: calc(15vw - 65px);
75 | }
76 |
77 | .right-arrow {
78 | right: calc(15vw - 65px);
79 | }
--------------------------------------------------------------------------------
/019-theme-clock/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Theme Clock
21 |
22 |
23 |
24 |
25 | Dark Mode
26 |
27 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/019-theme-clock/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/019-theme-clock/output.gif
--------------------------------------------------------------------------------
/019-theme-clock/script.js:
--------------------------------------------------------------------------------
1 | const hourEl = document.querySelector(".hour");
2 | const minuteEl = document.querySelector(".minute");
3 | const secondEl = document.querySelector(".second");
4 | const timeEl = document.querySelector(".time");
5 | const dateEl = document.querySelector(".date");
6 | const toggle = document.querySelector(".toggle");
7 |
8 | const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
9 |
10 | const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
11 |
12 | toggle.addEventListener("click", (e) => {
13 | const html = document.querySelector("html");
14 | if (html.classList.contains("dark")) {
15 | html.classList.remove("dark");
16 | e.target.innerHTML = "Dark Mode";
17 | } else {
18 | html.classList.add("dark");
19 | e.target.innerHTML = "Light Mode";
20 | }
21 | });
22 |
23 | function setTime() {
24 | const time = new Date();
25 | const month = time.getMonth();
26 | const day = time.getDay();
27 | const date = time.getDate();
28 | const hours = time.getHours();
29 | const hoursForClock = hours % 12;
30 | const minutes = time.getMinutes();
31 | const seconds = time.getSeconds();
32 | const ampm = hours >= 12 ? "PM" : "AM";
33 |
34 | hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 11, 0, 360)}deg)`;
35 | minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 59, 0, 360)}deg)`;
36 | secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 59, 0, 360)}deg)`;
37 |
38 | timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minuteEl}` : minutes} ${ampm}`;
39 | dateEl.innerHTML = `${days[day]}, ${months[month]} ${date} `;
40 |
41 | }
42 |
43 | const scale = (num, in_min, in_max, out_min, out_max) => {
44 | return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min;
45 | };
46 |
47 | setInterval(setTime, 1000);
48 |
--------------------------------------------------------------------------------
/020-button-ripple-effect/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Button Ripple Effect
21 |
22 |
23 |
24 |
25 |
26 | Click Me
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/020-button-ripple-effect/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/020-button-ripple-effect/output.gif
--------------------------------------------------------------------------------
/020-button-ripple-effect/script.js:
--------------------------------------------------------------------------------
1 | const buttons = document.querySelectorAll(".ripple");
2 |
3 | buttons.forEach((button) => {
4 | button.addEventListener("click", function (e) {
5 | const x = e.clientX;
6 | const y = e.clientY;
7 |
8 | const buttonTop = e.target.offsetTop;
9 | const buttonLeft = e.target.offsetLeft;
10 |
11 | const xInside = x - buttonLeft;
12 | const yInside = y - buttonTop;
13 |
14 | const circle = document.createElement("span");
15 | circle.classList.add("circle");
16 | circle.style.top = yInside + "px";
17 | circle.style.left = xInside + "px";
18 |
19 | this.appendChild(circle);
20 |
21 | setTimeout(() => circle.remove(), 5000);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/020-button-ripple-effect/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #000;
9 | font-family: "Mulish", sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | button {
20 | background-color: purple;
21 | color: white;
22 | border: 1px purple solid;
23 | font-size: 14px;
24 | text-transform: uppercase;
25 | letter-spacing: 2px;
26 | padding: 20px 30px;
27 | overflow: hidden;
28 | margin: 10px 0;
29 | cursor: pointer;
30 | position: relative;
31 | }
32 |
33 | button:focus {
34 | outline: none;
35 | }
36 |
37 | button .circle {
38 | position: absolute;
39 | background-color: white;
40 | width: 100px;
41 | height: 100px;
42 | border-radius: 50%;
43 | transform: translate(-50%, -50%) scale(0);
44 | animation: scale 0.5s ease-out;
45 | }
46 |
47 | @keyframes scale {
48 | to {
49 | transform: translate(-50%, -50%) scale(3);
50 | opacity: 0;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/021-drag-n-drop/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Drag N Drop
21 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/021-drag-n-drop/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/021-drag-n-drop/output.gif
--------------------------------------------------------------------------------
/021-drag-n-drop/script.js:
--------------------------------------------------------------------------------
1 | const fill = document.querySelector(".fill");
2 | const empties = document.querySelectorAll(".empty");
3 |
4 | fill.addEventListener("dragstart", dragStart);
5 | fill.addEventListener("dragend", dragEnd);
6 |
7 | for (const empty of empties) {
8 | empty.addEventListener("dragover", dragOver);
9 | empty.addEventListener("dragenter", dragEnter);
10 | empty.addEventListener("dragleave", dragleave);
11 | empty.addEventListener("drop", dragDrop);
12 | }
13 |
14 | function dragStart() {
15 | this.className += " hold";
16 | setTimeout(() => (this.className = ""), 0);
17 | }
18 |
19 | function dragEnd() {
20 | this.className = "fill";
21 | }
22 |
23 | function dragOver(e) {
24 | e.preventDefault();
25 | }
26 |
27 | function dragEnter(e) {
28 | e.preventDefault();
29 | this.className += " hovered";
30 | }
31 |
32 | function dragleave() {
33 | this.className = "empty";
34 | }
35 |
36 | function dragDrop() {
37 | this.className = "empty";
38 | this.append(fill);
39 | }
40 |
--------------------------------------------------------------------------------
/021-drag-n-drop/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | background-color: steelblue;
7 | display: flex;
8 | align-items: center;
9 | justify-content: center;
10 | height: 100vh;
11 | overflow: hidden;
12 | margin: 0;
13 | }
14 |
15 | .empty {
16 | height: 150px;
17 | width: 150px;
18 | margin: 10px;
19 | border: solid 3px black;
20 | background: white;
21 | }
22 |
23 | .fill {
24 | background-image: url("https://source.unsplash.com/random/150x150");
25 | height: 145px;
26 | width: 145px;
27 | cursor: pointer;
28 | }
29 |
30 | .hold {
31 | border: solid 5px #ccc;
32 | }
33 |
34 | .hovered {
35 | background-color: #333;
36 | border-color: #fff;
37 | border-style: dashed;
38 | }
39 |
40 | @media (max-width: 800px) {
41 | body {
42 | flex-direction: column;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/022-drawing-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Drawing App
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | -
29 | 6
30 | +
31 |
32 | X
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/022-drawing-app/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/022-drawing-app/output.gif
--------------------------------------------------------------------------------
/022-drawing-app/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #f5f5f5;
9 | font-family: "Mulish", sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | margin: 0;
16 | }
17 |
18 | canvas {
19 | border: 2px solid steelblue;
20 | cursor: crosshair;
21 | }
22 |
23 | .toolbox {
24 | background-color: steelblue;
25 | display: flex;
26 | width: fit-content;
27 | justify-content: center;
28 | align-items: center;
29 | gap: 0.5rem;
30 | border-radius: 50px;
31 | padding: 1rem;
32 | margin: 5px;
33 | }
34 |
35 | .toolbox > * {
36 | background-color: white;
37 | border: none;
38 | display: inline-flex;
39 | align-items: center;
40 | justify-content: center;
41 | font-size: 1.5rem;
42 | height: 40px;
43 | width: 40px;
44 | padding: 0.25rem;
45 | border-radius: 50%;
46 | outline: none;
47 | cursor: pointer;
48 | }
49 |
50 | input[type="color"]::-webkit-color-swatch-wrapper,
51 | input[type="color"]::-webkit-color-swatch {
52 | border: none;
53 | }
54 |
55 | input[type="color"]::-moz-color-swatch {
56 | border: none;
57 | }
58 |
59 | input[type="color"] {
60 | border: none;
61 | outline: none;
62 | }
63 |
--------------------------------------------------------------------------------
/023-kinetic-css-loader/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Kinetic CSS Loader
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/023-kinetic-css-loader/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/023-kinetic-css-loader/output.gif
--------------------------------------------------------------------------------
/023-kinetic-css-loader/script.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/023-kinetic-css-loader/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | background-color: #2c3e50;
7 | display: flex;
8 | align-items: center;
9 | justify-content: center;
10 | height: 100vh;
11 | overflow: hidden;
12 | margin: 0;
13 | }
14 |
15 | .kinetic {
16 | position: relative;
17 | height: 80px;
18 | width: 80px;
19 | }
20 |
21 | .kinetic::after,
22 | .kinetic::before {
23 | content: "";
24 | position: absolute;
25 | top: 0;
26 | left: 0;
27 | width: 0;
28 | height: 0;
29 | border: 50px solid transparent;
30 | border-bottom-color: white;
31 | animation: rotateA 2s linear infinite 0.5s;
32 | }
33 |
34 | .kinetic::before {
35 | transform: rotate(90deg);
36 | animation: rotateB 2s linear infinite;
37 | }
38 |
39 | @keyframes rotateA {
40 | 0%,
41 | 25% {
42 | transform: rotate(0deg);
43 | }
44 |
45 | 50%,
46 | 75% {
47 | transform: rotate(180deg);
48 | }
49 |
50 | 100% {
51 | transform: rotate(360deg);
52 | }
53 | }
54 |
55 | @keyframes rotateB {
56 | 0%,
57 | 25% {
58 | transform: rotate(90deg);
59 | }
60 |
61 | 50%,
62 | 75% {
63 | transform: rotate(270deg);
64 | }
65 |
66 | 100% {
67 | transform: rotate(450deg);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/024-content-placeholder/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Content Placeholder
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 |
--------------------------------------------------------------------------------
/024-content-placeholder/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/024-content-placeholder/output.gif
--------------------------------------------------------------------------------
/024-content-placeholder/script.js:
--------------------------------------------------------------------------------
1 | const header = document.getElementById("header");
2 | const title = document.getElementById("title");
3 | const excerpt = document.getElementById("excerpt");
4 | const profile_img = document.getElementById("profile_img");
5 | const name = document.getElementById("name");
6 | const date = document.getElementById("date");
7 |
8 | const animated_bgs = document.querySelectorAll(".animated-bg");
9 | const animated_bg_texts = document.querySelectorAll(".animated-bg-text");
10 |
11 | setTimeout(getData, 2500);
12 |
13 | function getData() {
14 | header.innerHTML =
15 | ' ';
16 | title.innerHTML = "Lorem ipsum dolor sit amet";
17 | excerpt.innerHTML =
18 | "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolore perferendis";
19 | profile_img.innerHTML =
20 | ' ';
21 | name.innerHTML = "John Doe";
22 | date.innerHTML = "Oct 08, 2020";
23 |
24 | animated_bgs.forEach((bg) => bg.classList.remove("animated-bg"));
25 | animated_bg_texts.forEach((bg) => bg.classList.remove("animated-bg-text"));
26 | }
27 |
--------------------------------------------------------------------------------
/024-content-placeholder/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Mulish&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #ecf0f1;
9 | font-family: "Mulish", sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
18 | img {
19 | max-width: 100%;
20 | }
21 |
22 | .card {
23 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
24 | border-radius: 10px;
25 | overflow: hidden;
26 | width: 350px;
27 | }
28 |
29 | .card-header {
30 | height: 200px;
31 |
32 | }
33 |
34 | .card-header img{
35 | object-fit: cover;
36 | height: 100%;
37 | width: 100%;
38 | }
39 |
40 | .card-content{
41 | background-color: #fff;
42 | padding: 30px;
43 | }
44 |
45 | .card-title{
46 | height: 20px;
47 | margin: 0;
48 | }
49 |
50 | .card-excerpt{
51 | color: #777;
52 | margin: 10px 0 20px;
53 | }
54 |
55 | .author{
56 | display: flex;
57 | }
58 |
59 | .profile-img{
60 | border-radius: 50%;
61 | overflow: hidden;
62 | height: 40px;
63 | width: 40px;
64 | }
65 |
66 | .author-info{
67 | display: flex;
68 | flex-direction: column;
69 | justify-content: space-around;
70 | margin-left: 10px;
71 | width: 100px;
72 | }
73 |
74 | .author-info small{
75 | color: #aaa;
76 | margin-top: 5px;
77 | }
78 |
79 | .animated-bg {
80 | background-image: linear-gradient(
81 | to right,
82 | #f6f7f8 0%,
83 | #edeef1 10%,
84 | #f6f7f8 20%,
85 | #f6f7f8 100%
86 | );
87 | background-size: 200% 100%;
88 | animation: bgPos 1s linear infinite;
89 | }
90 |
91 | .animated-bg-text {
92 | border-radius: 50px;
93 | display: inline-block;
94 | margin: 0;
95 | height: 10px;
96 | width: 100%;
97 | }
98 |
99 | @keyframes bgPos {
100 | 0% {
101 | background-position: 50% 0;
102 | }
103 |
104 | 100% {
105 | background-position: -150% 0;
106 | }
107 | }
--------------------------------------------------------------------------------
/025-sticky-navbar/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/025-sticky-navbar/output.gif
--------------------------------------------------------------------------------
/025-sticky-navbar/script.js:
--------------------------------------------------------------------------------
1 | const nav = document.querySelector(".nav");
2 | window.addEventListener("scroll", fixNav);
3 |
4 | function fixNav() {
5 | if (window.scrollY > nav.offsetHeight + 150) {
6 | nav.classList.add("active");
7 | } else {
8 | nav.classList.remove("active");
9 | }
10 | }
--------------------------------------------------------------------------------
/025-sticky-navbar/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Open+Sans&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | body {
10 | font-family: "Open Sans", sans-serif;
11 | color: #222;
12 | padding-bottom: 50px;
13 | }
14 |
15 | .container {
16 | max-width: 1200px;
17 | margin: 0 auto;
18 | }
19 |
20 | .nav {
21 | position: fixed;
22 | background-color: #222;
23 | top: 0;
24 | left: 0;
25 | right: 0;
26 | transition: all 0.3s ease-in-out;
27 | }
28 |
29 | .nav .container {
30 | display: flex;
31 | justify-content: space-between;
32 | align-items: center;
33 | padding: 20px 0;
34 | transition: all 0.3s ease-in-out;
35 | }
36 |
37 | .nav ul {
38 | display: flex;
39 | list-style-type: none;
40 | align-items: center;
41 | justify-content: center;
42 | }
43 |
44 | .nav a {
45 | color: #fff;
46 | text-decoration: none;
47 | padding: 7px 15px;
48 | transition: all 0.3s ease-in-out;
49 | }
50 |
51 | .nav.active {
52 | background-color: #fff;
53 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
54 | }
55 |
56 | .nav.active a {
57 | color: #000;
58 | }
59 |
60 | .nav.active .container {
61 | padding: 10px 0;
62 | }
63 |
64 | .nav a.current,
65 | .nav a:hover {
66 | color: #c0392b;
67 | font-weight: bold;
68 | }
69 |
70 | .hero {
71 | background-image: url("https://images.pexels.com/photos/450035/pexels-photo-450035.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260");
72 | background-repeat: no-repeat;
73 | background-size: cover;
74 | background-position: bottom center;
75 | height: 100vh;
76 | color: #fff;
77 | display: flex;
78 | justify-content: center;
79 | align-items: center;
80 | text-align: center;
81 | position: relative;
82 | margin-bottom: 20px;
83 | z-index: -2;
84 | }
85 |
86 | .hero::before {
87 | content: "";
88 | position: absolute;
89 | top: 0;
90 | left: 0;
91 | height: 100%;
92 | width: 100%;
93 | background-color: rgba(0, 0, 0, 0.6);
94 | z-index: -1;
95 | }
96 |
97 | .hero h1 {
98 | font-size: 46px;
99 | margin: -20px 0 20px;
100 | }
101 |
102 | .hero p {
103 | font-size: 20px;
104 | letter-spacing: 1px;
105 | }
106 |
107 | .content h2, .content h3 {
108 | font-size: 150%;
109 | margin: 20px 0;
110 | }
111 |
112 | .content p{
113 | color: #555;
114 | line-height: 30px;
115 | letter-spacing: 1.2px;
116 | }
--------------------------------------------------------------------------------
/026-vertical-slider/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Vertical Slider
21 |
22 |
23 |
24 |
25 |
26 |
27 |
Nature flower
28 |
all in pink
29 |
30 |
31 |
Bluuue Sky
32 |
with it's mountains
33 |
34 |
35 |
Lonely castle
36 |
in the wilderness
37 |
38 |
39 |
Flying eagle
40 |
in the sunset
41 |
42 |
43 |
44 |
46 |
47 |
49 |
50 |
52 |
53 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/026-vertical-slider/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/026-vertical-slider/output.gif
--------------------------------------------------------------------------------
/026-vertical-slider/script.js:
--------------------------------------------------------------------------------
1 | const sliderContainer = document.querySelector(".slider-container");
2 | const rightSlide = document.querySelector(".right-slide");
3 | const leftSlide = document.querySelector(".left-slide");
4 | const upButton = document.querySelector(".up-button");
5 | const downButton = document.querySelector(".down-button");
6 | const slidesLength = rightSlide.querySelectorAll("div").length;
7 |
8 | let activeSlideIndex = 0;
9 |
10 | leftSlide.style.top = `-${(slidesLength - 1) * 100}vh`;
11 |
12 | upButton.addEventListener("click", () => changeSlide("up"));
13 | downButton.addEventListener("click", () => changeSlide("down"));
14 |
15 | const changeSlide = (direction) => {
16 | const sliderHeight = sliderContainer.clientHeight;
17 | if (direction === "up") {
18 | activeSlideIndex++;
19 | if (activeSlideIndex > slidesLength - 1) {
20 | activeSlideIndex = 0;
21 | }
22 | } else if (direction === "down") {
23 | activeSlideIndex--;
24 | if (activeSlideIndex < 0) {
25 | activeSlideIndex = slidesLength - 1;
26 | }
27 | }
28 | rightSlide.style.transform = `translateY(-${
29 | activeSlideIndex * sliderHeight
30 | }px)`;
31 | leftSlide.style.transform = `translateY(${
32 | activeSlideIndex * sliderHeight
33 | }px)`;
34 | };
35 |
--------------------------------------------------------------------------------
/026-vertical-slider/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Open+Sans&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | body {
10 | font-family: "Open Sans", sans-serif;
11 | height: 100vh;
12 | }
13 |
14 | .slider-container {
15 | position: relative;
16 | overflow: hidden;
17 | width: 100vw;
18 | height: 100vh;
19 | }
20 |
21 | .left-slide {
22 | height: 100%;
23 | width: 35%;
24 | position: absolute;
25 | top: 0;
26 | left: 0;
27 | transition: all 0.5s ease-in-out;
28 | }
29 |
30 | .left-slide > div {
31 | height: 100%;
32 | width: 100%;
33 | display: flex;
34 | flex-direction: column;
35 | justify-content: center;
36 | align-items: center;
37 | text-align: center;
38 | color: white;
39 | }
40 |
41 | .left-slide h1 {
42 | font-size: 40px;
43 | margin-bottom: 10px;
44 | margin-top: -30px;
45 | }
46 |
47 | .right-slide {
48 | height: 100%;
49 | position: absolute;
50 | top: 0;
51 | left: 35%;
52 | width: 65%;
53 | transition: all 0.5s ease-in-out;
54 | }
55 |
56 | .right-slide > div {
57 | background-repeat: no-repeat;
58 | background-size: cover;
59 | background-position: center center;
60 | height: 100%;
61 | width: 100%;
62 | }
63 |
64 | button {
65 | background-color: #fff;
66 | border: none;
67 | color: #aaa;
68 | cursor: pointer;
69 | font-size: 16px;
70 | padding: 15px;
71 | }
72 |
73 | button:hover {
74 | color: #222;
75 | }
76 |
77 | button:focus {
78 | outline: none;
79 | }
80 |
81 | .slider-container .action-buttons button {
82 | position: absolute;
83 | left: 35%;
84 | top: 50%;
85 | z-index: 100;
86 | }
87 |
88 | .slider-container .action-buttons .down-button {
89 | transform: translateX(-100%);
90 | border-top-left-radius: 5px;
91 | border-bottom-left-radius: 5px;
92 | }
93 |
94 | .slider-container .action-buttons .up-button {
95 | transform: translateY(-100%);
96 | border-top-right-radius: 5px;
97 | border-bottom-right-radius: 5px;
98 | }
99 |
--------------------------------------------------------------------------------
/027-toast-notification/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Toast Notification
21 |
22 |
23 |
24 |
25 |
26 | Show Notification
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/027-toast-notification/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/027-toast-notification/output.gif
--------------------------------------------------------------------------------
/027-toast-notification/script.js:
--------------------------------------------------------------------------------
1 | const button = document.getElementById("button");
2 | const toasts = document.getElementById("toasts");
3 |
4 | const messages = [
5 | "Message One",
6 | "Message Two",
7 | "Message Three",
8 | "Message Four",
9 | ];
10 |
11 | const types = ["info", "success", "error"];
12 |
13 | button.addEventListener("click", () => createNotification());
14 |
15 | function createNotification(message = null, type = null) {
16 | const notif = document.createElement("div");
17 | notif.classList.add("toast");
18 | notif.classList.add(type ? type : getRandomType());
19 |
20 | notif.innerText = message ? message : getRandomMessage();
21 |
22 | toasts.appendChild(notif);
23 |
24 | setTimeout(() => {
25 | notif.remove();
26 | }, 3000);
27 | }
28 |
29 | function getRandomMessage() {
30 | return messages[Math.floor(Math.random() * messages.length)];
31 | }
32 |
33 | function getRandomType() {
34 | return types[Math.floor(Math.random() * types.length)];
35 | }
36 |
--------------------------------------------------------------------------------
/027-toast-notification/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: rebeccapurple;
9 | font-family: 'Poppins', sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | .btn {
20 | background-color: #ffffff;
21 | color: rebeccapurple;
22 | font-family: inherit;
23 | font-weight: bold;
24 | padding: 1rem;
25 | border-radius: 5px;
26 | border: none;
27 | cursor: pointer;
28 | }
29 |
30 | .btn:focus {
31 | outline: none;
32 | }
33 |
34 | .btn:active {
35 | transform: scale(0.98);
36 | }
37 |
38 | #toasts {
39 | position: fixed;
40 | bottom: 10px;
41 | right: 10px;
42 | display: flex;
43 | flex-direction: column;
44 | align-items: flex-end;
45 | }
46 |
47 | .toast {
48 | background-color: #fff;
49 | border-radius: 5px;
50 | padding: 1rem 2rem;
51 | margin: 0.5rem;
52 | }
53 |
54 | .toast.info {
55 | color: rebeccapurple;
56 | }
57 |
58 | .toast.success {
59 | color: green;
60 | }
61 |
62 | .toast.error {
63 | color: red;
64 | }
--------------------------------------------------------------------------------
/028-github-profiles/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | GitHub Profiles
21 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/028-github-profiles/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/028-github-profiles/output.gif
--------------------------------------------------------------------------------
/028-github-profiles/script.js:
--------------------------------------------------------------------------------
1 | const APIURL = "https://api.github.com/users/";
2 |
3 | const main = document.getElementById("main");
4 | const form = document.getElementById("form");
5 | const search = document.getElementById("search");
6 |
7 | async function getUser(username) {
8 | try {
9 | const { data } = await axios(APIURL + username);
10 | createUserCard(data);
11 | getRepos(username);
12 | } catch (err) {
13 | if (err.response.status == 404) {
14 | createErrorCard("No profile with this username");
15 | }
16 | }
17 | }
18 |
19 | async function getRepos(username) {
20 | try {
21 | const { data } = await axios(APIURL + username + "/repos?sort=created");
22 | addReposToCard(data);
23 | } catch (err) {
24 | createErrorCard("Problem fetching repos");
25 | }
26 | }
27 |
28 | function createUserCard(user) {
29 | const cardHTML = `
30 |
31 |
32 |
33 |
34 |
35 |
${user.name}
36 |
${user.bio}
37 |
38 | ${user.followers} Followers
39 | ${user.following} Following
40 | ${user.public_repos} Repos
41 |
42 |
43 |
44 |
45 |
46 | `;
47 | main.innerHTML = cardHTML;
48 | }
49 |
50 | function createErrorCard(msg) {
51 | const cardHTML = `
52 |
53 |
${msg}
54 |
55 | `;
56 |
57 | main.innerHTML = cardHTML;
58 | }
59 |
60 | function addReposToCard(repos) {
61 | const reposEl = document.getElementById("repos");
62 |
63 | repos.slice(0, 5).forEach((repo) => {
64 | const repoEl = document.createElement("a");
65 | repoEl.classList.add("repo");
66 | repoEl.href = repo.html_url;
67 | repoEl.target = "_blank";
68 | repoEl.innerText = repo.name;
69 |
70 | reposEl.appendChild(repoEl);
71 | });
72 | }
73 |
74 | form.addEventListener("submit", (e) => {
75 | e.preventDefault();
76 | const user = search.value;
77 | if (user) {
78 | getUser(user);
79 | search.value = "";
80 | }
81 | });
82 |
--------------------------------------------------------------------------------
/028-github-profiles/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #2a2a72;
9 | color: #fff;
10 | font-family: 'Poppins', sans-serif;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: center;
15 | height: 100vh;
16 | overflow: hidden;
17 | margin: 0;
18 | }
19 |
20 | .user-form {
21 | width: 100%;
22 | max-width: 700px;
23 | }
24 |
25 | .user-form input {
26 | width: 100%;
27 | display: block;
28 | background-color: #4c2885;
29 | border: none;
30 | border-radius: 10px;
31 | color: #fff;
32 | padding: 1rem;
33 | margin-bottom: 2rem;
34 | font-family: inherit;
35 | font-size: 1rem;
36 | box-shadow: 0 5px 10px rgba(154, 160, 185, 0.05),
37 | 0 15px 40px rgba(0, 0, 0, 0.1);
38 | }
39 |
40 | .user-form input::placeholder {
41 | color: #bbb;
42 | }
43 |
44 | .user-form input:focus {
45 | outline: none;
46 | }
47 |
48 | .card {
49 | max-width: 800px;
50 | background-color: #4c2885;
51 | border-radius: 20px;
52 | box-shadow: 0 5px 10px rgba(154, 160, 185, 0.05),
53 | 0 15px 40px rgba(0, 0, 0, 0.1);
54 | display: flex;
55 | padding: 3rem;
56 | margin: 0 1.5rem;
57 | }
58 |
59 | .avatar {
60 | border-radius: 50%;
61 | border: 10px solid #2a2a72;
62 | height: 150px;
63 | width: 150px;
64 | }
65 |
66 | .user-info {
67 | color: #eee;
68 | margin-left: 2rem;
69 | }
70 |
71 | .user-info h2 {
72 | margin-top: 0;
73 | }
74 |
75 | .user-info ul {
76 | list-style-type: none;
77 | display: flex;
78 | justify-content: space-between;
79 | padding: 0;
80 | max-width: 400px;
81 | }
82 |
83 | .user-info ul li {
84 | display: flex;
85 | align-items: center;
86 | }
87 |
88 | .user-info ul li strong {
89 | font-size: 0.9rem;
90 | margin-left: 0.5rem;
91 | }
92 |
93 | .repo {
94 | text-decoration: none;
95 | color: #fff;
96 | background-color: #212a72;
97 | font-size: 0.7rem;
98 | padding: 0.25rem 0.5rem;
99 | margin-right: 0.5rem;
100 | margin-bottom: 0.5rem;
101 | display: inline-block;
102 | }
103 |
104 | @media (max-width: 500px) {
105 | .card {
106 | flex-direction: column;
107 | align-items: center;
108 | }
109 |
110 | .user-form {
111 | max-width: 400px;
112 | }
113 | }
--------------------------------------------------------------------------------
/029-double-click-heart/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Double Click Heart
21 |
22 |
23 |
24 | Double click on the image to it
25 | You liked it 0 times
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/029-double-click-heart/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/029-double-click-heart/output.gif
--------------------------------------------------------------------------------
/029-double-click-heart/script.js:
--------------------------------------------------------------------------------
1 | const loveMe = document.querySelector('.loveMe')
2 | const times = document.querySelector('#times')
3 |
4 | let clickTime = 0
5 | let timesClicked = 0
6 |
7 | loveMe.addEventListener('click', (e) => {
8 | if(clickTime === 0) {
9 | clickTime = new Date().getTime()
10 | } else {
11 | if((new Date().getTime() - clickTime) < 800) {
12 | createHeart(e)
13 | clickTime = 0
14 | } else {
15 | clickTime = new Date().getTime()
16 | }
17 | }
18 | })
19 |
20 | const createHeart = (e) => {
21 | const heart = document.createElement('i')
22 | heart.classList.add('fas')
23 | heart.classList.add('fa-heart')
24 |
25 | const x = e.clientX
26 | const y = e.clientY
27 |
28 | const leftOffset = e.target.offsetLeft
29 | const topOffset = e.target.offsetTop
30 |
31 | const xInside = x - leftOffset
32 | const yInside = y - topOffset
33 |
34 | heart.style.top = `${yInside}px`
35 | heart.style.left = `${xInside}px`
36 |
37 | loveMe.appendChild(heart)
38 |
39 | times.innerHTML = ++timesClicked
40 |
41 | setTimeout(() => heart.remove(), 1000)
42 | }
--------------------------------------------------------------------------------
/029-double-click-heart/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Oswald');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: 'Oswald', sans-serif;
9 | text-align: center;
10 | overflow: hidden;
11 | margin: 0;
12 | }
13 |
14 | h3 {
15 | margin-bottom: 0;
16 | text-align: center;
17 | }
18 |
19 | small {
20 | display: block;
21 | margin-bottom: 20px;
22 | text-align: center;
23 | }
24 |
25 | .fa-heart {
26 | color: red;
27 | }
28 |
29 | .loveMe {
30 | height: 440px;
31 | width: 300px;
32 | background: url('https://images.unsplash.com/photo-1504215680853-026ed2a45def?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=334&q=80')
33 | no-repeat center center/cover;
34 | margin: auto;
35 | cursor: pointer;
36 | max-width: 100%;
37 | position: relative;
38 | box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
39 | }
40 |
41 | .loveMe .fa-heart {
42 | position: absolute;
43 | animation: grow 0.6s linear;
44 | transform: translate(-50%, -50%) scale(0);
45 | }
46 |
47 | @keyframes grow {
48 | to {
49 | transform: translate(-50%, -50%) scale(10);
50 | opacity: 0;
51 | }
52 | }
--------------------------------------------------------------------------------
/030-auto-text-effect/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Auto Text Effect
21 |
22 |
23 |
24 | Starting...
25 |
26 |
27 | Speed:
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/030-auto-text-effect/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/030-auto-text-effect/output.gif
--------------------------------------------------------------------------------
/030-auto-text-effect/script.js:
--------------------------------------------------------------------------------
1 | const textEl = document.getElementById('text')
2 | const speedEl = document.getElementById('speed')
3 | const text = 'We Love Programming!'
4 | let idx = 1
5 | let speed = 300 / speedEl.value
6 |
7 | writeText()
8 |
9 | function writeText() {
10 | textEl.innerText = text.slice(0, idx)
11 |
12 | idx++
13 |
14 | if(idx > text.length) {
15 | idx = 1
16 | }
17 |
18 | setTimeout(writeText, speed)
19 | }
20 |
21 |
22 | speedEl.addEventListener('input', (e) => speed = 300 / e.target.value)
--------------------------------------------------------------------------------
/030-auto-text-effect/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: darksalmon;
9 | font-family: 'Roboto', sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | div {
20 | position: absolute;
21 | bottom: 20px;
22 | background: rgba(0, 0, 0, 0.1);
23 | padding: 10px 20px;
24 | font-size: 18px;
25 | }
26 |
27 | input {
28 | width: 50px;
29 | padding: 5px;
30 | font-size: 18px;
31 | background-color: darksalmon;
32 | border: none;
33 | text-align: center;
34 | }
35 |
36 | input:focus {
37 | outline: none;
38 | }
--------------------------------------------------------------------------------
/031-random-password/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Random Password
21 |
22 |
23 |
24 |
25 |
Password Generator
26 |
27 |
28 |
29 |
30 |
31 |
32 |
54 |
55 |
56 | Generate Password
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/031-random-password/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/031-random-password/output.gif
--------------------------------------------------------------------------------
/031-random-password/script.js:
--------------------------------------------------------------------------------
1 | const resultEl = document.getElementById("result");
2 | const lengthEl = document.getElementById("length");
3 | const uppercaseEl = document.getElementById("uppercase");
4 | const lowercaseEl = document.getElementById("lowercase");
5 | const numbersEl = document.getElementById("numbers");
6 | const symbolsEl = document.getElementById("symbols");
7 | const generateEl = document.getElementById("generate");
8 | const clipboardEl = document.getElementById("clipboard");
9 |
10 | const randomFunc = {
11 | lower: getRandomLower,
12 | upper: getRandomUpper,
13 | number: getRandomNumber,
14 | symbol: getRandomSymbol,
15 | };
16 |
17 | clipboardEl.addEventListener("click", () => {
18 | const textarea = document.createElement("textarea");
19 | const password = resultEl.innerText;
20 |
21 | if (!password) {
22 | return;
23 | }
24 |
25 | textarea.value = password;
26 | document.body.appendChild(textarea);
27 | textarea.select();
28 | document.execCommand("copy");
29 | textarea.remove();
30 | alert("Password copied to clipboard!");
31 | });
32 |
33 | generateEl.addEventListener("click", () => {
34 | const length = +lengthEl.value;
35 | const hasLower = lowercaseEl.checked;
36 | const hasUpper = uppercaseEl.checked;
37 | const hasNumber = numbersEl.checked;
38 | const hasSymbol = symbolsEl.checked;
39 |
40 | resultEl.innerText = generatePassword(
41 | hasLower,
42 | hasUpper,
43 | hasNumber,
44 | hasSymbol,
45 | length
46 | );
47 | });
48 |
49 | function generatePassword(lower, upper, number, symbol, length) {
50 | let generatedPassword = "";
51 | const typesCount = lower + upper + number + symbol;
52 | const typesArr = [{ lower }, { upper }, { number }, { symbol }].filter(
53 | (item) => Object.values(item)[0]
54 | );
55 |
56 | if (typesCount === 0) {
57 | return "";
58 | }
59 |
60 | for (let i = 0; i < length; i += typesCount) {
61 | typesArr.forEach((type) => {
62 | const funcName = Object.keys(type)[0];
63 | generatedPassword += randomFunc[funcName]();
64 | });
65 | }
66 |
67 | const finalPassword = generatedPassword.slice(0, length);
68 |
69 | return finalPassword;
70 | }
71 |
72 | function getRandomLower() {
73 | return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
74 | }
75 |
76 | function getRandomUpper() {
77 | return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
78 | }
79 |
80 | function getRandomNumber() {
81 | return String.fromCharCode(Math.floor(Math.random() * 10) + 48);
82 | }
83 |
84 | function getRandomSymbol() {
85 | const symbols = "!@#$%^&*(){}[]=<>/,.";
86 | return symbols[Math.floor(Math.random() * symbols.length)];
87 | }
88 |
--------------------------------------------------------------------------------
/031-random-password/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #3b3b98;
9 | color: #fff;
10 | font-family: 'Muli', sans-serif;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: center;
15 | height: 100vh;
16 | overflow: hidden;
17 | padding: 10px;
18 | margin: 0;
19 | }
20 |
21 | h2 {
22 | margin: 10px 0 20px;
23 | text-align: center;
24 | }
25 |
26 | .container {
27 | background-color: #23235b;
28 | box-shadow: 0px 2px 10px rgba(255, 255, 255, 0.2);
29 | padding: 20px;
30 | width: 350px;
31 | max-width: 100%;
32 | }
33 |
34 | .result-container {
35 | background-color: rgba(0, 0, 0, 0.4);
36 | display: flex;
37 | justify-content: flex-start;
38 | align-items: center;
39 | position: relative;
40 | font-size: 18px;
41 | letter-spacing: 1px;
42 | padding: 12px 10px;
43 | height: 50px;
44 | width: 100%;
45 | }
46 |
47 | .result-container #result {
48 | word-wrap: break-word;
49 | max-width: calc(100% - 40px);
50 | }
51 |
52 | .result-container .btn {
53 | position: absolute;
54 | top: 5px;
55 | right: 5px;
56 | width: 40px;
57 | height: 40px;
58 | font-size: 20px;
59 | }
60 |
61 | .btn {
62 | border: none;
63 | background-color: #3b3b98;
64 | color: #fff;
65 | font-size: 16px;
66 | padding: 8px 12px;
67 | cursor: pointer;
68 | }
69 |
70 | .btn-large {
71 | display: block;
72 | width: 100%;
73 | }
74 |
75 | .setting {
76 | display: flex;
77 | justify-content: space-between;
78 | align-items: center;
79 | margin: 15px 0;
80 | }
--------------------------------------------------------------------------------
/032-good-cheap-fast/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Good, Cheap, Fast
21 |
22 |
23 |
24 |
25 | How do you want your project to be?
26 |
27 |
28 |
29 |
30 |
31 |
Good
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
Cheap
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
Fast
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/032-good-cheap-fast/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/032-good-cheap-fast/output.gif
--------------------------------------------------------------------------------
/032-good-cheap-fast/script.js:
--------------------------------------------------------------------------------
1 | const toggles = document.querySelectorAll(".toggle");
2 | const good = document.querySelector("#good");
3 | const cheap = document.querySelector("#cheap");
4 | const fast = document.querySelector("#fast");
5 |
6 | toggles.forEach((toggle) =>
7 | toggle.addEventListener("change", (e) => doTheTrick(e.target))
8 | );
9 |
10 | function doTheTrick(theClickedOne) {
11 | if (good.checked && cheap.checked && fast.checked) {
12 | if (good === theClickedOne) {
13 | fast.checked = false;
14 | }
15 |
16 | if (cheap === theClickedOne) {
17 | good.checked = false;
18 | }
19 |
20 | if (fast === theClickedOne) {
21 | cheap.checked = false;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/032-good-cheap-fast/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: "Roboto", sans-serif;
9 | display: flex;
10 | flex-direction: column;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
18 | .toggle-container {
19 | display: flex;
20 | align-items: center;
21 | margin: 10px 0;
22 | width: 200px;
23 | }
24 |
25 | .toggle {
26 | visibility: hidden;
27 | }
28 |
29 | .label {
30 | position: relative;
31 | background-color: #d0d0d0;
32 | border-radius: 50px;
33 | cursor: pointer;
34 | display: inline-block;
35 | margin: 0 15px 0;
36 | width: 80px;
37 | height: 40px;
38 | }
39 |
40 | .toggle:checked + .label {
41 | background-color: #8e44ad;
42 | }
43 |
44 | .ball {
45 | background: #fff;
46 | height: 34px;
47 | width: 34px;
48 | border-radius: 50%;
49 | position: absolute;
50 | top: 3px;
51 | left: 3px;
52 | align-items: center;
53 | justify-content: center;
54 | animation: slideOff 0.3s linear forwards;
55 | }
56 |
57 | .toggle:checked + .label .ball {
58 | animation: slideOn 0.3s linear forwards;
59 | }
60 |
61 | @keyframes slideOn {
62 | 0% {
63 | transform: translateX(0) scale(1);
64 | }
65 | 50% {
66 | transform: translateX(20px) scale(1.2);
67 | }
68 | 100% {
69 | transform: translateX(40px) scale(1);
70 | }
71 | }
72 |
73 | @keyframes slideOff {
74 | 0% {
75 | transform: translateX(40px) scale(1);
76 | }
77 | 50% {
78 | transform: translateX(20px) scale(1.2);
79 | }
80 | 100% {
81 | transform: translateX(0) scale(1);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/033-notes-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Notes App
21 |
22 |
23 |
24 |
25 | Add note
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/033-notes-app/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/033-notes-app/output.gif
--------------------------------------------------------------------------------
/033-notes-app/script.js:
--------------------------------------------------------------------------------
1 | const addBtn = document.getElementById("add");
2 |
3 | const notes = JSON.parse(localStorage.getItem("notes"));
4 |
5 | if (notes) {
6 | notes.forEach((note) => addNewNote(note));
7 | }
8 |
9 | addBtn.addEventListener("click", () => addNewNote());
10 |
11 | function addNewNote(text = "") {
12 | const note = document.createElement("div");
13 | note.classList.add("note");
14 |
15 | note.innerHTML = `
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | `;
24 |
25 | const editBtn = note.querySelector(".edit");
26 | const deleteBtn = note.querySelector(".delete");
27 | const main = note.querySelector(".main");
28 | const textArea = note.querySelector("textarea");
29 |
30 | textArea.value = text;
31 | main.innerHTML = marked(text);
32 |
33 | deleteBtn.addEventListener("click", () => {
34 | note.remove();
35 |
36 | updateLS();
37 | });
38 |
39 | editBtn.addEventListener("click", () => {
40 | main.classList.toggle("hidden");
41 | textArea.classList.toggle("hidden");
42 | });
43 |
44 | textArea.addEventListener("input", (e) => {
45 | const { value } = e.target;
46 |
47 | main.innerHTML = marked(value);
48 |
49 | updateLS();
50 | });
51 |
52 | document.body.appendChild(note);
53 | }
54 |
55 | function updateLS() {
56 | const notesText = document.querySelectorAll("textarea");
57 |
58 | const notes = [];
59 |
60 | notesText.forEach((note) => notes.push(note.value));
61 |
62 | localStorage.setItem("notes", JSON.stringify(notes));
63 | }
64 |
--------------------------------------------------------------------------------
/033-notes-app/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | outline: none;
6 | }
7 |
8 | body {
9 | background-color: #7bdaf3;
10 | font-family: "Poppins", sans-serif;
11 | display: flex;
12 | flex-wrap: wrap;
13 | margin: 0;
14 | padding-top: 3rem;
15 | }
16 |
17 | .add {
18 | position: fixed;
19 | top: 1rem;
20 | right: 1rem;
21 | background-color: #9ec862;
22 | color: #fff;
23 | border: none;
24 | border-radius: 3px;
25 | padding: 0.5rem 1rem;
26 | cursor: pointer;
27 | }
28 |
29 | .add:active {
30 | transform: scale(0.98);
31 | }
32 |
33 | .note {
34 | background-color: #fff;
35 | box-shadow: 0 0 10px 4px rgba(0, 0, 0, 0.1);
36 | margin: 30px 20px;
37 | height: 400px;
38 | width: 400px;
39 | overflow: hidden;
40 | }
41 |
42 | .note .tools {
43 | background-color: #9ec862;
44 | display: flex;
45 | justify-content: flex-end;
46 | padding: 0.5rem;
47 | }
48 |
49 | .note .tools button {
50 | background-color: transparent;
51 | border: none;
52 | color: #fff;
53 | cursor: pointer;
54 | font-size: 1rem;
55 | margin-left: 0.5rem;
56 | }
57 |
58 | .note textarea {
59 | outline: none;
60 | font-family: inherit;
61 | font-size: 1.2rem;
62 | border: none;
63 | height: 400px;
64 | width: 100%;
65 | padding: 20px;
66 | }
67 |
68 | .main {
69 | padding: 20px;
70 | }
71 |
72 | .hidden {
73 | display: none;
74 | }
75 |
--------------------------------------------------------------------------------
/034-animated-countdown/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Animated Countdown
21 |
22 |
23 |
24 |
25 |
26 | 3
27 | 2
28 | 1
29 | 0
30 |
31 |
Get Ready
32 |
33 |
34 |
35 |
GO
36 | Replay
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/034-animated-countdown/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/034-animated-countdown/output.gif
--------------------------------------------------------------------------------
/034-animated-countdown/script.js:
--------------------------------------------------------------------------------
1 | const nums = document.querySelectorAll('.nums span');
2 | const counter = document.querySelector('.counter');
3 | const finalMessage = document.querySelector('.final');
4 | const replay = document.querySelector('#replay');
5 |
6 |
7 | runAnimation();
8 |
9 | function resetDOM() {
10 | counter.classList.remove("hide");
11 | finalMessage.classList.remove("show");
12 |
13 | nums.forEach((num) => {
14 | num.classList.value = "";
15 | });
16 |
17 | nums[0].classList.add("in");
18 | }
19 |
20 | function runAnimation(){
21 | nums.forEach((num, idx) => {
22 | const nextToLast = nums.length - 1;
23 |
24 | num.addEventListener("animationend", (e) => {
25 | if(e.animationName === "goIn" && idx !== nextToLast){
26 | num.classList.remove("in");
27 | num.classList.add("out");
28 | }else if (e.animationName === "goOut" && num.nextElementSibling){
29 | num.nextElementSibling.classList.add("in");
30 | } else{
31 | counter.classList.add("hide");
32 | finalMessage.classList.add("show");
33 | }
34 | })
35 | })
36 | }
37 |
38 | replay.addEventListener('click', () => {
39 | resetDOM()
40 | runAnimation()
41 | })
--------------------------------------------------------------------------------
/035-image-carousel/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Image Carousel
21 |
22 |
23 |
24 |
25 |
42 |
43 |
44 | Prev
45 | Next
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/035-image-carousel/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/035-image-carousel/output.gif
--------------------------------------------------------------------------------
/035-image-carousel/script.js:
--------------------------------------------------------------------------------
1 | const imgs = document.getElementById('imgs')
2 | const leftBtn = document.getElementById('left')
3 | const rightBtn = document.getElementById('right')
4 |
5 | const img = document.querySelectorAll('#imgs img')
6 |
7 | let idx = 0
8 |
9 | let interval = setInterval(run, 2000)
10 |
11 | function run() {
12 | idx++
13 | changeImage()
14 | }
15 |
16 | function changeImage() {
17 | if(idx > img.length - 1) {
18 | idx = 0
19 | } else if(idx < 0) {
20 | idx = img.length - 1
21 | }
22 |
23 | imgs.style.transform = `translateX(${-idx * 500}px)`
24 | }
25 |
26 | function resetInterval() {
27 | clearInterval(interval)
28 | interval = setInterval(run, 2000)
29 | }
30 |
31 | rightBtn.addEventListener('click', () => {
32 | idx++
33 | changeImage()
34 | resetInterval()
35 | })
36 |
37 | leftBtn.addEventListener('click', () => {
38 | idx--
39 | changeImage()
40 | resetInterval()
41 | })
--------------------------------------------------------------------------------
/035-image-carousel/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: 'Roboto', sans-serif;
9 | display: flex;
10 | align-items: center;
11 | justify-content: center;
12 | height: 100vh;
13 | margin: 0;
14 | }
15 |
16 | img {
17 | width: 500px;
18 | height: 500px;
19 | object-fit: cover;
20 | }
21 |
22 | .carousel {
23 | box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
24 | height: 530px;
25 | width: 500px;
26 | overflow: hidden;
27 | }
28 |
29 | .image-container {
30 | display: flex;
31 | transform: translateX(0);
32 | transition: transform 0.5s ease-in-out;
33 | }
34 |
35 | .buttons-container {
36 | display: flex;
37 | justify-content: space-between;
38 | }
39 |
40 | .btn {
41 | background-color: rebeccapurple;
42 | color: #fff;
43 | border: none;
44 | padding: 0.5rem;
45 | cursor: pointer;
46 | width: 49.5%;
47 | }
48 |
49 | .btn:hover {
50 | opacity: 0.9;
51 | }
52 |
53 | .btn:focus {
54 | outline: none;
55 | }
--------------------------------------------------------------------------------
/036-hoverboard/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Hoverborad
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/036-hoverboard/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/036-hoverboard/output.gif
--------------------------------------------------------------------------------
/036-hoverboard/script.js:
--------------------------------------------------------------------------------
1 |
2 | const container = document.getElementById('container')
3 | const colors = ['#e74c3c', '#8e44ad', '#3498db', '#e67e22', '#2ecc71']
4 | const SQUARES = 500
5 |
6 | for(let i = 0; i < SQUARES; i++) {
7 | const square = document.createElement('div')
8 | square.classList.add('square')
9 |
10 | square.addEventListener('mouseover', () => setColor(square))
11 |
12 | square.addEventListener('mouseout', () => removeColor(square))
13 |
14 | container.appendChild(square)
15 | }
16 |
17 | function setColor(element) {
18 | const color = getRandomColor()
19 | element.style.background = color
20 | element.style.boxShadow = `0 0 2px ${color}, 0 0 10px ${color}`
21 | }
22 |
23 | function removeColor(element) {
24 | element.style.background = '#1d1d1d'
25 | element.style.boxShadow = '0 0 2px #000'
26 | }
27 |
28 | function getRandomColor() {
29 | return colors[Math.floor(Math.random() * colors.length)]
30 | }
--------------------------------------------------------------------------------
/036-hoverboard/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | background-color: #111;
7 | display: flex;
8 | align-items: center;
9 | justify-content: center;
10 | height: 100vh;
11 | overflow: hidden;
12 | margin: 0;
13 | }
14 |
15 | .container {
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | flex-wrap: wrap;
20 | max-width: 400px;
21 | }
22 |
23 | .square {
24 | background-color: #1d1d1d;
25 | box-shadow: 0 0 2px #000;
26 | height: 16px;
27 | width: 16px;
28 | margin: 2px;
29 | transition: 2s ease;
30 | }
31 |
32 | .square:hover {
33 | transition-duration: 0s;
34 | }
--------------------------------------------------------------------------------
/037-pokedex/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Pokedex
21 |
22 |
23 |
24 | Pokedex
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/037-pokedex/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/037-pokedex/output.gif
--------------------------------------------------------------------------------
/037-pokedex/script.js:
--------------------------------------------------------------------------------
1 | const poke_container = document.getElementById("poke-container");
2 | const pokemon_count = 150;
3 | const colors = {
4 | fire: "#FDDFDF",
5 | grass: "#DEFDE0",
6 | electric: "#FCF7DE",
7 | water: "#DEF3FD",
8 | ground: "#f4e7da",
9 | rock: "#d5d5d4",
10 | fairy: "#fceaff",
11 | poison: "#98d7a5",
12 | bug: "#f8d5a3",
13 | dragon: "#97b3e6",
14 | psychic: "#eaeda1",
15 | flying: "#F5F5F5",
16 | fighting: "#E6E0D4",
17 | normal: "#F5F5F5",
18 | };
19 |
20 | const main_types = Object.keys(colors);
21 |
22 | const fetchPokemons = async () => {
23 | for (let i = 1; i <= pokemon_count; i++) {
24 | await getPokemon(i);
25 | }
26 | };
27 |
28 | const getPokemon = async (id) => {
29 | const url = `https://pokeapi.co/api/v2/pokemon/${id}`;
30 | const res = await fetch(url);
31 | const data = await res.json();
32 | // console.log(data);
33 | createPokemonCard(data);
34 | };
35 |
36 | const createPokemonCard = (pokemon) => {
37 | const pokemonEl = document.createElement("div");
38 | pokemonEl.classList.add("pokemon");
39 |
40 | const name = pokemon.name[0].toUpperCase() + pokemon.name.slice(1);
41 | const id = pokemon.id.toString().padStart(3, "0");
42 |
43 | const poke_types = pokemon.types.map((type) => type.type.name);
44 | const type = main_types.find((type) => poke_types.indexOf(type) > -1);
45 | const color = colors[type];
46 | const pokeImg = pokemon.sprites.front_default;
47 |
48 | pokemonEl.style.backgroundColor = color;
49 |
50 | const pokemonInnerHTML = `
51 |
52 |
53 |
54 |
55 |
56 | #${id}
57 |
${name}
58 | Type: ${type}
59 |
60 | `;
61 |
62 | pokemonEl.innerHTML = pokemonInnerHTML;
63 |
64 | poke_container.appendChild(pokemonEl);
65 | };
66 |
67 | fetchPokemons();
68 |
--------------------------------------------------------------------------------
/037-pokedex/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Lato:300,400&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background: #efefbb;
9 | background: linear-gradient(to right, #d4d3dd, #efefbb);
10 | font-family: 'Lato', sans-serif;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: center;
15 | margin: 0;
16 | }
17 |
18 | h1 {
19 | letter-spacing: 3px;
20 | }
21 |
22 | .poke-container {
23 | display: flex;
24 | flex-wrap: wrap;
25 | align-items: space-between;
26 | justify-content: center;
27 | margin: 0 auto;
28 | max-width: 1200px;
29 | }
30 |
31 | .pokemon {
32 | background-color: #eee;
33 | border-radius: 10px;
34 | box-shadow: 0 3px 15px rgba(100, 100, 100, 0.5);
35 | margin: 10px;
36 | padding: 20px;
37 | text-align: center;
38 | }
39 |
40 | .pokemon .img-container {
41 | background-color: rgba(255, 255, 255, 0.6);
42 | border-radius: 50%;
43 | width: 120px;
44 | height: 120px;
45 | text-align: center;
46 | }
47 |
48 | .pokemon .img-container img {
49 | max-width: 90%;
50 | margin-top: 20px;
51 | }
52 |
53 | .pokemon .info {
54 | margin-top: 20px;
55 | }
56 |
57 | .pokemon .info .number {
58 | background-color: rgba(0, 0, 0, 0.1);
59 | padding: 5px 10px;
60 | border-radius: 10px;
61 | font-size: 0.8em;
62 | }
63 |
64 | .pokemon .info .name {
65 | margin: 15px 0 7px;
66 | letter-spacing: 1px;
67 | }
--------------------------------------------------------------------------------
/038-mobile-tab-navigation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Mobile Tab Navigation
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Home
35 |
36 |
37 |
38 | Work
39 |
40 |
41 |
42 | Blog
43 |
44 |
45 |
46 | About Us
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/038-mobile-tab-navigation/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/038-mobile-tab-navigation/output.gif
--------------------------------------------------------------------------------
/038-mobile-tab-navigation/script.js:
--------------------------------------------------------------------------------
1 | const contents = document.querySelectorAll('.content')
2 | const listItems = document.querySelectorAll('nav ul li')
3 |
4 | listItems.forEach((item, idx) => {
5 | item.addEventListener('click', () => {
6 | hideAllContents()
7 | hideAllItems()
8 |
9 | item.classList.add('active')
10 | contents[idx].classList.add('show')
11 | })
12 | })
13 |
14 | function hideAllContents() {
15 | contents.forEach(content => content.classList.remove('show'))
16 | }
17 |
18 |
19 | function hideAllItems() {
20 | listItems.forEach(item => item.classList.remove('active'))
21 | }
--------------------------------------------------------------------------------
/038-mobile-tab-navigation/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: rgba(155, 89, 182, 0.7);
9 | font-family: 'Open Sans', sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | margin: 0;
15 | }
16 |
17 | .phone {
18 | position: relative;
19 | overflow: hidden;
20 | border: 3px solid #eee;
21 | border-radius: 15px;
22 | height: 600px;
23 | width: 340px;
24 | }
25 |
26 | .phone .content {
27 | opacity: 0;
28 | object-fit: cover;
29 | position: absolute;
30 | top: 0;
31 | left: 0;
32 | height: calc(100% - 60px);
33 | width: 100%;
34 | transition: opacity 0.4s ease;
35 | }
36 |
37 | .phone .content.show {
38 | opacity: 1;
39 | }
40 |
41 | nav {
42 | position: absolute;
43 | bottom: 0;
44 | left: 0;
45 | margin-top: -5px;
46 | width: 100%;
47 | }
48 |
49 | nav ul {
50 | background-color: #fff;
51 | display: flex;
52 | list-style-type: none;
53 | padding: 0;
54 | margin: 0;
55 | height: 60px;
56 | }
57 |
58 | nav li {
59 | color: #777;
60 | cursor: pointer;
61 | flex: 1;
62 | padding: 10px;
63 | text-align: center;
64 | }
65 |
66 | nav ul li p {
67 | font-size: 12px;
68 | margin: 2px 0;
69 | }
70 |
71 | nav ul li:hover,
72 | nav ul li.active {
73 | color: #8e44ad;
74 | }
--------------------------------------------------------------------------------
/039-password-strength-background/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
26 | Password Strength Background
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Image Password Strength
34 |
Change the password to see the effect
35 |
36 | Email:
37 |
38 |
39 |
40 |
41 | Password:
42 |
43 |
44 |
45 |
46 | Submit
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/039-password-strength-background/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/039-password-strength-background/output.gif
--------------------------------------------------------------------------------
/039-password-strength-background/script.js:
--------------------------------------------------------------------------------
1 | const password = document.getElementById('password')
2 | const background = document.getElementById('background')
3 |
4 | password.addEventListener('input', (e) => {
5 | const input = e.target.value
6 | const length = input.length
7 | const blurValue = 20 - length * 2
8 | background.style.filter = `blur(${blurValue}px)`
9 | })
--------------------------------------------------------------------------------
/039-password-strength-background/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | display: flex;
7 | flex-direction: column;
8 | align-items: center;
9 | justify-content: center;
10 | height: 100vh;
11 | overflow: hidden;
12 | margin: 0;
13 | }
14 |
15 | .background {
16 | background: url('https://images.unsplash.com/photo-1556745757-8d76bdb6984b')
17 | no-repeat center center/cover;
18 | position: absolute;
19 | top: -20px;
20 | bottom: -20px;
21 | left: -20px;
22 | right: -20px;
23 | z-index: -1;
24 | filter: blur(20px);
25 | }
--------------------------------------------------------------------------------
/040-3d-background-boxes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | 3D Background Boxes
21 |
22 |
23 |
24 |
25 | Magic 🎩
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/040-3d-background-boxes/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/040-3d-background-boxes/output.gif
--------------------------------------------------------------------------------
/040-3d-background-boxes/script.js:
--------------------------------------------------------------------------------
1 | const boxesContainer = document.getElementById("boxes");
2 | const btn = document.getElementById("btn");
3 |
4 | btn.addEventListener("click", () => boxesContainer.classList.toggle("big"));
5 |
6 | function createBoxes() {
7 | for (let i = 0; i < 4; i++) {
8 | for (let j = 0; j < 4; j++) {
9 | const box = document.createElement("div");
10 | box.classList.add("box");
11 | box.style.backgroundPosition = `${-j * 125}px ${-i * 125}px`;
12 | boxesContainer.appendChild(box);
13 | }
14 | }
15 | }
16 |
17 | createBoxes();
18 |
--------------------------------------------------------------------------------
/040-3d-background-boxes/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 | @import url("https://fonts.googleapis.com/css2?family=Poppins&display=swap");
3 |
4 | * {
5 | box-sizing: border-box;
6 | }
7 |
8 | body {
9 | background-color: #fafafa;
10 | font-family: "Roboto", sans-serif;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: center;
15 | height: 100vh;
16 | overflow: hidden;
17 | }
18 |
19 | .magic {
20 | background-color: #f9ca24;
21 | color: #fff;
22 | font-family: "Poppins", sans-serif;
23 | border: 0;
24 | border-radius: 3px;
25 | font-size: 16px;
26 | padding: 12px 20px;
27 | cursor: pointer;
28 | position: fixed;
29 | top: 20px;
30 | letter-spacing: 1px;
31 | box-shadow: 0 3px rgba(249, 202, 36, 0.5);
32 | z-index: 100;
33 | }
34 |
35 | .magic:focus {
36 | outline: none;
37 | }
38 |
39 | .magic:active {
40 | box-shadow: none;
41 | transform: translateY(2px);
42 | }
43 |
44 | .boxes {
45 | display: flex;
46 | flex-wrap: wrap;
47 | justify-content: space-around;
48 | height: 500px;
49 | width: 500px;
50 | position: relative;
51 | transition: 0.4s ease;
52 | }
53 |
54 | .boxes.big {
55 | width: 600px;
56 | height: 600px;
57 | }
58 |
59 | .boxes.big .box {
60 | transform: rotateZ(360deg);
61 | }
62 |
63 | .box {
64 | background-image: url("https://media.giphy.com/media/EZqwsBSPlvSda/giphy.gif");
65 | background-repeat: no-repeat;
66 | background-size: 500px 500px;
67 | position: relative;
68 | height: 125px;
69 | width: 125px;
70 | transition: 0.4s ease;
71 | }
72 |
73 | .box::after {
74 | content: "";
75 | background-color: #f6e58d;
76 | position: absolute;
77 | top: 8px;
78 | right: -15px;
79 | height: 100%;
80 | width: 15px;
81 | transform: skewY(45deg);
82 | }
83 |
84 | .box::before {
85 | content: "";
86 | background-color: #f9ca24;
87 | position: absolute;
88 | bottom: -15px;
89 | left: 8px;
90 | height: 15px;
91 | width: 100%;
92 | transform: skewX(45deg);
93 | }
94 |
--------------------------------------------------------------------------------
/041-verify-account-ui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Verify Your Account
21 |
22 |
23 |
24 |
25 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/041-verify-account-ui/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/041-verify-account-ui/output.gif
--------------------------------------------------------------------------------
/041-verify-account-ui/script.js:
--------------------------------------------------------------------------------
1 | const codes = document.querySelectorAll('.code')
2 |
3 | codes[0].focus()
4 |
5 | codes.forEach((code, idx) => {
6 | code.addEventListener('keydown', (e) => {
7 | if(e.key >= 0 && e.key <=9) {
8 | codes[idx].value = ''
9 | setTimeout(() => codes[idx + 1].focus(), 10)
10 | } else if(e.key === 'Backspace') {
11 | setTimeout(() => codes[idx - 1].focus(), 10)
12 | }
13 | })
14 | })
--------------------------------------------------------------------------------
/041-verify-account-ui/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Muli:300,700&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #fbfcfe;
9 | font-family: 'Muli', sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
18 | .container {
19 | background-color: #fff;
20 | border: 3px #000 solid;
21 | border-radius: 10px;
22 | padding: 30px;
23 | max-width: 1000px;
24 | text-align: center;
25 | }
26 |
27 | .code-container {
28 | display: flex;
29 | align-items: center;
30 | justify-content: center;
31 | margin: 40px 0;
32 | }
33 |
34 | .code {
35 | border-radius: 5px;
36 | font-size: 75px;
37 | height: 120px;
38 | width: 100px;
39 | border: 1px solid #eee;
40 | margin: 1%;
41 | text-align: center;
42 | font-weight: 300;
43 | -moz-appearance: textfield;
44 | }
45 |
46 | .code::-webkit-outer-spin-button,
47 | .code::-webkit-inner-spin-button {
48 | -webkit-appearance: none;
49 | margin: 0;
50 | }
51 |
52 | .code:valid {
53 | border-color: #3498db;
54 | box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.25);
55 | }
56 |
57 | .info {
58 | background-color: #eaeaea;
59 | display: inline-block;
60 | padding: 10px;
61 | line-height: 20px;
62 | max-width: 400px;
63 | color: #777;
64 | border-radius: 5px;
65 | }
66 |
67 | @media (max-width: 600px) {
68 | .code-container {
69 | flex-wrap: wrap;
70 | }
71 |
72 | .code {
73 | font-size: 60px;
74 | height: 80px;
75 | max-width: 70px;
76 | }
77 | }
--------------------------------------------------------------------------------
/042-live-user-filter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Live User Filter
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 | Loading...
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/042-live-user-filter/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/042-live-user-filter/output.gif
--------------------------------------------------------------------------------
/042-live-user-filter/script.js:
--------------------------------------------------------------------------------
1 | const result = document.getElementById('result')
2 | const filter = document.getElementById('filter')
3 | const listItems = []
4 |
5 | getData()
6 |
7 | filter.addEventListener('input', (e) => filterData(e.target.value))
8 |
9 | async function getData() {
10 | const res = await fetch('https://randomuser.me/api?results=50')
11 |
12 | const { results } = await res.json()
13 |
14 | // Clear result
15 | result.innerHTML = ''
16 |
17 | results.forEach(user => {
18 | const li = document.createElement('li')
19 |
20 | listItems.push(li)
21 |
22 | li.innerHTML = `
23 |
24 |
25 |
${user.name.first} ${user.name.last}
26 |
${user.location.city}, ${user.location.country}
27 |
28 | `
29 |
30 | result.appendChild(li)
31 | })
32 | }
33 |
34 | function filterData(searchTerm) {
35 | listItems.forEach(item => {
36 | if(item.innerText.toLowerCase().includes(searchTerm.toLowerCase())) {
37 | item.classList.remove('hide')
38 | } else {
39 | item.classList.add('hide')
40 | }
41 | })
42 | }
--------------------------------------------------------------------------------
/042-live-user-filter/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #f8f9fd;
9 | font-family: 'Roboto', sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
18 | .container {
19 | border-radius: 5px;
20 | box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
21 | overflow: hidden;
22 | width: 300px;
23 | }
24 |
25 | .title {
26 | margin: 0;
27 | }
28 |
29 | .subtitle {
30 | display: inline-block;
31 | margin: 5px 0 20px;
32 | opacity: 0.8;
33 | }
34 |
35 | .header {
36 | background-color: #3e57db;
37 | color: #fff;
38 | padding: 30px 20px;
39 | }
40 |
41 | .header input {
42 | background-color: rgba(0, 0, 0, 0.3);
43 | border: 0;
44 | border-radius: 50px;
45 | color: #fff;
46 | font-size: 14px;
47 | padding: 10px 15px;
48 | width: 100%;
49 | }
50 |
51 | .header input:focus {
52 | outline: none;
53 | }
54 |
55 | .user-list {
56 | background-color: #fff;
57 | list-style-type: none;
58 | margin: 0;
59 | padding: 0;
60 | max-height: 400px;
61 | overflow-y: auto;
62 | }
63 |
64 | .user-list li {
65 | display: flex;
66 | padding: 20px;
67 | }
68 |
69 | .user-list img {
70 | border-radius: 50%;
71 | object-fit: cover;
72 | height: 50px;
73 | width: 50px;
74 | }
75 |
76 | .user-list .user-info {
77 | margin-left: 10px;
78 | }
79 |
80 | .user-list .user-info h4 {
81 | margin: 0 0 10px;
82 | }
83 |
84 | .user-list .user-info p {
85 | font-size: 12px;
86 | }
87 |
88 | .user-list li:not(:last-of-type) {
89 | border-bottom: 1px solid #eee;
90 | }
91 |
92 | .user-list li.hide {
93 | display: none;
94 | }
--------------------------------------------------------------------------------
/043-feedback-ui-design/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Let Us Know Your Feedback
21 |
22 |
23 |
24 |
25 |
How satisfied are you with our customer support performance?
26 |
27 |
28 |
31 |
Unhappy
32 |
33 |
34 |
35 |
38 |
Neutral
39 |
40 |
41 |
42 |
45 |
Satisfied
46 |
47 |
48 |
Send Review
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/043-feedback-ui-design/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/043-feedback-ui-design/output.png
--------------------------------------------------------------------------------
/043-feedback-ui-design/script.js:
--------------------------------------------------------------------------------
1 | const ratings = document.querySelectorAll('.rating')
2 | const ratingsContainer = document.querySelector('.ratings-container')
3 | const sendBtn = document.querySelector('#send')
4 | const panel = document.querySelector('#panel')
5 | let selectedRating = 'Satisfied'
6 |
7 | ratingsContainer.addEventListener('click', (e) => {
8 | if(e.target.parentNode.classList.contains('rating') && e.target.nextElementSibling) {
9 | removeActive()
10 | e.target.parentNode.classList.add('active')
11 | selectedRating = e.target.nextElementSibling.innerHTML
12 | } else if(
13 | e.target.parentNode.classList.contains('rating') &&
14 | e.target.previousSibling &&
15 | e.target.previousElementSibling.nodeName === 'IMG'
16 | ) {
17 | removeActive()
18 | e.target.parentNode.classList.add('active')
19 | selectedRating = e.target.innerHTML
20 | }
21 |
22 | })
23 |
24 | sendBtn.addEventListener('click', (e) => {
25 | panel.innerHTML = `
26 |
27 | Thank You!
28 |
29 | Feedback: ${selectedRating}
30 | We'll use your feedback to improve our customer support
31 | `
32 | })
33 |
34 | function removeActive() {
35 | for(let i = 0; i < ratings.length; i++) {
36 | ratings[i].classList.remove('active')
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/043-feedback-ui-design/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Montserrat&display=swap');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #fef9f2;
9 | font-family: 'Montserrat', sans-serif;
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | overflow: hidden;
15 | margin: 0;
16 | }
17 |
18 | .panel-container {
19 | background-color: #fff;
20 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
21 | border-radius: 4px;
22 | font-size: 90%;
23 | display: flex;
24 | flex-direction: column;
25 | justify-content: center;
26 | align-items: center;
27 | text-align: center;
28 | padding: 30px;
29 | max-width: 400px;
30 | }
31 |
32 | .panel-container strong {
33 | line-height: 20px;
34 | }
35 |
36 | .ratings-container {
37 | display: flex;
38 | margin: 20px 0;
39 | }
40 |
41 | .rating {
42 | flex: 1;
43 | cursor: pointer;
44 | padding: 20px;
45 | margin: 10px 5px;
46 | }
47 |
48 | .rating:hover,
49 | .rating.active {
50 | border-radius: 4px;
51 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
52 | }
53 |
54 | .rating img {
55 | width: 40px;
56 | }
57 |
58 | .rating small {
59 | color: #555;
60 | display: inline-block;
61 | margin: 10px 0 0;
62 | }
63 |
64 | .rating:hover small,
65 | .rating.active small {
66 | color: #111;
67 | }
68 |
69 | .btn {
70 | background-color: #302d2b;
71 | color: #fff;
72 | border: 0;
73 | border-radius: 4px;
74 | padding: 12px 30px;
75 | cursor: pointer;
76 | }
77 |
78 | .btn:focus {
79 | outline: 0;
80 | }
81 |
82 | .btn:active {
83 | transform: scale(0.98);
84 | }
85 |
86 | .fa-heart {
87 | color: red;
88 | font-size: 30px;
89 | margin-bottom: 10px;
90 | }
91 |
--------------------------------------------------------------------------------
/044-custom-range-slider/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Custom Range Slider
21 |
22 |
23 |
24 | Custom Range Slider
25 |
26 |
27 | 50
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/044-custom-range-slider/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/044-custom-range-slider/output.png
--------------------------------------------------------------------------------
/044-custom-range-slider/script.js:
--------------------------------------------------------------------------------
1 | const range = document.getElementById("range");
2 |
3 | range.addEventListener("input", (e) => {
4 | const value = +e.target.value;
5 | const label = e.target.nextElementSibling;
6 |
7 | const range_width = getComputedStyle(e.target).getPropertyValue("width");
8 | const label_width = getComputedStyle(label).getPropertyValue("width");
9 |
10 | const num_width = +range_width.substring(0, range_width.length - 2);
11 | const num_label_width = +label_width.substring(0, label_width.length - 2);
12 |
13 | const max = +e.target.max;
14 | const min = +e.target.min;
15 |
16 | const left =
17 | value * (num_width / max) -
18 | num_label_width / 2 +
19 | scale(value, min, max, 10, -10);
20 |
21 | label.style.left = `${left}px`;
22 |
23 | label.innerHTML = value;
24 | });
25 |
26 | const scale = (num, in_min, in_max, out_min, out_max) => {
27 | return ((num - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min;
28 | };
29 |
--------------------------------------------------------------------------------
/044-custom-range-slider/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Lato&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
9 | font-family: "Lato", sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | h2 {
20 | position: absolute;
21 | top: 10px;
22 | }
23 |
24 | .range-container {
25 | position: relative;
26 | }
27 |
28 | input[type="range"] {
29 | width: 300px;
30 | margin: 18px 0;
31 | -webkit-appearance: none;
32 | }
33 |
34 | input[type="range"]:focus {
35 | outline: none;
36 | }
37 |
38 | input[type="range"] + label {
39 | background-color: #fff;
40 | position: absolute;
41 | top: -25px;
42 | left: 110px;
43 | width: 80px;
44 | padding: 5px 0;
45 | text-align: center;
46 | border-radius: 4px;
47 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
48 | }
49 |
50 | /* Chrome & Safari */
51 | input[type="range"]::-webkit-slider-runnable-track {
52 | background: purple;
53 | border-radius: 4px;
54 | width: 100%;
55 | height: 10px;
56 | cursor: pointer;
57 | }
58 |
59 | input[type="range"]::-webkit-slider-thumb {
60 | -webkit-appearance: none;
61 | height: 24px;
62 | width: 24px;
63 | background: #fff;
64 | border-radius: 50%;
65 | border: 1px solid purple;
66 | margin-top: -7px;
67 | cursor: pointer;
68 | }
69 |
70 | /* Firefox */
71 | input[type="range"]::-moz-range-track {
72 | background: purple;
73 | border-radius: 4px;
74 | width: 100%;
75 | height: 13px;
76 | cursor: pointer;
77 | }
78 |
79 | input[type="range"]::-moz-range-thumb {
80 | -webkit-appearance: none;
81 | height: 24px;
82 | width: 24px;
83 | background: #fff;
84 | border-radius: 50%;
85 | border: 1px solid purple;
86 | margin-top: -7px;
87 | cursor: pointer;
88 | }
89 |
90 | /* IE */
91 | input[type="range"]::-ms-track {
92 | background: purple;
93 | border-radius: 4px;
94 | width: 100%;
95 | height: 13px;
96 | cursor: pointer;
97 | }
98 |
99 | input[type="range"]::-ms-thumb {
100 | -webkit-appearance: none;
101 | height: 24px;
102 | width: 24px;
103 | background: #fff;
104 | border-radius: 50%;
105 | border: 1px solid purple;
106 | margin-top: -7px;
107 | cursor: pointer;
108 | }
109 |
--------------------------------------------------------------------------------
/045-netflix-mobile-navigation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Netflix Mobile Navigation
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 | Mobile Navigation
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
44 |
45 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/045-netflix-mobile-navigation/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/045-netflix-mobile-navigation/output.gif
--------------------------------------------------------------------------------
/045-netflix-mobile-navigation/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/045-netflix-mobile-navigation/output.png
--------------------------------------------------------------------------------
/045-netflix-mobile-navigation/script.js:
--------------------------------------------------------------------------------
1 | const open_btn = document.querySelector(".open-btn");
2 | const close_btn = document.querySelector(".close-btn");
3 | const nav = document.querySelectorAll(".nav");
4 |
5 | open_btn.addEventListener("click", () => {
6 | nav.forEach((nav_el) => nav_el.classList.add("visible"));
7 | });
8 |
9 | close_btn.addEventListener("click", () => {
10 | nav.forEach((nav_el) => nav_el.classList.remove("visible"));
11 | });
12 |
--------------------------------------------------------------------------------
/045-netflix-mobile-navigation/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Muli&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: "Muli", sans-serif;
9 | display: flex;
10 | flex-direction: column;
11 | align-items: center;
12 | justify-content: center;
13 | height: 100vh;
14 | }
15 |
16 | .text {
17 | text-transform: uppercase;
18 | }
19 |
20 | .logo {
21 | width: 200px;
22 | }
23 |
24 | .nav-btn {
25 | border: none;
26 | background-color: transparent;
27 | cursor: pointer;
28 | font-size: 20px;
29 | }
30 |
31 | .open-btn {
32 | position: fixed;
33 | top: 10px;
34 | left: 10px;
35 | }
36 |
37 | .nav {
38 | position: fixed;
39 | top: 0;
40 | left: 0;
41 | height: 100vh;
42 | transform: translateX(-100%);
43 | transition: transform 0.3s ease-in-out;
44 | }
45 |
46 | .nav.visible {
47 | transform: translateX(0);
48 | }
49 |
50 | .nav-black {
51 | background-color: rgb(34, 31, 31);
52 | width: 60%;
53 | max-width: 480px;
54 | min-width: 320px;
55 | transition-delay: 0.4s;
56 | }
57 |
58 | .nav-black.visible {
59 | transition-delay: 0s;
60 | }
61 |
62 | .nav-red {
63 | background-color: rgb(229, 9, 20);
64 | width: 95%;
65 | transition-delay: 0.2s;
66 | }
67 |
68 | .nav-red.visible {
69 | transition-delay: 0.2s;
70 | }
71 |
72 | .nav-white {
73 | background-color: #fff;
74 | width: 95%;
75 | padding: 40px;
76 | position: relative;
77 | transition-delay: 0s;
78 | }
79 |
80 | .nav-white.visible {
81 | transition-delay: 0.4s;
82 | }
83 |
84 | .close-btn {
85 | opacity: 0.3;
86 | position: absolute;
87 | top: 40px;
88 | right: 30px;
89 | }
90 |
91 | .list {
92 | list-style-type: none;
93 | padding: 0;
94 | }
95 |
96 | .list li {
97 | margin: 20px 0;
98 | }
99 |
100 | .list li a {
101 | color: rgb(34, 31, 31);
102 | font-size: 14px;
103 | text-decoration: none;
104 | text-transform: uppercase;
105 | }
106 |
107 | .list ul {
108 | list-style-type: none;
109 | padding-left: 20px;
110 | }
111 |
--------------------------------------------------------------------------------
/046-quiz-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Quiz App
21 |
22 |
23 |
24 |
25 |
49 | Submit
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/046-quiz-app/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/046-quiz-app/output.gif
--------------------------------------------------------------------------------
/046-quiz-app/script.js:
--------------------------------------------------------------------------------
1 | const quizData = [
2 | {
3 | question: "Which language runs in a web browser?",
4 | a: "Java",
5 | b: "C",
6 | c: "Python",
7 | d: "JavaScript",
8 | correct: "d",
9 | },
10 | {
11 | question: "What does CSS stand for?",
12 | a: "Central Style Sheets",
13 | b: "Cascading Style Sheets",
14 | c: "Cascading Simple Sheets",
15 | d: "Cars SUVs Sailboats",
16 | correct: "b",
17 | },
18 | {
19 | question: "What does HTML stand for?",
20 | a: "Hypertext Markup Language",
21 | b: "Hypertext Markdown Language",
22 | c: "Hyperloop Machine Language",
23 | d: "Helicopters Terminals Motorboats Lamborginis",
24 | correct: "a",
25 | },
26 | {
27 | question: "What year was JavaScript launched?",
28 | a: "1996",
29 | b: "1995",
30 | c: "1994",
31 | d: "none of the above",
32 | correct: "b",
33 | },
34 | ];
35 |
36 | const quiz = document.getElementById("quiz");
37 | const answerEls = document.querySelectorAll(".answer");
38 | const questionEl = document.getElementById("question");
39 | const a_text = document.getElementById("a_text");
40 | const b_text = document.getElementById("b_text");
41 | const c_text = document.getElementById("c_text");
42 | const d_text = document.getElementById("d_text");
43 | const submitBtn = document.getElementById("submit");
44 |
45 | let currentQuiz = 0;
46 | let score = 0;
47 |
48 | loadQuiz();
49 |
50 | function loadQuiz() {
51 | deselectAnswers();
52 |
53 | const currentQuizData = quizData[currentQuiz];
54 |
55 | questionEl.innerText = currentQuizData.question;
56 | a_text.innerText = currentQuizData.a;
57 | b_text.innerText = currentQuizData.b;
58 | c_text.innerText = currentQuizData.c;
59 | d_text.innerText = currentQuizData.d;
60 | }
61 |
62 | function deselectAnswers() {
63 | answerEls.forEach((answerEl) => (answerEl.checked = false));
64 | }
65 |
66 | function getSelected() {
67 | let answer;
68 |
69 | answerEls.forEach((answerEl) => {
70 | if (answerEl.checked) {
71 | answer = answerEl.id;
72 | }
73 | });
74 |
75 | return answer;
76 | }
77 |
78 | submitBtn.addEventListener("click", () => {
79 | const answer = getSelected();
80 |
81 | if (answer) {
82 | if (answer === quizData[currentQuiz].correct) {
83 | score++;
84 | }
85 |
86 | currentQuiz++;
87 |
88 | if (currentQuiz < quizData.length) {
89 | loadQuiz();
90 | } else {
91 | quiz.innerHTML = `
92 | You answered ${score}/${quizData.length} questions correctly
93 |
94 | Reload
95 | `;
96 | }
97 | }
98 | });
99 |
--------------------------------------------------------------------------------
/046-quiz-app/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #b8c6db;
9 | background-image: linear-gradient(315deg, #b8c6db 0%, #f5f7fa 100%);
10 | font-family: "Poppins", sans-serif;
11 | display: flex;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | }
18 |
19 | .quiz-container {
20 | background-color: #fff;
21 | border-radius: 10px;
22 | box-shadow: 0 0 10px 2px rgba(100, 100, 100, 0.1);
23 | width: 600px;
24 | overflow: hidden;
25 | }
26 |
27 | .quiz-header {
28 | padding: 4rem;
29 | }
30 |
31 | h2 {
32 | padding: 1rem;
33 | text-align: center;
34 | margin: 0;
35 | }
36 |
37 | ul {
38 | list-style-type: none;
39 | padding: 0;
40 | }
41 |
42 | ul li {
43 | font-size: 1.2rem;
44 | margin: 1rem 0;
45 | }
46 |
47 | ul li label {
48 | cursor: pointer;
49 | }
50 |
51 | button {
52 | background-color: #8e44ad;
53 | color: #fff;
54 | border: none;
55 | display: block;
56 | width: 100%;
57 | cursor: pointer;
58 | font-size: 1.1rem;
59 | font-family: inherit;
60 | padding: 1.3rem;
61 | }
62 |
63 | button:hover {
64 | background-color: #732d91;
65 | }
66 |
67 | button:focus {
68 | outline: none;
69 | background-color: #5e3370;
70 | }
71 |
--------------------------------------------------------------------------------
/047-testimonial-box-switcher/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Testimonial Box
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | I've worked with literally hundreds of HTML/CSS developers and I have to
30 | say the top spot goes to this guy. This guy is an amazing developer. He
31 | stresses on good, clean code and pays heed to the details. I love
32 | developers who respect each and every aspect of a throughly thought out
33 | design and do their best to put it in code. He goes over and beyond and
34 | transforms ART into PIXELS - without a glitch, every time.
35 |
36 |
37 |
38 |
39 |
Miyah Myles
40 |
Marketing
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/047-testimonial-box-switcher/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/047-testimonial-box-switcher/output.gif
--------------------------------------------------------------------------------
/047-testimonial-box-switcher/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Montserrat');
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #f4f4f4;
9 | font-family: 'Montserrat', sans-serif;
10 | display: flex;
11 | flex-direction: column;
12 | align-items: center;
13 | justify-content: center;
14 | height: 100vh;
15 | overflow: hidden;
16 | margin: 0;
17 | padding: 10px;
18 | }
19 |
20 | .testimonial-container {
21 | background-color: #476ce4;
22 | color: #fff;
23 | border-radius: 15px;
24 | margin: 20px auto;
25 | padding: 50px 80px;
26 | max-width: 768px;
27 | position: relative;
28 | }
29 |
30 | .fa-quote {
31 | color: rgba(255, 255, 255, 0.3);
32 | font-size: 28px;
33 | position: absolute;
34 | top: 70px;
35 | }
36 |
37 | .fa-quote-right {
38 | left: 40px;
39 | }
40 |
41 | .fa-quote-left {
42 | right: 40px;
43 | }
44 |
45 | .testimonial {
46 | line-height: 28px;
47 | text-align: justify;
48 | }
49 |
50 | .user {
51 | display: flex;
52 | align-items: center;
53 | justify-content: center;
54 | }
55 |
56 | .user .user-image {
57 | border-radius: 50%;
58 | height: 75px;
59 | width: 75px;
60 | object-fit: cover;
61 | }
62 |
63 | .user .user-details {
64 | margin-left: 10px;
65 | }
66 |
67 | .user .username {
68 | margin: 0;
69 | }
70 |
71 | .user .role {
72 | font-weight: normal;
73 | margin: 10px 0;
74 | }
75 |
76 | .progress-bar {
77 | background-color: #fff;
78 | height: 4px;
79 | width: 100%;
80 | animation: grow 10s linear infinite;
81 | transform-origin: left;
82 | }
83 |
84 | @keyframes grow {
85 | 0% {
86 | transform: scaleX(0);
87 | }
88 | }
89 |
90 | @media (max-width: 768px) {
91 | .testimonial-container {
92 | padding: 20px 30px;
93 | }
94 |
95 | .fa-quote {
96 | display: none;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/048-random-image-generator/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Random Image Feed
21 |
22 |
23 |
24 | Random Image Feed
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/048-random-image-generator/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/048-random-image-generator/output.png
--------------------------------------------------------------------------------
/048-random-image-generator/script.js:
--------------------------------------------------------------------------------
1 | const container = document.querySelector(".container");
2 | const unsplashURL = "https://source.unsplash.com/random/";
3 | const rows = 5;
4 |
5 | for (let i = 0; i < rows * 3; i++) {
6 | const img = document.createElement("img");
7 | img.src = `${unsplashURL}${getRandomSize()}`;
8 | container.appendChild(img);
9 | }
10 |
11 | function getRandomSize() {
12 | return `${getRandomNr()}x${getRandomNr()}`;
13 | }
14 |
15 | function getRandomNr() {
16 | return Math.floor(Math.random() * 10) + 300;
17 | }
18 |
--------------------------------------------------------------------------------
/048-random-image-generator/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: "Roboto", sans-serif;
9 | display: flex;
10 | flex-direction: column;
11 | align-items: center;
12 | justify-content: center;
13 | min-height: 100vh;
14 | margin: 0;
15 | }
16 |
17 | .title {
18 | margin: 10px 0 0;
19 | text-align: center;
20 | }
21 |
22 | .container {
23 | display: flex;
24 | align-items: center;
25 | justify-content: center;
26 | flex-wrap: wrap;
27 | max-width: 1000px;
28 | }
29 |
30 | .container img {
31 | object-fit: cover;
32 | margin: 10px;
33 | height: 300px;
34 | width: 300px;
35 | max-width: 100%;
36 | }
37 |
--------------------------------------------------------------------------------
/049-todo-list/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Todo List
21 |
22 |
23 |
24 | todos
25 |
30 | Left click to toggle completed. Right click to delete todo
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/049-todo-list/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/049-todo-list/output.gif
--------------------------------------------------------------------------------
/049-todo-list/script.js:
--------------------------------------------------------------------------------
1 | const form = document.getElementById("form");
2 | const input = document.getElementById("input");
3 | const todosUL = document.getElementById("todos");
4 |
5 | const todos = JSON.parse(localStorage.getItem("todos"));
6 |
7 | if (todos) {
8 | todos.forEach((todo) => addTodo(todo));
9 | }
10 |
11 | form.addEventListener("submit", (e) => {
12 | e.preventDefault();
13 |
14 | addTodo();
15 | });
16 |
17 | function addTodo(todo) {
18 | let todoText = input.value;
19 |
20 | if (todo) {
21 | todoText = todo.text;
22 | }
23 |
24 | if (todoText) {
25 | const todoEl = document.createElement("li");
26 | if (todo && todo.completed) {
27 | todoEl.classList.add("completed");
28 | }
29 |
30 | todoEl.innerText = todoText;
31 |
32 | todoEl.addEventListener("click", () => {
33 | todoEl.classList.toggle("completed");
34 | updateLS();
35 | });
36 |
37 | todoEl.addEventListener("contextmenu", (e) => {
38 | e.preventDefault();
39 |
40 | todoEl.remove();
41 | updateLS();
42 | });
43 |
44 | todosUL.appendChild(todoEl);
45 |
46 | input.value = "";
47 |
48 | updateLS();
49 | }
50 | }
51 |
52 | function updateLS() {
53 | todosEl = document.querySelectorAll("li");
54 |
55 | const todos = [];
56 |
57 | todosEl.forEach((todoEl) => {
58 | todos.push({
59 | text: todoEl.innerText,
60 | completed: todoEl.classList.contains("completed"),
61 | });
62 | });
63 |
64 | localStorage.setItem("todos", JSON.stringify(todos));
65 | }
66 |
--------------------------------------------------------------------------------
/049-todo-list/style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background-color: #f5f5f5;
9 | color: #444;
10 | font-family: "Poppins", sans-serif;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: center;
15 | height: 100vh;
16 | margin: 0;
17 | }
18 |
19 | h1 {
20 | color: rgb(179, 131, 226);
21 | font-size: 10rem;
22 | text-align: center;
23 | opacity: 0.4;
24 | }
25 |
26 | form {
27 | box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
28 | max-width: 100%;
29 | width: 400px;
30 | }
31 |
32 | .input {
33 | border: none;
34 | color: #444;
35 | font-size: 2rem;
36 | padding: 1rem 2rem;
37 | display: block;
38 | width: 100%;
39 | }
40 |
41 | .input::placeholder {
42 | color: #d5d5d5;
43 | }
44 |
45 | .input:focus {
46 | outline-color: rgb(179, 131, 226);
47 | }
48 |
49 | .todos {
50 | background-color: #fff;
51 | padding: 0;
52 | margin: 0;
53 | list-style-type: none;
54 | }
55 |
56 | .todos li {
57 | border-top: 1px solid #e5e5e5;
58 | cursor: pointer;
59 | font-size: 1.5rem;
60 | padding: 1rem 2rem;
61 | }
62 |
63 | .todos li.completed {
64 | color: #b6b6b6;
65 | text-decoration: line-through;
66 | }
67 |
68 | small {
69 | color: #b5b5b5;
70 | margin-top: 3rem;
71 | text-align: center;
72 | }
73 |
--------------------------------------------------------------------------------
/050-insect-catch-game/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | Catch The Insect
21 |
22 |
23 |
24 |
25 |
Catch The Insect
26 | Play Game
27 |
28 |
29 |
30 |
What is your "favorite" insect?
31 |
32 |
33 |
34 | Fly
35 |
36 |
37 |
38 |
39 |
40 | Mosquito
41 |
42 |
43 |
44 |
45 |
46 | Spider
47 |
48 |
49 |
50 |
51 |
52 | Roach
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
Time: 00:00
61 | Score: 0
62 |
63 | Are you annoyed yet?
64 | You are playing an impossible game!!
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/050-insect-catch-game/output.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshkgd/css-js-projects/0fea7387b50b4c76871520548e4b44dc94aff2f0/050-insect-catch-game/output.gif
--------------------------------------------------------------------------------
/050-insect-catch-game/script.js:
--------------------------------------------------------------------------------
1 | const screens = document.querySelectorAll(".screen");
2 | const choose_insect_btns = document.querySelectorAll(".choose-insect-btn");
3 | const start_btn = document.getElementById("start-btn");
4 | const game_container = document.getElementById("game-container");
5 | const timeEl = document.getElementById("time");
6 | const scoreEl = document.getElementById("score");
7 | const message = document.getElementById("message");
8 | let seconds = 0;
9 | let score = 0;
10 | let selected_insect = {};
11 |
12 | start_btn.addEventListener("click", () => screens[0].classList.add("up"));
13 |
14 | choose_insect_btns.forEach((btn) => {
15 | btn.addEventListener("click", () => {
16 | const img = btn.querySelector("img");
17 | const src = img.getAttribute("src");
18 | const alt = img.getAttribute("alt");
19 | selected_insect = { src, alt };
20 | screens[1].classList.add("up");
21 | setTimeout(createInsect, 1000);
22 | startGame();
23 | });
24 | });
25 |
26 | function startGame() {
27 | setInterval(increaseTime, 1000);
28 | }
29 |
30 | function increaseTime() {
31 | let m = Math.floor(seconds / 60);
32 | let s = seconds % 60;
33 | m = m < 10 ? `0${m}` : m;
34 | s = s < 10 ? `0${s}` : s;
35 | timeEl.innerHTML = `Time: ${m}:${s}`;
36 | seconds++;
37 | }
38 |
39 | function createInsect() {
40 | const insect = document.createElement("div");
41 | insect.classList.add("insect");
42 | const { x, y } = getRandomLocation();
43 | insect.style.top = `${y}px`;
44 | insect.style.left = `${x}px`;
45 | insect.innerHTML = ` `;
48 |
49 | insect.addEventListener("click", catchInsect);
50 |
51 | game_container.appendChild(insect);
52 | }
53 |
54 | function getRandomLocation() {
55 | const width = window.innerWidth;
56 | const height = window.innerHeight;
57 | const x = Math.random() * (width - 200) + 100;
58 | const y = Math.random() * (height - 200) + 100;
59 | return { x, y };
60 | }
61 |
62 | function catchInsect() {
63 | increaseScore();
64 | this.classList.add("caught");
65 | setTimeout(() => this.remove(), 2000);
66 | addInsects();
67 | }
68 |
69 | function addInsects() {
70 | setTimeout(createInsect, 1000);
71 | setTimeout(createInsect, 1500);
72 | }
73 |
74 | function increaseScore() {
75 | score++;
76 | if (score > 19) {
77 | message.classList.add("visible");
78 | }
79 | scoreEl.innerHTML = `Score: ${score}`;
80 | }
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # html-css-js-only-projects
2 |
--------------------------------------------------------------------------------