How to Build a Weather App with HTML,CSS and Vanilla JavaScript

vaatiesther

vaatiesther

Posted on February 26, 2024

How to Build a Weather App with HTML,CSS and Vanilla JavaScript

The best way to learn JavaScript or any other programming language is by doing. In this tutorial, we will create a fully functioning weather app, and it will look like this:

HTML Structure

When building any project, it’s essential to have the design of how you want it to look. The HTML structure will look like this

<body>
    <div class="container">
      <div class="date">

        <p>Wednesday, 21st Feb 2024</p>
      </div>
      <div class="location">
        <input type="text" placeholder="Enter city" />
        <button class="fa-solid fa-magnifying-glass"></button>
      </div>

      <section class="weather hidden">
        <img src="" alt="" />
        <span class="cityName">Rome</span>
        <span class="description">clear clouds</span>
        <span class="temp">23°C</span>

      </section>

      <section class="weather-details hidden">
        <div class="wind">
          <p>Wind</p>
          <i class="fa-solid fa-wind"></i>
          <p class="speed">6.17</p>
        </div>
        <div class="humidity">
          <p>Humidity</p>
          <i class="fa-solid fa-droplet"></i>
          <p id="humidity">40</p>
        </div>
        <div class="feeling">
          <p>Feels</p>
          <i class="fa-solid fa-temperature-three-quarters"></i>
          <p id="feeeling">30°C</p>
        </div>
      </div>
    </section>

Enter fullscreen mode Exit fullscreen mode

We will replace the data dynamically with Javascript.

Styling with CSS

And here are the CSS styles:

  body {
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        background: #06283d;
      }

      .container {
        position: relative;
        width: 450px;
        height: 750px;
        background: #f0f0f0;
        padding: 18px 12px;
        overflow: hidden;
        border-radius: 18px;
        font-family: "Roboto", sans-serif;
        transition: 0.6s ease-out;
        border-radius: 30px;
      }

      .date {
        padding: 20px 32px;
        text-align: center;
      }
      .location {
        padding: 20px 32px;

        display: flex;
        align-items: center;
        justify-content: space-around;
      }
      .location input {
        /* color: #e26010; */
        width: 80%;
        background-color: #f0f0f0;
        font-size: 20px;
        font-weight: 500;
        margin-left: 22px;
      }
      .location button {
        cursor: pointer;
        width: 40px;
        height: 40px;
        color: #e35519;
        background: #e8dad1;
        border-radius: 50%;
        font-size: 22px;
        transition: 0.4s ease;
      }
      .weather {
        margin-bottom: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        gap: 20px;
      }
      .weather img {
        width: 50%;
      }
      .weather span{
        font-size: 24px;
        font-weight: 500;
      }

      .weather-details {
        background: #fff;
        border-radius: 40px;
        padding: 20px 32px;
        display: flex;
        align-items: center;
        justify-content: space-around;
      }
       .wind,
      .humidity,
      .feeeling {
        padding: 10px 22px;
      }

      .weather-details .wind p,
      .weather-details .humidity p,
      .weather-details .feeling p {
        margin: 8px 0;
      }

      .humidity i {
        color: rgb(73, 73, 220);
      }
      #feeeling i {
        color: orange;
      }

      .hidden {
        visibility: hidden;
      }

Enter fullscreen mode Exit fullscreen mode

Things to Note

The section with the class weather will display the general weather, like the city name, weather description, and current temperature.

The weather-details section will display the rest of the weather details. Both sections have the class hidden and will be hidden by default.

.hidden {
visibility: hidden;
}
Enter fullscreen mode Exit fullscreen mode

Once we get the Weather from the open weather API, we will use JavaScript to change the visibility of the sections.

Open Weather API

The Open Weather API is an organization that allows developers to get real-time data about the weather all over the world. To get the weather data, we need an API key. An API KEY is a secret key allowing us to authenticate ourselves when we request the data. Head to the Open weather API page and sign up for free to obtain your API Key.

There are multiple ways to get the weather data; you can use latitude and longitudes. However, the open weather provides a simple request that uses the city name as a parameter.

https://api.openweathermap.org/data/2.5/weather?q={city}&appid={APIKEY}
Enter fullscreen mode Exit fullscreen mode

The only thing required of you is to replace city with the city you want the weather for and APIKEY with your APIKEY. For exmplee, the endpoint for getting the weather in rome will look like this:

