weather app

Responsive Weather App with Live Weather Data

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

  1. 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
  2. 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
  3. Files Structure:
weather-app/
├── index.html
├── styles.css
└── script.js
  1. 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

Note: The free tier of OpenWeatherMap API has some limitations (60 calls per minute). For heavy usage, consider upgrading to a paid plan.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *