Here’s a complete responsive weather app that fetches live weather data using the OpenWeatherMap API. The app displays current weather conditions, temperature, humidity, wind speed, and a 5-day forecast.
HTML (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Weather Forecast | CodeWithTanveer</title>
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"
/>
</head>
<body>
<div class="container">
<div class="search-container">
<input type="text" id="city-input" placeholder="Enter city name" />
<button id="search-btn"><i class="fas fa-search"></i></button>
<button id="location-btn"><i class="fas fa-location-arrow"></i></button>
</div>
<div class="weather-container">
<div class="current-weather">
<div class="location-date">
<h2 id="city-name">Loading...</h2>
<p id="current-date">--/--/----</p>
</div>
<div class="weather-info">
<div class="temperature">
<img
id="weather-icon"
src="https://openweathermap.org/img/wn/01d@2x.png"
alt="Weather Icon"
/>
<span id="current-temp">--°C</span>
</div>
<div class="details">
<p id="weather-desc">--</p>
<p>Humidity: <span id="humidity">--%</span></p>
<p>Wind: <span id="wind-speed">-- km/h</span></p>
</div>
</div>
</div>
<div class="forecast">
<h3>5-Day Forecast</h3>
<div class="forecast-cards" id="forecast-container">
<!-- Forecast cards will be inserted here by JavaScript -->
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS(style.css)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
width: 100%;
max-width: 800px;
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
padding: 30px;
transition: all 0.3s ease;
}
.search-container {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.search-container input {
flex: 1;
padding: 15px;
border: none;
border-radius: 10px;
font-size: 16px;
background: #f1f1f1;
transition: all 0.3s ease;
}
.search-container input:focus {
outline: none;
background: #e1e1e1;
}
.search-container button {
width: 50px;
height: 50px;
border: none;
border-radius: 10px;
background: #4a6fa5;
color: white;
font-size: 18px;
cursor: pointer;
transition: all 0.3s ease;
}
.search-container button:hover {
background: #3a5a8a;
}
.weather-container {
display: flex;
flex-direction: column;
gap: 20px;
}
.current-weather {
background: linear-gradient(135deg, #4a6fa5 0%, #3a5a8a 100%);
color: white;
border-radius: 15px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 15px;
}
.location-date h2 {
font-size: 24px;
font-weight: 600;
}
.location-date p {
font-size: 14px;
opacity: 0.8;
}
.weather-info {
display: flex;
justify-content: space-between;
align-items: center;
}
.temperature {
display: flex;
align-items: center;
gap: 10px;
}
.temperature img {
width: 80px;
height: 80px;
}
.temperature span {
font-size: 48px;
font-weight: 600;
}
.details p {
margin-bottom: 8px;
font-size: 16px;
}
.forecast {
background: white;
border-radius: 15px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}
.forecast h3 {
margin-bottom: 15px;
color: #333;
font-size: 18px;
}
.forecast-cards {
display: flex;
gap: 10px;
overflow-x: auto;
padding-bottom: 10px;
}
.forecast-card {
min-width: 120px;
background: #f8f9fa;
border-radius: 10px;
padding: 15px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.forecast-card p:first-child {
font-weight: 600;
color: #4a6fa5;
}
.forecast-card img {
width: 50px;
height: 50px;
}
.forecast-temp {
display: flex;
gap: 5px;
}
.max-temp {
color: #333;
font-weight: 600;
}
.min-temp {
color: #777;
}
/* Responsive styles */
@media (max-width: 768px) {
.container {
padding: 15px;
}
.weather-info {
flex-direction: column;
align-items: flex-start;
gap: 20px;
}
.temperature {
flex-direction: column;
align-items: flex-start;
}
.forecast-cards {
flex-wrap: wrap;
justify-content: center;
}
.forecast-card {
min-width: calc(50% - 10px);
}
}
@media (max-width: 480px) {
.forecast-card {
min-width: 100%;
}
.search-container input {
padding: 12px;
}
.search-container button {
width: 45px;
height: 45px;
}
}
Javascript(script.js)
// API key for OpenWeatherMap
const API_KEY = "YOUR_API_KEY";
// DOM elements
const cityInput = document.getElementById("city-input");
const searchBtn = document.getElementById("search-btn");
const locationBtn = document.getElementById("location-btn");
const cityName = document.getElementById("city-name");
const currentDate = document.getElementById("current-date");
const weatherIcon = document.getElementById("weather-icon");
const currentTemp = document.getElementById("current-temp");
const weatherDesc = document.getElementById("weather-desc");
const humidity = document.getElementById("humidity");
const windSpeed = document.getElementById("wind-speed");
const forecastContainer = document.getElementById("forecast-container");
// Create loader and error elements
const loader = document.createElement("div");
loader.className = "loader";
document.querySelector(".weather-container").prepend(loader);
const errorMessage = document.createElement("div");
errorMessage.className = "error-message";
document.querySelector(".weather-container").prepend(errorMessage);
// Format date
function formatDate(timestamp) {
const date = new Date(timestamp * 1000);
const options = {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
};
return date.toLocaleDateString("en-US", options);
}
// Format day for forecast
function formatDay(timestamp) {
const date = new Date(timestamp * 1000);
return date.toLocaleDateString("en-US", { weekday: "short" });
}
// Show loading state
function showLoading() {
loader.style.display = "block";
errorMessage.style.display = "none";
}
// Hide loading state
function hideLoading() {
loader.style.display = "none";
}
// Show error message
function showError(message) {
errorMessage.textContent = message;
errorMessage.style.display = "block";
hideLoading();
}
// Get weather data from API with improved error handling
async function getWeatherData(city) {
showLoading();
try {
// Fetch current weather
const currentResponse = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${API_KEY}`
);
if (!currentResponse.ok) {
const errorData = await currentResponse.json();
throw new Error(
errorData.message || "City not found. Please try another location."
);
}
const currentData = await currentResponse.json();
// Fetch forecast
const forecastResponse = await fetch(
`https://api.openweathermap.org/data/2.5/forecast?q=${city}&units=metric&appid=${API_KEY}`
);
if (!forecastResponse.ok) {
const errorData = await forecastResponse.json();
throw new Error(errorData.message || "Could not load forecast data.");
}
const forecastData = await forecastResponse.json();
hideLoading();
return { current: currentData, forecast: forecastData };
} catch (error) {
console.error("Error fetching weather data:", error);
showError(error.message);
return null;
}
}
// Display weather data
function displayWeatherData(data) {
if (!data) return;
const { current, forecast } = data;
// Update current weather
cityName.textContent = `${current.name}, ${current.sys.country}`;
currentDate.textContent = formatDate(current.dt);
currentTemp.textContent = `${Math.round(current.main.temp)}°C`;
weatherDesc.textContent = current.weather[0].description;
humidity.textContent = `${current.main.humidity}%`;
windSpeed.textContent = `${Math.round(current.wind.speed * 3.6)} km/h`;
weatherIcon.src = `https://openweathermap.org/img/wn/${current.weather[0].icon}@2x.png`;
weatherIcon.alt = current.weather[0].main;
// Update forecast
forecastContainer.innerHTML = "";
// Get one forecast per day (API returns forecast every 3 hours)
const dailyForecasts = [];
for (let i = 0; i < forecast.list.length; i += 8) {
dailyForecasts.push(forecast.list[i]);
}
dailyForecasts.slice(0, 5).forEach((day) => {
const forecastCard = document.createElement("div");
forecastCard.className = "forecast-card";
forecastCard.innerHTML = `
<p>${formatDay(day.dt)}</p>
<img src="https://openweathermap.org/img/wn/${
day.weather[0].icon
}.png" alt="${day.weather[0].main}">
<div class="forecast-temp">
<span class="max-temp">${Math.round(day.main.temp_max)}°</span>
<span class="min-temp">${Math.round(day.main.temp_min)}°</span>
</div>
`;
forecastContainer.appendChild(forecastCard);
});
}
// Get weather by city name
async function getWeatherByCity() {
const city = cityInput.value.trim();
if (!city) {
showError("Please enter a city name");
return;
}
const weatherData = await getWeatherData(city);
if (weatherData) {
displayWeatherData(weatherData);
}
}
// Get weather by current location
async function getWeatherByLocation() {
if (!navigator.geolocation) {
showError("Geolocation is not supported by your browser");
return;
}
showLoading();
navigator.geolocation.getCurrentPosition(
async (position) => {
const { latitude, longitude } = position.coords;
try {
// Get city name from coordinates
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&units=metric&appid=${API_KEY}`
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Location not found");
}
const data = await response.json();
cityInput.value = data.name;
getWeatherByCity();
} catch (error) {
console.error("Error fetching location data:", error);
showError(
"Error fetching your location. Please try searching manually."
);
}
},
(error) => {
console.error("Error getting location:", error);
showError(
"Location access denied. Please enable location services or search manually."
);
hideLoading();
}
);
}
// Event listeners
searchBtn.addEventListener("click", getWeatherByCity);
locationBtn.addEventListener("click", getWeatherByLocation);
cityInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
getWeatherByCity();
}
});
// Initialize with default city
window.addEventListener("load", () => {
cityInput.value = "Delhi";
getWeatherByCity();
});
How to Use This Weather App
- Get an API Key:
- Go to OpenWeatherMap and sign up for a free account
- Get your API key from the account dashboard
- Replace
YOUR_API_KEY_HERE
in the JavaScript file with your actual API key
- Features:
- Search for weather by city name
- Get weather for your current location
- View current weather conditions
- See a 5-day forecast
- Fully responsive design that works on mobile and desktop
- Files Structure:
weather-app/
├── index.html
├── styles.css
└── script.js
- To Run:
- Simply open the
index.html
file in a web browser - For best results, serve it through a local server (like Live Server in VS Code) to avoid CORS issues
- Simply open the
Note: The free tier of OpenWeatherMap API has some limitations (60 calls per minute). For heavy usage, consider upgrading to a paid plan.