https://api.openweathermap.org/data/2.5/weather?q=rome&appid=04419024fb0f20edd3f1abd06e46dd6d
Enter fullscreen mode Exit fullscreen mode

If you paste this link on your browser, you will get this data

Weather App

From this data, we are in a position to extract the weather information.

JavaScript Functionality

Next, make a GET request to this endpoint using the fetch method to get the weather for the city provided by the user. In your JavaScript file, create a variable called currentDate and use the new Date constructor to get the current Date.

const currentDate = new Date();
Enter fullscreen mode Exit fullscreen mode

Display the current date at the top of the page.

const currentDate = document.querySelector(".date p");
currentDate.textContent = date
        .toString()
        .split(" ")
        .slice(0, 4)
        .join(" ");
Enter fullscreen mode Exit fullscreen mode

Next, select all the DOM elements that will be updated dynamically with JavaScript.

const currentDate = document.querySelector(".date p");
const searchButton = document.querySelector(".location button");
const weatherDetails = document.querySelector(".weather-details");
const weather = document.querySelector(".weather");
const image = document.querySelector(".weather img");
Enter fullscreen mode Exit fullscreen mode

Add an event listener to the search button. This event listener will listen for a click event.

searchButton.addEventListener("click", function () {
}
Enter fullscreen mode Exit fullscreen mode

Inside the function, we want to get the city name value from the input, perform a request using the fetch method, and print the data to the console.

const BASE_URL = ` https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${APIKEY}`;
console.log(BASE_URL);
fetch(BASE_URL)
.then((resp) => resp.json())
.then((data) => {
console.log(data);
});
Enter fullscreen mode Exit fullscreen mode

Logging the data is also essential to ensure the fetch request performs as expected.

As you can see, the request was successful. Next, we will create an if statement that will extract data from the weather if cod ===200, 200 means a successful response, we will then display the appropriate weather icon.

The data will be contained in the first Array of the weather key

data.weather[0].main
data.weather[0].icon
data.weather[0].description
Enter fullscreen mode Exit fullscreen mode
searchButton.addEventListener("click", function () {
  const city = document.querySelector(".location input").value;
  const APIKEY = "04419024fb0f20edd3f1abd06e46dd6d";
  const BASE_URL = ` https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${APIKEY}`;

  fetch(BASE_URL)
    .then((resp) => resp.json())
    .then((data) => {
      if (data.cod === 200) {

        const iconUrl = `http://openweathermap.org/img/wn/${data.weather[0].icon}.png`;
        image.src =iconUrl; 

        const description = document.querySelector(".description");
        const temp = document.querySelector(".temp");
        const cityName = document.querySelector(".cityName");
        cityName.textContent = data.name;
        description.textContent = data.weather[0].description;
        const roundedCelsius = Math.round(data.main.temp / 18.14);
        temp.textContent = `${roundedCelsius}°C `;
        weather.style.visibility = "visible";

      }
    });
});
Enter fullscreen mode Exit fullscreen mode

Let’s Summarise the code above.

The open weather API data comes with an icon code for each weather, which looks like this:

"weather": [
 {
 "id": 500,
 "main":"Rain",
 "description": "light rain",
 "icon": "10n"
 }
 ],
Enter fullscreen mode Exit fullscreen mode

We have extracted the icon from the data and used it to construct the URL for the weather icon image.

Outside of the if statement, we are updating the city name, weather description, and the current temperature. Finally, we are setting the visibility of the element with the class weather to be visible. Now, if you search any city, you will get the following information.

The final step is to display

  • Wind
  • Pressure
  • Feels like

Get the DOM elements:

const windSpeed = document.querySelector(".speed");
const humidity = document.getElementById("humidity");


const feeeling = document.getElementById("feeeling");
Enter fullscreen mode Exit fullscreen mode

Update the text content and change the visibility of the weather details element.


windSpeed.textContent = `{data.wind.speed}m/s`;
humidity.textContent = `${data.main["humidity"]}%`;
feeeling.textContent = `${Math.round(data.main["feels_like"]/18.14)} °C`;
weatherDetails.style.visibility = "visible";
weather.style.visibility = "visible";
Enter fullscreen mode Exit fullscreen mode

Conclusion

Here is the Codepen. You can fork it and update the features of the weather app.

Subscribe to my Practical JavaScript Substack and master JavaScript by building projects, along with other talented developers who read it weekly.

💖 💪 🙅 🚩
vaatiesther
vaatiesther

Posted on February 26, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related