diff --git a/README.md b/README.md index 0f57702..af383c5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -# HTML-CSS-JavaScript-projects-for-beginners - -This is the source code of the YouTube video (10 projects) https://www.youtube.com/watch?v=ePzOFu2xXUQ. - -Part 2 (16 projects) : https://youtu.be/EWv2jnhZErc - -NEW HTML CSS JavaScript Projects Interesting HTML CSS JavaScript projects Learn HTML, CSS, and JavaScript 2021 to create modern websites. Fun learning HTML, CSS, and JavaScript! - -I'm Sahand, a web developer in computer science. I've been doing this for over a decade. This course was created to share my knowledge and experience with you. Build simple websites using HTML, CSS, and JavaScript. Responsive web design employs HTML, CSS, and JavaScript. This is a skill you'll learn in this course. This new course teaches students how to install Visual Studio Code and its extensions. Then we start from scratch with each project. After finishing HTML, it's on to CSS and JavaScript. Building in HTML, CSS, or JavaScript is fine. This guide explains HTML, CSS, and JavaScript syntax. - -Every project is started from scratch and finished without using copied code. Then they are used on the project to ensure everyone understands. This program's exciting project-based curriculum includes building modern, super cool, and responsive websites! Let's get started learning HTML, CSS, and JavaScript. - -Contact me if you have any questions through my twitter: @codewithsahand. +# HTML CSS JavaScript Projects + +This is the source code of the website: 100 HTML CSS JavaScript Projects +
+ Visit 100jsprojects.com to preview the projects. + +
+
+

About

+

Hi there! I'm Sahand, a web developer with over a decade of experience. This course, "HTML CSS JavaScript Projects," was created to share my knowledge and experience with you. In this course, you'll learn how to build simple, responsive websites using HTML, CSS, and JavaScript.

+

In this course, you'll learn how to install Visual Studio Code and its extensions, and then we'll start from scratch with each project. After finishing HTML, we'll move on to CSS and JavaScript. Building in HTML, CSS, or JavaScript is fine, and this guide will explain HTML, CSS, and JavaScript syntax.

+

Each project in this course is started from scratch and finished without using copied code. Then, we'll go over the code together to ensure that everyone understands. This program's exciting project-based curriculum includes building modern, super cool, and responsive websites!

+

If you have any questions, please feel free to contact me through my email: codewithsahand@gmail.com

+ Visit my website +
diff --git a/projects/Navbar-project/index.html b/projects/Navbar-project/index.html deleted file mode 100644 index 4975da5..0000000 --- a/projects/Navbar-project/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - Sahand Ghavidel - - - - - - - - \ No newline at end of file diff --git a/projects/age-calculator/index.html b/projects/age-calculator/index.html new file mode 100644 index 0000000..7ef5c27 --- /dev/null +++ b/projects/age-calculator/index.html @@ -0,0 +1,23 @@ + + + + + + + Age Calculator + + + +
+

Age Calculator

+
+ + + +

Your age is 21 years old

