Bulid a web page that fetches weather data from a weather API based on the user’s location or a user inputted location display the current weather conditions temperature and other relevant information

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Quick Weather App</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
        }

    body {
        background: #f0f4f8;
        color: #333;
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
        padding: 20px;
    }

    .weather-card {
        background: white;
        padding: 30px;
        border-radius: 16px;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
        width: 100%;
        max-width: 400px;
        text-align: center;
    }

    h1 {
        font-size: 24px;
        margin-bottom: 20px;
        color: #1e293b;
    }

    .search-box {
        display: flex;
        gap: 8px;
        margin-bottom: 15px;
    }

    input {
        flex: 1;
        padding: 10px 14px;
        border: 1px solid #cbd5e1;
        border-radius: 8px;
        font-size: 16px;
        outline: none;
    }

    input:focus {
        border-color: #3b82f6;
    }

    button {
        padding: 10px 16px;
        background: #3b82f6;
        color: white;
        border: none;
        border-radius: 8px;
        cursor: pointer;
        font-weight: 600;
        transition: background 0.2s;
    }

    button:hover {
        background: #2563eb;
    }

    .geo-btn {
        width: 100%;
        background: #10b981;
        margin-bottom: 25px;
    }

    .geo-btn:hover {
        background: #059669;
    }

    .hidden {
        display: none !important;
    }

    /* Weather Info Display Styling */
    .location-name {
        font-size: 20px;
        font-weight: 600;
        color: #475569;
        margin-bottom: 8px;
    }

    .temp-display {
        font-size: 54px;
        font-weight: 700;
        color: #1e293b;
        margin-bottom: 10px;
    }

    .condition {
        font-size: 18px;
        text-transform: capitalize;
        color: #64748b;
        margin-bottom: 20px;
    }

    .details-grid {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 12px;
        border-top: 1px solid #e2e8f0;
        padding-top: 20px;
    }

    .detail-item {
        background: #f8fafc;
        padding: 10px;
        border-radius: 8px;
        font-size: 14px;
    }

    .detail-label {
        color: #94a3b8;
        margin-bottom: 4px;
        font-size: 12px;
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }

    .detail-value {
        font-weight: 600;
        color: #334155;
    }

    .error-msg {
        color: #ef4444;
        background: #fef2f2;
        padding: 10px;
        border-radius: 8px;
        font-size: 14px;
        margin-top: 15px;
    }
</style>

</head>
<body>

<div class="weather-card">
    <h1>Weather Forecast</h1>
    
    <div class="search-box">
        <input type="text" id="city-input" placeholder="Enter city name (e.g., Paris)">
        <button id="search-btn">Search</button>
    </div>

    <button id="geo-btn" class="geo-btn">📍 Use Current Location</button>

    <!-- Status/Error Box -->
    <div id="status-message" class="error-msg hidden"></div>

    <!-- Weather Display Block -->
    <div id="weather-info" class="hidden">
        <div class="location-name" id="display-location">---</div>
        <div class="temp-display" id="display-temp">--°C</div>
        <div class="condition" id="display-condition">---</div>
        
        <div class="details-grid">
            <div class="detail-item">
                <div class="detail-label">Humidity</div>
                <div class="detail-value" id="display-humidity">--%</div>
            </div>
            <div class="detail-item">
                <div class="detail-label">Wind Speed</div>
                <div class="detail-value" id="display-wind">-- km/h</div>
            </div>
        </div>
    </div>
</div>

<script>
    // Mapping Open-Meteo WMO weather codes to human-readable text
    const weatherCodes = {
        0: "Clear sky",
        1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast",
        45: "Fog", 48: "Depositing rime fog",
        51: "Light drizzle", 53: "Moderate drizzle", 55: "Dense drizzle",
        61: "Slight rain", 63: "Moderate rain", 65: "Heavy rain",
        71: "Slight snow fall", 73: "Moderate snow fall", 75: "Heavy snow fall",
        77: "Snow grains",
        80: "Slight rain showers", 81: "Moderate rain showers", 82: "Violent rain showers",
        85: "Slight snow showers", 86: "Heavy snow showers",
        95: "Thunderstorm", 96: "Thunderstorm with slight hail", 99: "Thunderstorm with heavy hail"
    };

    const cityInput = document.getElementById('city-input');
    const searchBtn = document.getElementById('search-btn');
    const geoBtn = document.getElementById('geo-btn');
    const statusMsg = document.getElementById('status-message');
    const weatherInfo = document.getElementById('weather-info');

    // Event Listeners
    searchBtn.addEventListener('click', handleCitySearch);
    cityInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleCitySearch(); });
    geoBtn.addEventListener('click', handleGeolocation);

    // Option 1: Search by City Name
    async function handleCitySearch() {
        const cityName = cityInput.value.trim();
        if (!cityName) return showStatus("Please enter a city name.");

        showStatus("Searching for city...", false);
        try {
            // Open-Meteo uses Geocoding API to convert city names to Latitude/Longitude
            const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(cityName)}&count=1&language=en&format=json`;
            const response = await fetch(geoUrl);
            const data = await response.json();

            if (!data.results || data.results.length === 0) {
                throw new Error("City not found. Try checking the spelling.");
            }

            const result = data.results[0];
            const displayName = `${result.name}, ${result.country}`;
            
            fetchWeatherData(result.latitude, result.longitude, displayName);
        } catch (error) {
            showStatus(error.message);
        }
    }

    // Option 2: Get Browser Coordinates
    function handleGeolocation() {
        if (!navigator.geolocation) {
            return showStatus("Geolocation is not supported by your browser.");
        }

        showStatus("Requesting location access...", false);
        navigator.geolocation.getCurrentPosition(
            (position) => {
                const lat = position.coords.latitude;
                const lon = position.coords.longitude;
                fetchWeatherData(lat, lon, "Your Location");
            },
            (error) => {
                showStatus("Location access denied or unavailable.");
            }
        );
    }

    // Main function to query the Weather API
    async function fetchWeatherData(lat, lon, locationLabel) {
        try {
            const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&current=temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m`;
            const response = await fetch(weatherUrl);
            
            if (!response.ok) throw new Error("Failed to retrieve weather data.");
            
            const data = await response.json();
            renderWeather(data.current, locationLabel);
        } catch (error) {
            showStatus(error.message);
        }
    }

    // Display data onto the UI
    function renderWeather(currentData, locationName) {
        statusMsg.classList.add('hidden'); // Hide any errors
        
        document.getElementById('display-location').textContent = locationName;
        document.getElementById('display-temp').textContent = `${Math.round(currentData.temperature_2m)}°C`;
        document.getElementById('display-humidity').textContent = `${currentData.relative_humidity_2m}%`;
        document.getElementById('display-wind').textContent = `${currentData.wind_speed_10m} km/h`;
        
        // Translate the WMO numeric weather code to descriptive text
        const conditionText = weatherCodes[currentData.weather_code] || "Unknown Conditions";
        document.getElementById('display-condition').textContent = conditionText;

        weatherInfo.classList.remove('hidden');
    }

    // Helper to handle messages / errors
    function showStatus(msg, isError = true) {
        statusMsg.textContent = msg;
        statusMsg.classList.remove('hidden');
        if (isError) {
            statusMsg.style.background = '#fef2f2';
            statusMsg.style.color = '#ef4444';
            weatherInfo.classList.add('hidden');
        } else {
            statusMsg.style.background = '#f0fdf4';
            statusMsg.style.color = '#15803d';
        }
    }
</script>

</body>
</html>

Welcome there,

Do you have a question? Or are you posting this for I Built This ?

The more you say, the more we can help.