├── sun.png ├── cloud.png ├── haze.png ├── icon.png ├── mist.png ├── rain.png ├── snow.png ├── wind.png ├── world.html ├── README.md ├── search.js ├── search.html ├── world.js ├── style.css ├── search.css ├── world.css ├── main.js └── index.html /sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/sun.png -------------------------------------------------------------------------------- /cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/cloud.png -------------------------------------------------------------------------------- /haze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/haze.png -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/icon.png -------------------------------------------------------------------------------- /mist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/mist.png -------------------------------------------------------------------------------- /rain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/rain.png -------------------------------------------------------------------------------- /snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/snow.png -------------------------------------------------------------------------------- /wind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohittiwari98/simple-weather-app/main/wind.png -------------------------------------------------------------------------------- /world.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Document 13 | 14 | 15 | 16 |
17 | 18 | 25 | 26 |
27 |
April 7, 2024
28 |
29 |
30 | 31 |
32 |
33 |
34 |

Add a new place

35 |
36 | 37 | 41 | 42 |
43 |
City not found
44 |
Search your city to add
45 |
Succefy added ✔
46 |
47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simple-weather-app 2 | Simple Weather App 3 | A simple, user-friendly web application that provides current weather data for any city. Built with HTML, CSS, and JavaScript, this app fetches live weather information from an external API, displaying temperature, humidity, wind speed, and more. 4 | 5 | Features 6 | City Search: Users can search for the weather by entering a city name. 7 | Current Weather Data: Displays the temperature, humidity, wind speed, and weather conditions (e.g., sunny, cloudy). 8 | Temperature Units: Option to toggle between Celsius and Fahrenheit. 9 | Responsive Design: Works seamlessly on both mobile and desktop devices. 10 | Error Handling: If the city is not found or the API call fails, an error message is shown. 11 | Demo 12 | You can view the live demo of the Simple Weather App [here](URL to live demo, if applicable). 13 | 14 | Technologies Used 15 | HTML: Provides the structure and content of the web application. 16 | CSS: For styling the user interface, ensuring the app is visually appealing and mobile-friendly. 17 | JavaScript: Handles the logic for fetching weather data, managing user input, and dynamically updating the UI. 18 | Weather API: Fetches current weather data (e.g., OpenWeatherMap API). 19 | How to Use 20 | Search for a City: Type the name of the city in the search bar and press the "Search" button or hit Enter. 21 | View Weather Data: The app will display the current temperature, humidity, wind speed, and weather conditions for the selected city. 22 | Change Temperature Unit: Toggle between Celsius and Fahrenheit by clicking the unit button. 23 | Installation 24 | To run the project locally: 25 | 26 | In the JavaScript file (script.js), replace the API_KEY placeholder with your actual API key: 27 | 28 | const apiKey = 'YOUR_API_KEY'; 29 | Ensure the API URL in the JavaScript code is set up correctly to query the weather data. 30 | Customization: 31 | You can easily customize the app by modifying the following files: 32 | index.html: Update the structure of the page and add any new sections or features. 33 | style.css: Adjust the styling to change the appearance of the weather app, including layout, colors, fonts, and more. 34 | script.js: Update the logic for fetching data, adding new weather information, or integrating different weather APIs. 35 | Contributing 36 | Fork the repository: 37 | Create a new branch (git checkout -b feature-xyz). 38 | Make your changes and commit (git commit -am 'Add new feature'). 39 | Push to the branch (git push origin feature-xyz). 40 | Open a pull request. 41 | License: 42 | This project is licensed under the MIT License - see the LICENSE file for details. 43 | Acknowledgments: 44 | OpenWeatherMap API (or whichever weather API you use) for providing the weather data. 45 | Font Awesome for the icons used in the app (e.g., weather condition icons). 46 | -------------------------------------------------------------------------------- /search.js: -------------------------------------------------------------------------------- 1 | let apiKey = "1e3e8f230b6064d27976e41163a82b77"; 2 | let searchinput = document.querySelector(`.searchinput`); 3 | 4 | async function search(city, state, country){ 5 | let url = await fetch(`https://api.openweathermap.org/data/2.5/weather?units=metric&q=${city},${state},${country}&appid=${apiKey}`); 6 | 7 | if(url.ok){ 8 | let data = await url.json(); 9 | console.log(data); 10 | 11 | let box = document.querySelector(".return"); 12 | box.style.display = "block"; 13 | 14 | let message = document.querySelector(".message"); 15 | message.style.display = "none"; 16 | 17 | let errormessage = document.querySelector( ".error-message"); 18 | errormessage.style.display = "none"; 19 | 20 | let weatherImg = document.querySelector(".weather-img"); 21 | document.querySelector(".city-name").innerHTML = data.name; 22 | document.querySelector(".weather-temp").innerHTML = Math.floor(data.main.temp) + '°'; 23 | document.querySelector(".wind").innerHTML = Math.floor(data.wind.speed) + " m/s"; 24 | document.querySelector(".pressure").innerHTML = Math.floor(data.main.pressure) + " hPa"; 25 | document.querySelector('.humidity').innerHTML = Math.floor(data.main.humidity)+ "%"; 26 | document.querySelector(".sunrise").innerHTML = new Date(data.sys.sunrise * 1000).toLocaleTimeString([], {hour:"2-digit", minute:"2-digit"}); 27 | document.querySelector(".sunset").innerHTML = new Date(data.sys.sunset * 1000).toLocaleTimeString([], {hour:"2-digit", minute:"2-digit"}); 28 | 29 | if (data.weather[0].main === "Rain") { 30 | weatherImg.src = "rain.png"; 31 | } else if (data.weather[0].main === "Clear") { 32 | weatherImg.src = "sun.png"; 33 | } else if (data.weather[0].main === "Snow") { 34 | weatherImg.src = "snow.png"; 35 | } else if ( 36 | data.weather[0].main === "Clouds" || 37 | data.weather[0].main === "Smoke" 38 | ) { 39 | weatherImg.src = "cloud.png"; 40 | } else if ( 41 | data.weather[0].main === "Mist" || 42 | data.weather[0].main === "Fog" 43 | ) { 44 | weatherImg.src = "mist.png"; 45 | } else if (data.weather[0].main === "Haze") { 46 | weatherImg.src = "haze.png"; 47 | } 48 | }else{ 49 | let box = document.querySelector(".return"); 50 | box.style.display = "none"; 51 | 52 | let message = document.querySelector(".message"); 53 | message.style.display = "none"; 54 | 55 | let errormessage = document.querySelector( ".error-message"); 56 | errormessage.style.display = "block"; 57 | } 58 | } 59 | 60 | 61 | searchinput.addEventListener('keydown', function(event) { 62 | if (event.keyCode === 13 || event.which === 13) { 63 | search(searchinput.value); 64 | console.log("worked") 65 | } 66 | }); -------------------------------------------------------------------------------- /search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Document 12 | 13 | 14 | 15 |
16 | 17 | 24 | 25 |