+
+
+ + + + \ No newline at end of file diff --git a/projects/age-calculator/index.js b/projects/age-calculator/index.js new file mode 100644 index 0000000..b2888ee --- /dev/null +++ b/projects/age-calculator/index.js @@ -0,0 +1,31 @@ +const btnEl = document.getElementById("btn"); +const birthdayEl = document.getElementById("birthday"); +const resultEl = document.getElementById("result"); + +function calculateAge() { + const birthdayValue = birthdayEl.value; + if (birthdayValue === "") { + alert("Please enter your birthday"); + } else { + const age = getAge(birthdayValue); + resultEl.innerText = `Your age is ${age} ${age > 1 ? "years" : "year"} old`; + } +} + +function getAge(birthdayValue) { + const currentDate = new Date(); + const birthdayDate = new Date(birthdayValue); + let age = currentDate.getFullYear() - birthdayDate.getFullYear(); + const month = currentDate.getMonth() - birthdayDate.getMonth(); + + if ( + month < 0 || + (month === 0 && currentDate.getDate() < birthdayDate.getDate()) + ) { + age--; + } + + return age; +} + +btnEl.addEventListener("click", calculateAge); diff --git a/projects/age-calculator/style.css b/projects/age-calculator/style.css new file mode 100644 index 0000000..0229675 --- /dev/null +++ b/projects/age-calculator/style.css @@ -0,0 +1,63 @@ +body { + margin: 0; + padding: 20px; + font-family: "Montserrat", sans-serif; + background-color: #f7f7f7; +} + +.container { + background-color: white; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + padding: 20px; + max-width: 600px; + margin: 0 auto; + border-radius: 5px; + margin-top: 50px; +} + +h1 { + font-size: 36px; + text-align: center; + margin-top: 0; + margin-bottom: 20px; +} + +.form { + display: flex; + flex-direction: column; + align-items: center; +} + +label { + font-weight: bold; + margin-bottom: 10px; +} + +input { + padding: 8px; + border: 1px solid #ccc; + border-radius: 5px; + width: 100%; + max-width: 300px; +} + +button { + background-color: #007bff; + color: white; + border: none; + padding: 10px 20px; + border-radius: 5px; + margin-top: 10px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #0062cc; +} + +#result { + margin-top: 20px; + font-size: 24px; + font-weight: bold; +} diff --git a/projects/background-video-project/background-video.mp4 b/projects/background-video/background-video.mp4 similarity index 100% rename from projects/background-video-project/background-video.mp4 rename to projects/background-video/background-video.mp4 diff --git a/projects/background-video-project/index.html b/projects/background-video/index.html similarity index 100% rename from projects/background-video-project/index.html rename to projects/background-video/index.html diff --git a/projects/background-video-project/index.js b/projects/background-video/index.js similarity index 100% rename from projects/background-video-project/index.js rename to projects/background-video/index.js diff --git a/projects/background-video-project/preloader.gif b/projects/background-video/preloader.gif similarity index 100% rename from projects/background-video-project/preloader.gif rename to projects/background-video/preloader.gif diff --git a/projects/background-video-project/styles.css b/projects/background-video/styles.css similarity index 100% rename from projects/background-video-project/styles.css rename to projects/background-video/styles.css diff --git a/projects/basic-calculator/index.html b/projects/basic-calculator/index.html index f9cf785..432ea60 100644 --- a/projects/basic-calculator/index.html +++ b/projects/basic-calculator/index.html @@ -1,32 +1,35 @@ - - - Simple Calculator - - - + + + + + + Basic Calculator + + +
-

-
- - - - - - - - - - - - - - - - - -
+ +
+ + + + + + + + + + + + + + + + + +
- - - + + + \ No newline at end of file diff --git a/projects/basic-calculator/index.js b/projects/basic-calculator/index.js new file mode 100644 index 0000000..40fa6e8 --- /dev/null +++ b/projects/basic-calculator/index.js @@ -0,0 +1,29 @@ +const buttonsEl = document.querySelectorAll("button"); + +const inputFieldEl = document.getElementById("result"); + +for (let i = 0; i < buttonsEl.length; i++) { + buttonsEl[i].addEventListener("click", () => { + const buttonValue = buttonsEl[i].textContent; + if (buttonValue === "C") { + clearResult(); + } else if (buttonValue === "=") { + calculateResult(); + } else { + appendValue(buttonValue); + } + }); +} + +function clearResult() { + inputFieldEl.value = ""; +} + +function calculateResult() { + inputFieldEl.value = eval(inputFieldEl.value); +} + +function appendValue(buttonValue) { + inputFieldEl.value += buttonValue; + // inputFieldEl.value = inputFieldEl.value + buttonValue; +} diff --git a/projects/basic-calculator/script.js b/projects/basic-calculator/script.js deleted file mode 100644 index c898ec4..0000000 --- a/projects/basic-calculator/script.js +++ /dev/null @@ -1,35 +0,0 @@ -const resultField = document.getElementById("result"); -const buttons = document.querySelectorAll("button"); - -for (let i = 0; i < buttons.length; i++) { - const button = buttons[i]; - button.addEventListener("click", function () { - const buttonValue = button.textContent; - if (buttonValue === "C") { - clearResult(); - } else if (buttonValue === "=") { - calculate(); - } else { - appendValue(buttonValue); - } - }); -} - -function appendValue(val) { - resultField.value += val; -} - -function clearResult() { - resultField.value = ""; -} - -function calculate() { - const expression = resultField.value; - const result = eval(expression); - // In JavaScript, eval() is a built-in function that evaluates a string as if it were a JavaScript code and returns the result. It can be used to dynamically evaluate expressions or code that is generated at runtime. - - // In the context of a calculator, eval() can be used to evaluate the arithmetic expression entered by the user and return the result. - - // For example, if the user enters the expression "2 + 3 * 4", eval("2 + 3 * 4") will return 14, which is the result of evaluating the expression. - resultField.value = result; -} diff --git a/projects/basic-calculator/style.css b/projects/basic-calculator/style.css index dbf9d16..baf4abd 100644 --- a/projects/basic-calculator/style.css +++ b/projects/basic-calculator/style.css @@ -1,82 +1,68 @@ * { box-sizing: border-box; + margin: 0; } -/* By setting box-sizing: border-box on all elements, we are ensuring that any padding or border we add to an element will be included in its total size. */ - .calculator { + background-color: #f2f2f2; + padding: 20px; max-width: 400px; margin: 0 auto; - margin-top: 30px; - padding: 20px; - background-color: #f2f2f2; - border: 1px solid #ccc; - border-radius: 5px; + border: solid 1px #ccc; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); -} - -#result { - width: 100%; - padding: 10px; - font-size: 24px; - border: none; border-radius: 5px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3) inset; - - /* In this case, the box-shadow property is set to 0 2px 5px rgba(0, 0, 0, 0.3) inset. This means that the shadow will have no horizontal offset (0), a vertical offset of 2px, a blur radius of 5px, and a color of rgba(0, 0, 0, 0.3). The inset keyword is used to specify that the shadow should be an inset shadow, rather than an outset shadow. */ + margin-top: 40px; } -.buttons { - display: grid; - grid-template-columns: repeat(4, 1fr); - /* grid-template-columns: repeat(4, 1fr) is a CSS property that sets the size of each column in a grid container. In this case, the repeat(4, 1fr) value creates a grid with four equal-sized columns. - -The fr unit stands for "fractional unit" and is used to divide the available space in a grid container. In this case, each column takes up an equal fraction of the available space, regardless of the size of the container. - -So, with grid-template-columns: repeat(4, 1fr), the grid container will be divided into four equal-sized columns, which is what we want for our calculator layout. */ - grid-gap: 10px; - margin-top: 20px; +#result{ + width: 100%; + padding: 10px; + font-size: 24px; + border: none; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3) inset; + border-radius: 5px; } -button { - padding: 10px; - font-size: 24px; - border: none; - border-radius: 5px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); - cursor: pointer; - transition: background-color 0.3s ease; +.buttons{ + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-gap: 10px; + margin-top: 20px; } -button:hover { - background-color: #ddd; -} +button{ + padding: 10px; + font-size: 24px; + border: none; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease; -.clear { - background-color: #ff4136; - color: #fff; } -.operator { - background-color: #0074d9; - color: #fff; +button:hover{ + background-color: #ddd; } -.number { - background-color: #fff; - color: #333; +.clear{ + background-color: #ff4136; + color: #fff; } -.equals { - grid-row: span 3; - /* grid-row: span 3; is a CSS property that sets the number of rows an element spans in a CSS grid container. +.number, .decimal{ + background-color: #fff; + color: #333; -In this case, span 3 is used to make the element span three rows in the grid container. */ - background-color: #01ff70; - color: #fff; } -.decimal { - background-color: #fff; - color: #333; +.operator{ + background-color: #0074d9; + color: #fff; } + +.equals{ + background-color: #01ff70; + grid-row: span 3; + color: #fff; +} \ No newline at end of file diff --git a/projects/dice-roll-simulator/index.html b/projects/dice-roll-simulator/index.html new file mode 100644 index 0000000..edf81b5 --- /dev/null +++ b/projects/dice-roll-simulator/index.html @@ -0,0 +1,20 @@ + + + + + + + Dice Roll Simulator + + + +

Dice Roll Simulator

+
+ + + + + diff --git a/projects/dice-roll-simulator/index.js b/projects/dice-roll-simulator/index.js new file mode 100644 index 0000000..8deecde --- /dev/null +++ b/projects/dice-roll-simulator/index.js @@ -0,0 +1,53 @@ +const buttonEl = document.getElementById("roll-button"); + +const diceEl = document.getElementById("dice"); + +const rollHistoryEl = document.getElementById("roll-history"); + +let historyList = []; + +function rollDice() { + const rollResult = Math.floor(Math.random() * 6) + 1; + const diceFace = getDiceFace(rollResult); + diceEl.innerHTML = diceFace; + historyList.push(rollResult); + updateRollHistory(); +} + +function updateRollHistory() { + rollHistoryEl.innerHTML = ""; + for (let i = 0; i < historyList.length; i++) { + const listItem = document.createElement("li"); + listItem.innerHTML = `Roll ${i + 1}: ${getDiceFace( + historyList[i] + )}`; + rollHistoryEl.appendChild(listItem); + } +} + +function getDiceFace(rollResult) { + switch (rollResult) { + case 1: + return "⚀"; + case 2: + return "⚁"; + case 3: + return "⚂"; + case 4: + return "⚃"; + case 5: + return "⚄"; + case 6: + return "⚅"; + default: + return ""; + } +} + +buttonEl.addEventListener("click", () => { + diceEl.classList.add("roll-animation"); + setTimeout(() => { + diceEl.classList.remove("roll-animation"); + rollDice(); + }, 1000); +}); diff --git a/projects/dice-roll-simulator/style.css b/projects/dice-roll-simulator/style.css new file mode 100644 index 0000000..439ab24 --- /dev/null +++ b/projects/dice-roll-simulator/style.css @@ -0,0 +1,70 @@ +body { + font-family: "Open Sans", sans-serif; + text-align: center; + margin: 0; +} + +h1 { + font-size: 3rem; + margin-top: 2rem; +} + +.dice { + font-size: 7rem; + margin: 5px; + animation-duration: 1s; + animation-fill-mode: forwards; +} + +.roll-animation { + animation-name: roll; +} + +@keyframes roll { + 0% { + transform: rotateY(0deg) rotateX(0deg); + } + + 100% { + transform: rotateY(720deg) rotateX(720deg); + } +} + +button { + background-color: #47a5c4; + color: white; + font-size: 1.5rem; + padding: 1rem 2rem; + border: none; + border-radius: 1rem; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #2e8baf; +} + +ul { + list-style: none; + padding: 0; + max-width: 600px; + margin: 2rem auto; +} + +li { + font-size: 1.5rem; + padding: 0.5rem; + margin: 0.5rem; + background-color: #f2f2f2; + border-radius: 0.5rem; + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3); + display: flex; + justify-content: space-between; + align-items: center; +} + +li span { + font-size: 3rem; + margin-right: 1rem; +} diff --git a/projects/double-landing-page/style.css b/projects/double-landing-page/style.css index 5a62c04..0d37d66 100644 --- a/projects/double-landing-page/style.css +++ b/projects/double-landing-page/style.css @@ -11,7 +11,7 @@ body { h1 { font-size: 100px; color: aliceblue; - backdrop-filter: brightness(0.5); + background-color: rgba(0, 0, 0, 0.3); letter-spacing: 4px; } diff --git a/projects/image-search-app/app.js b/projects/image-search-app/app.js deleted file mode 100644 index e342813..0000000 --- a/projects/image-search-app/app.js +++ /dev/null @@ -1,70 +0,0 @@ -// Set the access key for the Unsplash API -const accessKey = "3I7M0FgMDBz0BC9OMC4e4wi9ByTMXZYt0Rk4fQ15TKs"; - -// Get elements from the HTML document using their IDs -const searchForm = document.getElementById("search-form"); -const searchInput = document.getElementById("search-input"); -const searchResults = document.getElementById("search-results"); -const showMoreButton = document.getElementById("show-more-button"); - -// Initialize variables -let page = 1; -let query = ""; - -// Create an asynchronous function to search for images -async function searchImages() { - // Set the query value to the input value from the search form - query = searchInput.value; - // Create the URL for the Unsplash API with the page number, query, and access key - const url = `https://api.unsplash.com/search/photos?page=${page}&query=${query}&client_id=${accessKey}`; - // Send a request to the API and wait for the response - const response = await fetch(url); - // Parse the response data as JSON - const data = await response.json(); - // Get the results array from the response data - const results = data.results; - - // If this is the first page of results, clear the search results div - if (page === 1) { - searchResults.innerHTML = ""; - } - - // Loop through each result and create a div with an image and link for each one - results.forEach((result) => { - const imageWrapper = document.createElement("div"); - imageWrapper.classList.add("search-result"); - - const image = document.createElement("img"); - image.src = result.urls.small; - image.alt = result.alt_description; - - const imageLink = document.createElement("a"); - imageLink.href = result.links.html; - imageLink.target = "_blank"; - imageLink.textContent = result.alt_description; - - imageWrapper.appendChild(image); - imageWrapper.appendChild(imageLink); - searchResults.appendChild(imageWrapper); - }); - - // Increment the page number for the next search - page++; - - // Show the "show more" button if there are more than one page of results - if (page > 1) { - showMoreButton.style.display = "block"; - } -} - -// Listen for a submit event on the search form, prevent the default action, and search for images -searchForm.addEventListener("submit", (event) => { - event.preventDefault(); - page = 1; - searchImages(); -}); - -// Listen for a click event on the "show more" button and search for more images -showMoreButton.addEventListener("click", () => { - searchImages(); -}); diff --git a/projects/image-search-app/index.html b/projects/image-search-app/index.html index 92e769d..47214ed 100644 --- a/projects/image-search-app/index.html +++ b/projects/image-search-app/index.html @@ -2,27 +2,56 @@ - Unsplash Image Search App + + + Image Search App

Image Search App

-
+ - +
-
+
- - - + + diff --git a/projects/image-search-app/index.js b/projects/image-search-app/index.js new file mode 100644 index 0000000..87a94e1 --- /dev/null +++ b/projects/image-search-app/index.js @@ -0,0 +1,54 @@ +const accessKey = "RZEIOVfPhS7vMLkFdd2TSKGFBS4o9_FmcV1Nje3FSjw"; + +const formEl = document.querySelector("form"); +const searchInputEl = document.getElementById("search-input"); +const searchResultsEl = document.querySelector(".search-results"); +const showMoreButtonEl = document.getElementById("show-more-button"); + +let inputData = ""; +let page = 1; + +async function searchImages() { + inputData = searchInputEl.value; + const url = `https://api.unsplash.com/search/photos?page=${page}&query=${inputData}&client_id=${accessKey}`; + + const response = await fetch(url); + const data = await response.json(); + if (page === 1) { + searchResultsEl.innerHTML = ""; + } + + const results = data.results; + + results.map((result) => { + const imageWrapper = document.createElement("div"); + imageWrapper.classList.add("search-result"); + const image = document.createElement("img"); + image.src = result.urls.small; + image.alt = result.alt_description; + const imageLink = document.createElement("a"); + imageLink.href = result.links.html; + imageLink.target = "_blank"; + imageLink.textContent = result.alt_description; + + imageWrapper.appendChild(image); + imageWrapper.appendChild(imageLink); + searchResultsEl.appendChild(imageWrapper); + }); + + page++; + + if (page > 1) { + showMoreButtonEl.style.display = "block"; + } +} + +formEl.addEventListener("submit", (event) => { + event.preventDefault(); + page = 1; + searchImages(); +}); + +showMoreButtonEl.addEventListener("click", () => { + searchImages(); +}); diff --git a/projects/image-search-app/style.css b/projects/image-search-app/style.css index 07fc2e5..875a68a 100644 --- a/projects/image-search-app/style.css +++ b/projects/image-search-app/style.css @@ -1,170 +1,125 @@ body { - background-color: #f9f9f9; /* Sets the background color of the body element to a light gray */ - font-family: Arial, sans-serif; /* Sets the font family of the text inside the body to Arial or a generic sans-serif font */ - font-size: 16px; /* Sets the font size of the text inside the body to 16 pixels */ - line-height: 1.6; /* Sets the line height of the text inside the body to 1.6 times the font size */ - color: #333; /* Sets the color of the text inside the body to a dark gray */ + background-color: #f9f9f9; + font-family: Arial, Helvetica, sans-serif; + line-height: 1.6; + margin: 0; } h1 { - font-size: 36px; /* Sets the font size of the h1 heading to 36 pixels */ - font-weight: bold; /* Makes the h1 heading bold */ - text-align: center; /* Centers the h1 heading horizontally within its container */ - margin-top: 40px; /* Adds a top margin of 40 pixels to the h1 heading */ - margin-bottom: 60px; /* Adds a bottom margin of 60 pixels to the h1 heading */ + font-size: 36px; + font-weight: bold; + text-align: center; + margin-top: 40px; + margin-bottom: 60px; } -#search-form { - display: flex; /* Set the display property of the element to flex */ - justify-content: center; /* Center the child elements horizontally */ - align-items: center; /* Center the child elements vertically */ - margin-bottom: 60px; /* Add a bottom margin of 60 pixels to the element */ +form { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 60px; } #search-input { - width: 60%; /* Set the width of the element to 60% of its container */ - max-width: 400px; /* Set the maximum width of the element to 400 pixels */ - padding: 10px 20px; /* Add 10 pixels of padding to the top and bottom and 20 pixels of padding to the left and right of the element */ - border: none; /* Remove the border from the element */ - border-radius: 5px; /* Add a 5-pixel radius to the element's border corners */ - box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); /* Add a 5-pixel box shadow to the element */ - font-size: 18px; /* Set the font size of the element to 18 pixels */ - color: #333; /* Set the text color of the element to #333 */ + width: 60%; + max-width: 400px; + padding: 10px 20px; + border: none; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + border-radius: 5px; + font-size: 18px; + color: #333; } #search-button { - padding: 10px 20px; /* Sets the padding of the button */ - background-color: #4caf50; /* Sets the background color of the button */ - color: white; /* Sets the text color of the button */ - font-size: 18px; /* Sets the font size of the button text */ - border: none; /* Removes the border of the button */ - border-radius: 5px; /* Sets the border radius of the button */ - box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); /* Sets the box shadow of the button */ - cursor: pointer; /* Changes the cursor to pointer when hovering over the button */ - transition: background-color 0.3s ease-in-out; /* Sets the transition effect when the background color changes */ + padding: 10px 20px; + background-color: #4caf50; + color: white; + border: none; + font-size: 18px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + cursor: pointer; + border-radius: 5px; + transition: background-color 0.3s ease-in-out; } #search-button:hover { - background-color: #3e8e41; /* Changes the background color when hovering over the button */ + background-color: #3e8e41; } -#search-results { - display: flex; /* sets the display type of the element to flex*/ - flex-wrap: wrap; /* allows the flex items to wrap to multiple lines*/ - justify-content: space-between; /* aligns the flex items along the main axis with equal spacing between them*/ - margin: 0 auto; /* sets the top and bottom margins to 0 and the left and right margins to auto*/ - max-width: 1200px; /* sets the maximum width of the element to 1200 pixels*/ +.search-results { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + max-width: 1200px; + margin: 0 auto; + padding: 20px; } -/* Sets the styles for an individual search result element */ .search-result { - /* Adds 60px margin to the bottom of each search result element */ margin-bottom: 60px; - - /* Sets the width of the search result element to 30% of the parent container */ width: 30%; - - /* Adds rounded corners to the search result element */ border-radius: 5px; - - /* Adds a box shadow to the search result element */ - box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); - - /* Hides any content that overflows the search result element */ + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); overflow: hidden; } +.search-result:hover img { + transform: scale(1.05); +} + .search-result img { - /* Sets the width of the image to 100% of its container element */ width: 100%; - - /* Sets the height of the image to 200 pixels */ height: 200px; - - /* Determines how the image should be resized to cover its container without distorting its aspect ratio */ object-fit: cover; - - /* Specifies that any changes to the transform property of the image should be transitioned over a duration of 0.3 seconds with an easing function */ transition: transform 0.3s ease-in-out; } - -.search-result:hover img { - transform: scale(1.05); - /* The transform property scales the image by 1.05, making it 5% larger than its original size. This creates a zoom effect when the user hovers over the image. */ -} - .search-result a { - display: block; /* sets the display type to block */ - padding: 10px; /* adds padding to the top and bottom of the element */ - color: #333; /* sets the text color to dark gray */ - text-decoration: none; /* removes any text decoration */ - transition: background-color 0.3s ease-in-out; /* sets a transition effect when the background color changes */ + padding: 10px; + display: block; + color: #333; + text-decoration: none; + transition: background-color 0.3s ease-in-out; } -.search-result a:hover { - background-color: rgba( - 0, - 0, - 0, - 0.1 - ); /* changes the background color to a light gray when the element is hovered over */ +.search-result:hover a { + background-color: rgba(0, 0, 0, 0.1); } #show-more-button { - background-color: #008cba; /* Sets the background color of the button to a shade of blue */ - border: none; /* Removes the border around the button */ - color: white; /* Sets the font color of the button text to white */ - padding: 10px 20px; /* Sets the padding of the button to 10px on the top and bottom, and 20px on the left and right */ - text-align: center; /* Centers the button text horizontally */ - text-decoration: none; /* Removes any text decoration such as underlining */ - display: inline-block; /* Displays the button as an inline-level block container */ - font-size: 16px; /* Sets the font size of the button text to 16px */ - border-radius: 5px; /* Rounds the corners of the button to 5px */ - margin-top: 20px; /* Adds a 20px margin on the top of the button */ - transition: background-color 0.3s ease; /* Specifies a transition effect for the background color when hovering over the button */ - display: none; /* Hides the button */ - margin: 0 auto; /* Centers the button horizontally */ - margin-bottom: 40px; /* Adds a 40px margin on the bottom of the button */ - cursor: pointer; /* Sets the cursor to a pointer when hovering over the button */ + background-color: #008cba; + border: none; + color: white; + padding: 10px 20px; + display: block; + margin: 20px auto; + text-align: center; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease-in-out; + display: none; } #show-more-button:hover { - background-color: #0077b5; /* Changes the background color of the button to a darker shade of blue when hovering over it */ + background-color: #0077b5; } -/* This is a CSS media query, which applies different styles based on the size of the screen. - -The first media query applies when the screen width is a maximum of 768px. In this case, it changes the justify-content property of #search-results to center the search results horizontally. It also changes the width of .search-result to 45%. - -The second media query applies when the screen width is a maximum of 480px. In this case, it changes the flex-direction property of #search-form to column, which stacks the search input and button vertically. It also adds a margin bottom to #search-input and changes the width of .search-result to 100%, making each search result take up the full width of the screen. */ - -/* The following styles will apply when the screen size is 768px or smaller */ @media screen and (max-width: 768px) { - /* Centers the search result items */ - #search-results { - justify-content: center; - } - - /* Decreases the width of each search result item */ .search-result { width: 45%; } } - -/* The following styles will apply when the screen size is 480px or smaller */ @media screen and (max-width: 480px) { - /* Changes the direction of the search form to be vertical */ - #search-form { + .search-result { + width: 100%; + } + + form { flex-direction: column; } - /* Adds margin to the bottom of the search input */ #search-input { margin-bottom: 20px; - } - - /* Makes each search result item full width */ - .search-result { - width: 100%; + width: 85%; } } diff --git a/projects/navbar/index.html b/projects/navbar/index.html new file mode 100644 index 0000000..78fd71b --- /dev/null +++ b/projects/navbar/index.html @@ -0,0 +1,38 @@ + + + + + + + Navbar project + + + + + + + + diff --git a/projects/Navbar-project/index.js b/projects/navbar/index.js similarity index 100% rename from projects/Navbar-project/index.js rename to projects/navbar/index.js diff --git a/projects/Navbar-project/logo.svg b/projects/navbar/logo.svg similarity index 100% rename from projects/Navbar-project/logo.svg rename to projects/navbar/logo.svg diff --git a/projects/Navbar-project/styles.css b/projects/navbar/styles.css similarity index 100% rename from projects/Navbar-project/styles.css rename to projects/navbar/styles.css diff --git a/projects/new-year-countdown/index.html b/projects/new-year-countdown/index.html index c4c0578..3638291 100644 --- a/projects/new-year-countdown/index.html +++ b/projects/new-year-countdown/index.html @@ -9,7 +9,7 @@

Countdown to New Year

-
2022
+
2024
00
00
diff --git a/projects/new-year-countdown/index.js b/projects/new-year-countdown/index.js index 1a89f36..3ee8cd0 100644 --- a/projects/new-year-countdown/index.js +++ b/projects/new-year-countdown/index.js @@ -3,7 +3,7 @@ const hourEl = document.getElementById("hour"); const minuteEl = document.getElementById("minute"); const secondEl = document.getElementById("second"); -const newYearTime = new Date("Jan 1, 2022 00:00:00").getTime(); +const newYearTime = new Date("Jan 1, 2024 00:00:00").getTime(); updateCountdown(); diff --git a/projects/pomodoro-timer/index.html b/projects/pomodoro-timer/index.html new file mode 100644 index 0000000..7cfe584 --- /dev/null +++ b/projects/pomodoro-timer/index.html @@ -0,0 +1,22 @@ + + + + + + + Pomodoro Timer + + + +
+

Pomodoro Timer

+

25:00

+
+ + + +
+
+ + + \ No newline at end of file diff --git a/projects/pomodoro-timer/index.js b/projects/pomodoro-timer/index.js new file mode 100644 index 0000000..22b4ede --- /dev/null +++ b/projects/pomodoro-timer/index.js @@ -0,0 +1,42 @@ +const startEl = document.getElementById("start"); +const stopEl = document.getElementById("stop"); +const resetEl = document.getElementById("reset"); +const timerEl = document.getElementById("timer"); + +let interval; +let timeLeft = 1500; + +function updateTimer() { + let minutes = Math.floor(timeLeft / 60); + let seconds = timeLeft % 60; + let formattedTime = `${minutes.toString().padStart(2, "0")}:${seconds + .toString() + .padStart(2, "0")}`; + + timerEl.innerHTML = formattedTime; +} + +function startTimer() { + interval = setInterval(() => { + timeLeft--; + updateTimer(); + if (timeLeft === 0) { + clearInterval(interval); + alert("Time's up!"); + timeLeft = 1500; + updateTimer(); + } + }, 1000); +} +function stopTimer() { + clearInterval(interval); +} +function resetTimer() { + clearInterval(interval); + timeLeft = 1500; + updateTimer(); +} + +startEl.addEventListener("click", startTimer); +stopEl.addEventListener("click", stopTimer); +resetEl.addEventListener("click", resetTimer); diff --git a/projects/pomodoro-timer/style.css b/projects/pomodoro-timer/style.css new file mode 100644 index 0000000..0e6970b --- /dev/null +++ b/projects/pomodoro-timer/style.css @@ -0,0 +1,47 @@ +.container { + margin: 0 auto; + max-width: 400px; + text-align: center; + padding: 20px; + font-family: "Roboto", sans-serif; +} + +.title { + font-size: 36px; + margin-bottom: 10px; + color: #2c3e50; +} + +.timer { + font-size: 72px; + color: #2c3e50; +} + +button { + font-size: 18px; + padding: 10px 20px; + margin: 10px; + color: white; + + border: none; + border-radius: 4px; + cursor: pointer; + text-transform: uppercase; + transition: opacity 0.3s ease-in-out; +} + +button:hover { + opacity: 0.7; +} + +#start { + background-color: #27ae60; +} + +#stop { + background-color: #c0392b; +} + +#reset { + background-color: #7f8c8d; +} diff --git a/projects/Q&A-section/app.js b/projects/q-and-a-section/app.js similarity index 100% rename from projects/Q&A-section/app.js rename to projects/q-and-a-section/app.js diff --git a/projects/Q&A-section/index.html b/projects/q-and-a-section/index.html similarity index 100% rename from projects/Q&A-section/index.html rename to projects/q-and-a-section/index.html diff --git a/projects/Q&A-section/styles.css b/projects/q-and-a-section/styles.css similarity index 100% rename from projects/Q&A-section/styles.css rename to projects/q-and-a-section/styles.css diff --git a/projects/recipe-book-app/index.html b/projects/recipe-book-app/index.html new file mode 100644 index 0000000..b93360d --- /dev/null +++ b/projects/recipe-book-app/index.html @@ -0,0 +1,57 @@ + + + + + + + Document + + + +
+

Recipe Book App

+
+ +
+
    + +
+
+ + + diff --git a/projects/recipe-book-app/index.js b/projects/recipe-book-app/index.js new file mode 100644 index 0000000..d35b3b8 --- /dev/null +++ b/projects/recipe-book-app/index.js @@ -0,0 +1,50 @@ +const API_KEY = "275d58779ccf4e22af03e792e8819fff"; +const recipeListEl = document.getElementById("recipe-list"); + +function displayRecipes(recipes) { + recipeListEl.innerHTML = ""; + recipes.forEach((recipe) => { + const recipeItemEl = document.createElement("li"); + recipeItemEl.classList.add("recipe-item"); + recipeImageEl = document.createElement("img"); + recipeImageEl.src = recipe.image; + recipeImageEl.alt = "recipe image"; + + recipeTitleEl = document.createElement("h2"); + recipeTitleEl.innerText = recipe.title; + + recipeIngredientsEl = document.createElement("p"); + recipeIngredientsEl.innerHTML = ` + Ingredients: ${recipe.extendedIngredients + .map((ingredient) => ingredient.original) + .join(", ")} + `; + + recipeLinkEl = document.createElement("a"); + recipeLinkEl.href = recipe.sourceUrl; + recipeLinkEl.innerText = "View Recipe"; + + recipeItemEl.appendChild(recipeImageEl); + recipeItemEl.appendChild(recipeTitleEl); + recipeItemEl.appendChild(recipeIngredientsEl); + recipeItemEl.appendChild(recipeLinkEl); + recipeListEl.appendChild(recipeItemEl); + }); +} + +async function getRecipes() { + const response = await fetch( + `https://api.spoonacular.com/recipes/random?number=10&apiKey=${API_KEY}` + ); + + const data = await response.json(); + + return data.recipes; +} + +async function init() { + const recipes = await getRecipes(); + displayRecipes(recipes); +} + +init(); diff --git a/projects/recipe-book-app/style.css b/projects/recipe-book-app/style.css new file mode 100644 index 0000000..9e56d02 --- /dev/null +++ b/projects/recipe-book-app/style.css @@ -0,0 +1,104 @@ +body { + margin: 0; + padding: 0; + font-family: Arial, sans-serif; +} + +header { + background: #0c2461; + color: #fff; + padding: 20px; + text-align: center; +} + +h1 { + margin: 0; + font-size: 36px; +} + +.container { + margin: 0 auto; + max-width: 1200px; + padding: 20px; +} + +.recipe-list { + list-style: none; + margin: 0; + padding: 0; +} + +.recipe-item { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + border-radius: 5px; + overflow: hidden; +} + +.recipe-item img { + width: 150px; + height: 150px; + object-fit: cover; +} + +.recipe-item h2 { + margin: 0; + font-size: 20px; + padding: 10px; + min-width: 200px; +} + +.recipe-item p { + margin: 0; + padding: 10px; + color: #777; +} + +.recipe-item a { + background: #0c2461; + color: #fff; + min-width: 150px; + padding: 10px; + text-decoration: none; + text-transform: uppercase; + font-size: 14px; + transition: background 0.3s ease; +} + +.recipe-item a:hover { + background: #1e3799; +} + +@media screen and (max-width: 768px) { + .container { + max-width: 90%; + } + .recipe-item { + flex-direction: column; + } + + .recipe-item img { + width: 100%; + height: auto; + margin-bottom: 10px; + } + + .recipe-item h2 { + font-size: 20px; + padding: 0; + margin-bottom: 10px; + } + + .recipe-item p { + font-size: 14px; + margin-bottom: 10px; + } + + .recipe-item a { + width: 100%; + text-align: center; + } +} diff --git a/projects/rock-paper-scissors-game/index.html b/projects/rock-paper-scissors-game/index.html new file mode 100644 index 0000000..c458606 --- /dev/null +++ b/projects/rock-paper-scissors-game/index.html @@ -0,0 +1,25 @@ + + + + + + + Rock Paper Scissors Game + + + +

Rock Paper Scissors Game

+

Choose your move:

+
+ + + +
+

+

+ Your score: 0 + Computer score: 0 +

+ + + \ No newline at end of file diff --git a/projects/rock-paper-scissors-game/index.js b/projects/rock-paper-scissors-game/index.js new file mode 100644 index 0000000..4944f3e --- /dev/null +++ b/projects/rock-paper-scissors-game/index.js @@ -0,0 +1,42 @@ +const buttons = document.querySelectorAll("button"); + +const resultEl = document.getElementById("result"); + +const playerScoreEl = document.getElementById("user-score"); + +const computerScoreEl = document.getElementById("computer-score"); + +let playerScore = 0; +let computerScore = 0; + +buttons.forEach((button) => { + button.addEventListener("click", () => { + const result = playRound(button.id, computerPlay()); + resultEl.textContent = result; + + }); +}); + +function computerPlay() { + const choices = ["rock", "paper", "scissors"]; + const randomChoice = Math.floor(Math.random() * choices.length); + return choices[randomChoice]; +} + +function playRound(playerSelection, computerSelection) { + if (playerSelection === computerSelection) { + return "It's a tie!"; + } else if ( + (playerSelection === "rock" && computerSelection === "scissors") || + (playerSelection === "paper" && computerSelection === "rock") || + (playerSelection === "scissors" && computerSelection === "paper") + ) { + playerScore++; + playerScoreEl.textContent = playerScore; + return "You win! " + playerSelection + " beats " + computerSelection; + } else { + computerScore++; + computerScoreEl.textContent = computerScore; + return "You lose! " + computerSelection + " beats " + playerSelection; + } +} diff --git a/projects/rock-paper-scissors-game/style.css b/projects/rock-paper-scissors-game/style.css new file mode 100644 index 0000000..940eff4 --- /dev/null +++ b/projects/rock-paper-scissors-game/style.css @@ -0,0 +1,58 @@ +body { + background-color: #f1f1f1; + font-family: "Arial", sans-serif; + margin: 0; + padding: 0; +} + +h1 { + font-size: 2rem; + text-align: center; + padding-top: 100px; +} + +p { + font-size: 1.5rem; + font-weight: 600; + text-align: center; + margin-bottom: 0.5rem; +} + +.buttons { + display: flex; + justify-content: center; +} + +button { + border: none; + font-size: 3rem; + margin: 0 0.5rem; + padding: 0.5rem; + cursor: pointer; + border-radius: 5px; + transition: all 0.3s ease-in-out; +} + +button:hover { + opacity: 0.7; +} + +#rock { + background-color: #ff0000; +} + +#paper { + background-color: #2196f3; +} + +#scissors { + background-color: #4caf50; +} + +#user-score { + color: #2196f3; +} + +#computer-score { + color: #ff0000; +} diff --git a/projects/Sidebar-project/index.html b/projects/sidebar/index.html similarity index 100% rename from projects/Sidebar-project/index.html rename to projects/sidebar/index.html diff --git a/projects/Sidebar-project/index.js b/projects/sidebar/index.js similarity index 100% rename from projects/Sidebar-project/index.js rename to projects/sidebar/index.js diff --git a/projects/Sidebar-project/logo.svg b/projects/sidebar/logo.svg similarity index 100% rename from projects/Sidebar-project/logo.svg rename to projects/sidebar/logo.svg diff --git a/projects/Sidebar-project/styles.css b/projects/sidebar/styles.css similarity index 100% rename from projects/Sidebar-project/styles.css rename to projects/sidebar/styles.css diff --git a/projects/simple-stopwatch/index.html b/projects/simple-stopwatch/index.html deleted file mode 100644 index d61ac22..0000000 --- a/projects/simple-stopwatch/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - Stopwatch - - - -
00:00:00
-
- - - -
- - - diff --git a/projects/simple-stopwatch/stopwatch.js b/projects/simple-stopwatch/stopwatch.js deleted file mode 100644 index df0d14a..0000000 --- a/projects/simple-stopwatch/stopwatch.js +++ /dev/null @@ -1,78 +0,0 @@ -// Get references to the timer and button elements -var timer = document.getElementById("timer"); -var startButton = document.getElementById("start"); -var stopButton = document.getElementById("stop"); -var resetButton = document.getElementById("reset"); - -// Initialize variables for tracking the start time, elapsed time, and timer interval -var startTime, - elapsedTime = 0, - timerInterval; - -// Function to start the timer -function startTimer() { - // Calculate the start time by subtracting the elapsed time from the current time - startTime = Date.now() - elapsedTime; - - // Start an interval that updates the timer display every 10 milliseconds - timerInterval = setInterval(function printTime() { - // Calculate the elapsed time by subtracting the start time from the current time - elapsedTime = Date.now() - startTime; - - // Update the timer display with the formatted elapsed time - timer.textContent = formatTime(elapsedTime); - }, 10); - - // Disable the start button and enable the stop button - startButton.disabled = true; - stopButton.disabled = false; -} - -// Function to stop the timer -function stopTimer() { - // Clear the interval that updates the timer display - clearInterval(timerInterval); - - // Enable the start button and disable the stop button - startButton.disabled = false; - stopButton.disabled = true; -} - -// Function to reset the timer -function resetTimer() { - // Clear the interval that updates the timer display - clearInterval(timerInterval); - - // Reset the elapsed time to 0 and update the timer display - elapsedTime = 0; - timer.textContent = "00:00:00"; - - // Enable the start button and disable the stop button - startButton.disabled = false; - stopButton.disabled = true; -} - -// Function to format the elapsed time as a string -function formatTime(time) { - var hours = Math.floor(time / (1000 * 60 * 60)); - var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60)); - var seconds = Math.floor((time % (1000 * 60)) / 1000); - var milliseconds = Math.floor((time % 1000) / 10); - // The ternary operator hours ? (hours > 9 ? hours : "0" + hours) : "00" checks if the hours variable has a value greater than zero. If it does, it checks if it is greater than 9. If it is, it returns the value of hours. If it is less than or equal to 9, it adds a leading zero to the hours value and returns it. If hours is zero, it returns the string "00". - - // The same logic is applied to format the minutes and seconds values. - return ( - (hours ? (hours > 9 ? hours : "0" + hours) : "00") + - ":" + - (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + - ":" + - (seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") + - "." + - (milliseconds > 9 ? milliseconds : "0" + milliseconds) - ); -} - -// Add event listeners to the button elements to trigger the timer functions -startButton.addEventListener("click", startTimer); -stopButton.addEventListener("click", stopTimer); -resetButton.addEventListener("click", resetTimer); diff --git a/projects/stopwatch/index.html b/projects/stopwatch/index.html new file mode 100644 index 0000000..05d8b2b --- /dev/null +++ b/projects/stopwatch/index.html @@ -0,0 +1,20 @@ + + + + + + + Stopwatch + + + + +
00:00:00
+
+ + + +
+ + + \ No newline at end of file diff --git a/projects/stopwatch/index.js b/projects/stopwatch/index.js new file mode 100644 index 0000000..0cbd647 --- /dev/null +++ b/projects/stopwatch/index.js @@ -0,0 +1,54 @@ +const timerEl = document.getElementById("timer"); +const startButtonEl = document.getElementById("start"); +const stopButtonEl = document.getElementById("stop"); +const resetButtonEl = document.getElementById("reset"); + +let startTime = 0; +let elapsedTime = 0; +let timerInterval; + +function startTimer() { + startTime = Date.now() - elapsedTime; + + timerInterval = setInterval(() => { + elapsedTime = Date.now() - startTime; + timerEl.textContent = formatTime(elapsedTime); + }, 10); + + startButtonEl.disabled = true; + stopButtonEl.disabled = false; +} + +function formatTime(elapsedTime) { + const milliseconds = Math.floor((elapsedTime % 1000) / 10); + const seconds = Math.floor((elapsedTime % (1000 * 60)) / 1000); + const minutes = Math.floor((elapsedTime % (1000 * 60 * 60)) / (1000 * 60)); + const hours = Math.floor(elapsedTime / (1000 * 60 * 60)); + return ( + (hours ? (hours > 9 ? hours : "0" + hours) : "00") + + ":" + + (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + + ":" + + (seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") + + "." + + (milliseconds > 9 ? milliseconds : "0" + milliseconds) + ); +} +function stopTimer() { + clearInterval(timerInterval); + startButtonEl.disabled = false; + stopButtonEl.disabled = true; +} +function resetTimer() { + clearInterval(timerInterval); + + elapsedTime = 0; + timerEl.textContent = "00:00:00"; + + startButtonEl.disabled = false; + stopButtonEl.disabled = true; +} + +startButtonEl.addEventListener("click", startTimer); +stopButtonEl.addEventListener("click", stopTimer); +resetButtonEl.addEventListener("click", resetTimer); diff --git a/projects/simple-stopwatch/style.css b/projects/stopwatch/style.css similarity index 61% rename from projects/simple-stopwatch/style.css rename to projects/stopwatch/style.css index f1a4e31..cf0859d 100644 --- a/projects/simple-stopwatch/style.css +++ b/projects/stopwatch/style.css @@ -4,17 +4,16 @@ body { display: flex; flex-direction: column; justify-content: center; - align-items: center; - height: 100vh; + min-height: 100vh; overflow: hidden; + align-items: center; } #timer { font-size: 7rem; font-weight: 700; - color: #f92672; text-shadow: 2px 2px #f8a5c2; - /* In the current code, the value 2px 2px #f8a5c2 sets a shadow that is 2 pixels to the right and 2 pixels down of the text, with a blur radius of 0 (no blur), and a color of #f8a5c2. */ + color: #f92672; width: 600px; text-align: center; margin: 40px auto; @@ -29,15 +28,14 @@ button { background-color: #f92672; color: white; border: none; - border-radius: 30px; font-size: 2rem; font-weight: bold; padding: 1.5rem 4rem; - /* In the current code, the value 1.5rem 4rem sets a padding of 1.5rem (24px) for the top and bottom sides of the buttons, and 4rem (64px) for the left and right sides of the buttons. */ margin: 1rem; + border-radius: 30px; cursor: pointer; - transition: background-color 0.2s; box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3); + transition: all 0.2s; } button:hover { @@ -45,12 +43,19 @@ button:hover { box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5); } -button:active { - background-color: #f34282; - box-shadow: none; -} - button[disabled] { opacity: 0.5; cursor: default; } + +@media (max-width: 800px) { + #timer { + font-size: 4rem; + width: 350px; + } + + button { + font-size: 1.5rem; + padding: 1rem 2rem; + } +} diff --git a/projects/tip-calculator/index.html b/projects/tip-calculator/index.html new file mode 100644 index 0000000..029457b --- /dev/null +++ b/projects/tip-calculator/index.html @@ -0,0 +1,28 @@ + + + + + + + Tip Calculator + + + +
+

Tip Calculator

+

Enter the bill amount and tip percentage to calculate the total.

+ + +
+ + +
+ +
+ + + +
+ + + \ No newline at end of file diff --git a/projects/tip-calculator/index.js b/projects/tip-calculator/index.js new file mode 100644 index 0000000..98cb079 --- /dev/null +++ b/projects/tip-calculator/index.js @@ -0,0 +1,13 @@ +const btnEl = document.getElementById("calculate"); +const billInput = document.getElementById("bill"); +const tipInput = document.getElementById("tip"); +const totalSpan = document.getElementById("total"); + +function calculateTotal() { + const billValue = billInput.value; + const tipValue = tipInput.value; + const totalValue = billValue * (1 + tipValue / 100); + totalSpan.innerText = totalValue.toFixed(2); +} + +btnEl.addEventListener("click", calculateTotal); diff --git a/projects/tip-calculator/style.css b/projects/tip-calculator/style.css new file mode 100644 index 0000000..786e129 --- /dev/null +++ b/projects/tip-calculator/style.css @@ -0,0 +1,53 @@ +* { + box-sizing: border-box; +} + +body { + background-color: #f2f2f2; + font-family: "Helvetica", sans-serif; +} + +.container { + background-color: white; + max-width: 600px; + margin: 100px auto; + padding: 20px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + border-radius: 10px; +} + +h1 { + margin-top: 0; + text-align: center; +} + +input { + padding: 10px; + border: 1px solid #ccc; + border-radius: 4px; + margin: 10px 0; + width: 100%; +} + +button { + background-color: #4caf50; + color: white; + padding: 10px; + border: none; + cursor: pointer; + margin: 10px 0; + width: 100%; + font-size: 18px; + text-transform: uppercase; + transition: background-color 0.2s ease; +} + +button:hover { + background-color: #45a049; +} + +#total { + font-size: 24px; + font-weight: bold; + margin-top: 10px; +}