Search For City

26 | 27 | 31 | 32 |
33 |

You have the option to search by city, state, or country names.

34 |
35 | 36 |
37 |

One of the specified locations (city, state, or country) was not found. Please try again

38 |
39 | 40 |
41 |
42 |
43 |
44 |
Landon
45 |
20°
46 |
47 |
48 |
49 | 50 |
51 |
52 |
53 |
Wind
54 |
15 m/s
55 |
56 | 57 |
58 |
59 |
Pressure
60 |
15 mbar
61 |
62 | 63 |
64 |
65 |
Humidity
66 |
50%
67 |
68 |
69 | 70 |
71 |
72 |
73 |
Sun Rise
74 |
12:00:00
75 |
76 | 77 |
78 |
79 |
Sun Set
80 |
12:00:00
81 |
82 | 83 |
84 |
85 |
86 |
87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /world.js: -------------------------------------------------------------------------------- 1 | let apiKey = "YOUR API"; 2 | //YOU CAN USE YOUR OWN API 3 | let searchinput = document.querySelector(".searchinput"); 4 | let box = document.querySelector(".box"); 5 | let normalMessage = document.querySelector(".normal-message"); 6 | let errorMessage = document.querySelector(".error-message"); 7 | let addedMessage = document.querySelector(".added-message"); 8 | 9 | // Function to get the date 10 | let date = new Date().getDate(); 11 | let months_name = [ 12 | "January", 13 | "February", 14 | "March", 15 | "April", 16 | "May", 17 | "June", 18 | "July", 19 | "August", 20 | "September", 21 | "October", 22 | "November", 23 | "December", 24 | ]; 25 | let months = new Date().getMonth(); 26 | let year = new Date().getFullYear(); 27 | 28 | let FullDate = document.querySelector(".date"); 29 | FullDate.innerHTML = `${months_name[months]} ${date}, ${year}`; 30 | 31 | // Weather info 32 | async function city(cityName) { 33 | let url = await fetch( 34 | `https://api.openweathermap.org/data/2.5/weather?units=metric&q=${cityName}&appid=${apiKey}` 35 | ); 36 | if (url.ok) { 37 | let data = await url.json(); 38 | console.log(data); 39 | 40 | let pcsreen = document.querySelector(".pc"); 41 | 42 | if (!box) { 43 | box = document.createElement("div"); 44 | box.className = "box"; 45 | pcsreen.appendChild(box); 46 | } 47 | 48 | let weatherBox = document.createElement("div"); 49 | weatherBox.className = "weather-box"; 50 | 51 | let nameDiv = document.createElement("div"); 52 | nameDiv.className = "name"; 53 | 54 | let cityElement = document.createElement("div"); 55 | cityElement.className = "city-name city"; 56 | cityElement.innerHTML = data.name; 57 | 58 | let tempElement = document.createElement("div"); 59 | tempElement.className = "weather-temp temp"; 60 | tempElement.innerHTML = Math.floor(data.main.temp) + "°"; 61 | 62 | let weatherIconDiv = document.createElement("div"); 63 | weatherIconDiv.className = "weather-icon"; 64 | 65 | let weatherImg = document.createElement("img"); 66 | weatherImg.className = "weather"; 67 | 68 | if (data.weather[0].main === "Rain") { 69 | weatherImg.src = "rain.png"; 70 | } else if (data.weather[0].main === "Clear") { 71 | weatherImg.src = "sun.png"; 72 | } else if (data.weather[0].main === "Snow") { 73 | weatherImg.src = "snow.png"; 74 | } else if ( 75 | data.weather[0].main === "Clouds" || 76 | data.weather[0].main === "Smoke" 77 | ) { 78 | weatherImg.src = "cloud.png"; 79 | } else if ( 80 | data.weather[0].main === "Mist" || 81 | data.weather[0].main === "Fog" 82 | ) { 83 | weatherImg.src = "mist.png"; 84 | } else if (data.weather[0].main === "Haze") { 85 | weatherImg.src = "haze.png"; 86 | } 87 | 88 | weatherIconDiv.appendChild(weatherImg); 89 | nameDiv.appendChild(cityElement); 90 | nameDiv.appendChild(tempElement); 91 | weatherBox.appendChild(nameDiv); 92 | weatherBox.appendChild(weatherIconDiv); 93 | box.appendChild(weatherBox); 94 | 95 | return weatherBox; 96 | } else { 97 | return ""; 98 | } 99 | } 100 | 101 | // add section 102 | let section = document.querySelector(".add-section"); 103 | let navBtn = document.querySelector(".button"); 104 | let navIcon = document.querySelector(".btn-icon"); 105 | 106 | navBtn.addEventListener("click", () => { 107 | if (section.style.top === "-60rem") { 108 | section.style.top = "100px"; 109 | navIcon.className = "fa-solid fa-circle-xmark"; 110 | } else { 111 | section.style.top = "-60rem"; 112 | navIcon.className = "fa-solid fa-circle-plus"; 113 | } 114 | }); 115 | 116 | searchinput.addEventListener("keydown", async function (event) { 117 | if (event.keyCode === 13 || event.which === 13) { 118 | const weatherInfo = await city(searchinput.value); 119 | if (weatherInfo) { 120 | normalMessage.style.display = "none"; 121 | errorMessage.style.display = "none"; 122 | addedMessage.style.display = "block"; 123 | } else { 124 | normalMessage.style.display = "none"; 125 | errorMessage.style.display = "block"; 126 | addedMessage.style.display = "none"; 127 | } 128 | box.prepend(weatherInfo); 129 | } 130 | }); 131 | 132 | city("London"); 133 | city("Paris"); 134 | city("Mumbai"); 135 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap"); 2 | * { 3 | padding: 0; 4 | margin: 0; 5 | box-sizing: border-box; 6 | list-style: none; 7 | font-family: "Rubik", sans-serif; 8 | } 9 | :root { 10 | --font-color-main: #332464; 11 | --white-color: #fff; 12 | } 13 | body { 14 | background-color: black; 15 | /*background-color: #e0eefa;*/ 16 | } 17 | .pc { 18 | width: 400px; 19 | height: 860px; 20 | margin-left: auto; 21 | margin-right: auto; 22 | border: 1px solid var(--font-color-main); 23 | border-radius: 40px; 24 | } 25 | 26 | nav { 27 | position: fixed; 28 | left: 0; 29 | right: 0; 30 | margin: 0 auto; 31 | width: fit-content; 32 | bottom: 5px; 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | width: 250px; 37 | height: 60px; 38 | border-radius: 40px; 39 | border: 2px solid var(--white-color); 40 | background-color: var(--font-color-main); 41 | } 42 | nav ul { 43 | display: flex; 44 | gap: 2pc; 45 | } 46 | nav ul li a { 47 | color: var(--white-color); 48 | font-size: 18px; 49 | } 50 | .active { 51 | background-color: var(--white-color); 52 | color: var(--font-color-main); 53 | border-radius: 100px; 54 | padding: 8px 15px; 55 | } 56 | 57 | #screen { 58 | width: 100%; 59 | height: 100vh; 60 | margin: 20px 0; 61 | } 62 | .city-name { 63 | color: var(--font-color-main); 64 | display: flex; 65 | justify-content: center; 66 | align-items: center; 67 | padding-top: 30px; 68 | gap: 5px; 69 | } 70 | .city-name i { 71 | font-size: 20px; 72 | } 73 | .weather-icon-css { 74 | display: flex; 75 | justify-content: center; 76 | align-items: center; 77 | width: 100%; 78 | height: 350px; 79 | margin-top: 10px; 80 | } 81 | .weather-icon-css img { 82 | width: 80%; 83 | } 84 | .weather-description { 85 | height: 150px; 86 | margin-top: 20px; 87 | display: flex; 88 | align-items: center; 89 | color: var(--font-color-main); 90 | /* border: 1px solid #000; */ 91 | } 92 | .show-metric { 93 | padding-left: 30px; 94 | font-size: 90px; 95 | font-weight: 550; 96 | } 97 | .weather-details { 98 | font-size: 14px; 99 | margin: 50px 20px 30px 10px; 100 | width: 100px; 101 | display: flex; 102 | flex-direction: column; 103 | } 104 | .weather-details .h-f { 105 | display: flex; 106 | gap: 5px; 107 | } 108 | .forcasts-box { 109 | display: flex; 110 | margin: 20px 0; 111 | color: var(--font-color-main); 112 | } 113 | .today-forecast { 114 | width: 100px; 115 | height: 160px; 116 | border-radius: 20px; 117 | margin-left: 15px; 118 | display: flex; 119 | gap: 5px; 120 | flex-direction: column; 121 | justify-content: center; 122 | align-items: center; 123 | background-color: var(--white-color); 124 | } 125 | .weather-icon-today img { 126 | width: 40px; 127 | } 128 | .temp-today { 129 | font-weight: 500; 130 | } 131 | .weather-main-today { 132 | padding: 3px 0 0 0; 133 | font-size: 13px; 134 | text-align: center; 135 | } 136 | .forecast { 137 | width: 65%; 138 | height: 160px; 139 | margin-left: 10px; 140 | border-radius: 20px; 141 | background-color: var(--white-color); 142 | } 143 | .forecast h5 { 144 | text-align: left; 145 | padding: 15px 0 0 15px; 146 | } 147 | #forecast-box { 148 | display: grid; 149 | grid-auto-flow: column; 150 | overflow-y: auto; 151 | gap: 10px; 152 | width: 95%; 153 | padding: 10px 12px; 154 | overscroll-behavior-x: contain; 155 | scroll-snap-type: x mandatory; 156 | scrollbar-width: none; 157 | } 158 | #forecast-box::-webkit-scrollbar { 159 | display: none; 160 | } 161 | .weather-forecast-box { 162 | width: 70px; 163 | height: 110px; 164 | border-radius: 15px; 165 | display: flex; 166 | text-align: center; 167 | flex-direction: column; 168 | justify-content: center; 169 | align-items: center; 170 | gap: 2px; 171 | flex-shrink: 0; 172 | align-items: center; 173 | border: 1px solid var(--font-color-main); 174 | } 175 | .day-weather { 176 | font-size: 15px; 177 | } 178 | .weather-icon-forecast img { 179 | width: 30px; 180 | } 181 | .temp-weather { 182 | font-size: 12px; 183 | } 184 | .weather-main-forecast { 185 | font-size: 12px; 186 | } 187 | 188 | @media (max-width: 400px) { 189 | /* 400 * 860 */ 190 | .pc { 191 | border: none; 192 | border-radius: none; 193 | width: auto; 194 | height: auto; 195 | } 196 | } -------------------------------------------------------------------------------- /search.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap"); 2 | * { 3 | padding: 0; 4 | margin: 0; 5 | box-sizing: border-box; 6 | list-style: none; 7 | font-family: "Rubik", sans-serif; 8 | } 9 | :root { 10 | --font-color-main: #332464; 11 | --white-color: #fff; 12 | } 13 | body { 14 | background-color: black; 15 | /* background-color: #e0eefa;*/ 16 | } 17 | .pc { 18 | width: 398px; 19 | height: 860px; 20 | margin-left: auto; 21 | margin-right: auto; 22 | border: 1px solid var(--font-color-main); 23 | border-radius: 40px; 24 | } 25 | 26 | nav { 27 | position: fixed; 28 | left: 0; 29 | right: 0; 30 | margin: 0 auto; 31 | width: fit-content; 32 | bottom: 5px; 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | width: 250px; 37 | height: 60px; 38 | border-radius: 40px; 39 | border: 2px solid var(--white-color); 40 | background-color: var(--font-color-main); 41 | } 42 | nav ul { 43 | display: flex; 44 | gap: 2pc; 45 | } 46 | nav ul li a { 47 | color: var(--white-color); 48 | font-size: 18px; 49 | } 50 | .active { 51 | background-color: var(--white-color); 52 | color: var(--font-color-main); 53 | border-radius: 100px; 54 | padding: 8px 15px; 55 | } 56 | h3 { 57 | color: var(--font-color-main); 58 | text-align: center; 59 | margin: 30px 0; 60 | } 61 | .search { 62 | width: 340px; 63 | height: 50px; 64 | margin-left: auto; 65 | margin-right: auto; 66 | border-radius: 40px; 67 | display: flex; 68 | justify-content: center; 69 | align-items: center; 70 | box-shadow: 1px 2px 2px var(--font-color-main); 71 | background-color: var(--white-color); 72 | } 73 | .search-icon { 74 | width: 18px; 75 | height: 50px; 76 | display: flex; 77 | border-radius: 20px; 78 | justify-content: center; 79 | align-items: center; 80 | } 81 | .search-icon i { 82 | font-size: 18px; 83 | color: var(--font-color-main); 84 | } 85 | .search input { 86 | width: 85%; 87 | padding: 10px; 88 | font-size: 15px; 89 | color: var(--font-color-main); 90 | border: none; 91 | outline: none; 92 | } 93 | .search input::placeholder { 94 | color: var(--font-color-main); 95 | } 96 | /* */ 97 | .error-message { 98 | display: none; 99 | } 100 | .error-message p { 101 | width: 100%; 102 | height: 500px; 103 | display: flex; 104 | justify-content: center; 105 | align-items: center; 106 | color: var(--font-color-main); 107 | text-align: center; 108 | padding: 40px; 109 | } 110 | /* */ 111 | .message { 112 | display: block; 113 | } 114 | .message p { 115 | width: 100%; 116 | height: 500px; 117 | display: flex; 118 | justify-content: center; 119 | align-items: center; 120 | color: var(--font-color-main); 121 | text-align: center; 122 | padding: 50px; 123 | } 124 | /* */ 125 | .return { 126 | display: none; 127 | } 128 | .box { 129 | max-width: 400px; 130 | height: auto; 131 | padding: 0 40px; 132 | margin-left: auto; 133 | margin-right: auto; 134 | border:1px solid black; 135 | margin-top: 40px; 136 | } 137 | .weather-box { 138 | height: 200px; 139 | max-width: 320px; 140 | border-radius: 40px; 141 | margin-top: 10px; 142 | display: flex; 143 | justify-content: center; 144 | align-items: center; 145 | background-color: var(--font-color-main); 146 | } 147 | .name { 148 | padding-left: 40px; 149 | width: 220px; 150 | display: flex; 151 | flex-direction: column; 152 | gap: 5px; 153 | color: var(--white-color); 154 | height: auto; 155 | } 156 | .city-name { 157 | font-size: 20px; 158 | } 159 | .weather-temp { 160 | font-size: 60px; 161 | } 162 | .weather-icon { 163 | padding: 0 20px; 164 | width: 220px; 165 | height: 170px; 166 | display: flex; 167 | align-items: center; 168 | justify-content: center; 169 | } 170 | .weather-icon img { 171 | width: 100%; 172 | } 173 | /* */ 174 | .weather-desc { 175 | display: flex; 176 | justify-content: center; 177 | column-gap: 10px; 178 | } 179 | .desc-box { 180 | width: 100px; 181 | display: grid; 182 | padding: 15px; 183 | gap: 5px; 184 | height: 100px; 185 | margin-top: 10px; 186 | border-radius: 20px; 187 | place-content: center; 188 | color: var(--white-color); 189 | background-color: var(--font-color-main); 190 | } 191 | 192 | @media (max-width: 400px) { 193 | .pc { 194 | border: none; 195 | border-radius: none; 196 | width: auto; 197 | height: auto; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /world.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap"); 2 | * { 3 | padding: 0; 4 | margin: 0; 5 | box-sizing: border-box; 6 | list-style: none; 7 | font-family: "Rubik", sans-serif; 8 | } 9 | :root { 10 | --font-color-main: #332464; 11 | --white-color: #fff; 12 | } 13 | body { 14 | background-color: black; 15 | /* background-color: you can choose more*/ 16 | } 17 | .pc { 18 | width: 400px; 19 | height: auto; 20 | margin-left: auto; 21 | margin-right: auto; 22 | border: 1px solid var(--font-color-main); 23 | border-radius: 40px; 24 | } 25 | nav { 26 | position: fixed; 27 | left: 0; 28 | right: 0; 29 | margin: 0 auto; 30 | width: fit-content; 31 | bottom: 5px; 32 | display: flex; 33 | justify-content: center; 34 | align-items: center; 35 | width: 250px; 36 | height: 60px; 37 | border: 2px solid var(--white-color); 38 | border-radius: 40px; 39 | background-color: var(--font-color-main); 40 | } 41 | nav ul { 42 | display: flex; 43 | gap: 2pc; 44 | } 45 | nav ul li a { 46 | color: var(--white-color); 47 | font-size: 18px; 48 | } 49 | .active { 50 | background-color: var(--white-color); 51 | color: var(--font-color-main); 52 | border-radius: 100px; 53 | padding: 8px 15px; 54 | } 55 | /* main section */ 56 | .section{ 57 | display: flex; 58 | justify-content: space-between; 59 | align-items: center; 60 | padding: 10px 40px; 61 | } 62 | .date { 63 | text-align: left; 64 | font-weight: 500; 65 | font-size: 20px; 66 | padding: 30px 0; 67 | color: var(--font-color-main); 68 | } 69 | .button{ 70 | font-size: 20px; 71 | color: var(--font-color-main); 72 | } 73 | /* section-box */ 74 | .section-box{ 75 | width: auto; 76 | height: 100%; 77 | padding: 0 80px; 78 | display: flex; 79 | justify-content: center; 80 | } 81 | .add-section{ 82 | min-width: 280px; 83 | height: 250px; 84 | top: -60rem; 85 | border-radius: 40px; 86 | border: 1px solid var(--white-color); 87 | position: absolute; 88 | transition: .4s ease-in; 89 | background-color: var(--font-color-main); 90 | } 91 | .add-section-title{ 92 | text-align: center; 93 | color: var(--white-color); 94 | padding-top: 40px; 95 | } 96 | .search { 97 | margin-top: 20px; 98 | width: 80%; 99 | height: 35px; 100 | margin-left: auto; 101 | margin-right: auto; 102 | border-radius: 40px; 103 | display: flex; 104 | justify-content: center; 105 | align-items: center; 106 | box-shadow: 1px 2px 2px var(--font-color-main); 107 | background-color: var(--white-color); 108 | } 109 | .search-icon { 110 | width: 15px; 111 | height: 50px; 112 | display: flex; 113 | border-radius: 20px; 114 | justify-content: center; 115 | align-items: center; 116 | } 117 | .search-icon i { 118 | font-size: 18px; 119 | color: var(--font-color-main); 120 | } 121 | .search input { 122 | width: 80%; 123 | padding: 8px; 124 | font-size: 15px; 125 | color: var(--font-color-main); 126 | border: none; 127 | outline: none; 128 | } 129 | .search input::placeholder { 130 | color: var(--font-color-main); 131 | } 132 | .messages{ 133 | color: var(--white-color); 134 | font-size: 15px; 135 | text-align: center; 136 | padding: 30px 0; 137 | font-weight: 500; 138 | margin-top: 10px; 139 | } 140 | .normal-message{ 141 | display: block; 142 | } 143 | .error-message{ 144 | display: none; 145 | } 146 | .added-message{ 147 | display: none; 148 | } 149 | .box { 150 | width: 100%; 151 | height: auto; 152 | display: flex; 153 | flex-wrap: wrap; 154 | justify-content: center; 155 | padding: 0 30px; 156 | align-items: center; 157 | margin-bottom: 40px; 158 | } 159 | .weather-box { 160 | height: 180px; 161 | min-width: 280px; 162 | border-radius: 40px; 163 | margin-top: 10px; 164 | display: flex; 165 | justify-content: center; 166 | align-items: center; 167 | background-color: var(--font-color-main); 168 | } 169 | .name { 170 | padding-left: 40px; 171 | width: 220px; 172 | display: flex; 173 | flex-direction: column; 174 | gap: 5px; 175 | color: var(--white-color); 176 | height: auto; 177 | } 178 | .city-name { 179 | font-size: 20px; 180 | } 181 | .weather-temp { 182 | font-size: 60px; 183 | } 184 | .weather-icon { 185 | padding: 0 20px; 186 | width: 220px; 187 | height: 170px; 188 | display: flex; 189 | align-items: center; 190 | justify-content: center; 191 | } 192 | .weather-icon img { 193 | width: 100%; 194 | } 195 | @media (max-width: 400px) { 196 | .pc { 197 | border: none; 198 | border-radius: none; 199 | width: auto; 200 | height: auto; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | let apiKey = "YOUR API"; 2 | //YOUR API 3 | 4 | navigator.geolocation.getCurrentPosition(async function (position) { 5 | 6 | try { 7 | var lat = position.coords.latitude; 8 | var lon = position.coords.longitude; 9 | //longitude and latitude are used to get city name 10 | var map = await fetch(`https://api.openweathermap.org/geo/1.0/reverse?lat=${lat}&lon=${lon}&limit=5&appid=${apiKey}`) 11 | var userdata = await map.json(); 12 | let loc = userdata[0].name; 13 | //By using City name we can get the weather details of that particular city from OpenWeatherMap API 14 | let url = `https://api.openweathermap.org/data/2.5/forecast?&units=metric&`; 15 | let respond = await fetch(url + `q=${loc}&` + `appid=${apiKey}`); 16 | let data = await respond.json(); 17 | 18 | console.log(data); 19 | 20 | // display current weather info 21 | let cityMain = document.getElementById("city-name"); 22 | let cityTemp = document.getElementById("metric"); 23 | let weatherMain = document.querySelectorAll("#weather-main"); 24 | let mainHumidity = document.getElementById("humidity"); 25 | let mainFeel = document.getElementById("feels-like"); 26 | let weatherImg = document.querySelector(".weather-icon"); 27 | let weatherImgs = document.querySelector(".weather-icons"); 28 | let tempMinWeather = document.getElementById("temp-min-today"); 29 | let tempMaxWeather = document.getElementById("temp-max-today"); 30 | 31 | cityMain.innerHTML = data.city.name; 32 | cityTemp.innerHTML = Math.floor(data.list[0].main.temp) + "°"; 33 | weatherMain[0].innerHTML = data.list[0].weather[0].description; 34 | weatherMain[1].innerHTML = data.list[0].weather[0].description; 35 | mainHumidity.innerHTML = Math.floor(data.list[0].main.humidity); 36 | mainFeel.innerHTML = Math.floor(data.list[0].main.feels_like); 37 | tempMinWeather.innerHTML = Math.floor(data.list[0].main.temp_min) + "°"; 38 | tempMaxWeather.innerHTML = Math.floor(data.list[0].main.temp_max) + "°"; 39 | 40 | let weatherCondition = data.list[0].weather[0].main.toLowerCase(); 41 | 42 | if (weatherCondition === "rain") { 43 | weatherImg.src = "rain.png"; 44 | weatherImgs.src = "rain.png"; 45 | } else if (weatherCondition === "clear" || weatherCondition === "clear sky") { 46 | weatherImg.src = "sun.png"; 47 | weatherImgs.src = "sun.png"; 48 | } else if (weatherCondition === "snow") { 49 | weatherImg.src = "snow.png"; 50 | weatherImgs.src = "snow.png"; 51 | } else if (weatherCondition === "clouds" || weatherCondition === "smoke") { 52 | weatherImg.src = "cloud.png"; 53 | weatherImgs.src = "cloud.png"; 54 | } else if (weatherCondition === "mist" || weatherCondition === "Fog") { 55 | weatherImg.src = "mist.png"; 56 | weatherImgs.src = "mist.png"; 57 | } else if (weatherCondition === "haze") { 58 | weatherImg.src = "haze.png" ; 59 | weatherImgs.src = "haze.png"; 60 | } 61 | 62 | // Fetch and display 5-day forecast data 63 | const forecastUrl = `https://api.openweathermap.org/data/2.5/forecast?q=${data.city.name}&appid=${apiKey}&units=metric`; 64 | 65 | fetch(forecastUrl) 66 | .then(response => response.json()) 67 | .then(data => { 68 | console.log("5-Day Forecast for", data.city.name); 69 | displayForecast(data); 70 | }) 71 | .catch(error => { 72 | console.error("Error fetching forecast:", error); 73 | }); 74 | 75 | function displayForecast(data) { 76 | const dailyForecasts = {}; 77 | let forecast = document.getElementById('forecast-box'); 78 | let forecastbox = ""; 79 | 80 | data.list.forEach(item => { 81 | const date = item.dt_txt.split(' ')[0]; 82 | let dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; 83 | let day = new Date(date).getDay(); 84 | 85 | if (!dailyForecasts[date]) { 86 | dailyForecasts[date] = { 87 | day_today: dayName[day], 88 | temperature: Math.floor(item.main.temp) + "°", 89 | description: item.weather[0].description, 90 | weatherImg: item.weather[0].main.toLowerCase() 91 | }; 92 | } 93 | }); 94 | 95 | for (const date in dailyForecasts) { 96 | let imgSrc = ""; 97 | 98 | switch (dailyForecasts[date].weatherImg) { 99 | case "rain": 100 | imgSrc = "img/rain.png"; 101 | break; 102 | case "clear": 103 | case "clear sky": 104 | imgSrc = "sun.png"; 105 | break; 106 | case "snow": 107 | imgSrc = "snow.png"; 108 | break; 109 | case "clouds": 110 | case "smoke": 111 | imgSrc = "cloud.png"; 112 | break; 113 | case "mist": 114 | imgSrc = "mist.png"; 115 | break; 116 | case "haze": 117 | imgSrc = "haze.png"; 118 | break; 119 | default: 120 | imgSrc = "sun.png"; 121 | } 122 | 123 | forecastbox += ` 124 |
125 |
126 | ${dailyForecasts[date].day_today} 127 |
128 |
129 | 130 |
131 |
132 | ${dailyForecasts[date].temperature} 133 |
134 |
${dailyForecasts[date].description}
135 |
`; 136 | } 137 | 138 | forecast.innerHTML = forecastbox; 139 | 140 | console.log(data); 141 | } 142 | } catch (error) { 143 | console.error("An error occurred:", error); 144 | } 145 | }, 146 | () => { 147 | // Handle location retrieval error 148 | alert("Please turn on your location and refresh the page"); 149 | }); 150 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | Weather App 15 | 16 | 17 | 18 |
19 | 20 | 155 | 156 |
157 | 158 |
159 | 160 |

Mumbai

161 |
162 | 163 |
164 | 165 |
166 | 167 |
168 |
169 |
170 |
Sunnen
171 |
172 |
H: 60
173 | || 174 |
175 | F: 60 176 |
177 |
178 |
179 |
180 | 181 |
182 |
183 |

TODAY

184 |
185 | 186 |
187 |
188 | 50°/ 55° 190 |
191 |
Sunnen
192 |
193 | 194 | 195 |
196 |
6-DAYS FORECAST
197 |
198 |
199 |
200 |
201 |
202 | 203 | 204 | 205 | 206 | --------------------------------------------------------------------------------