Create Real-Time News App with HTML, CSS, and JavaScript

Faraz

By Faraz -

Learn how to create a real-time news app using HTML, CSS, and JavaScript. Follow step-by-step instructions to build your own news aggregator with ease.


create-real-time-news-app-with-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

Building a real-time news app is a great way to learn how to integrate APIs and display dynamic content on a website. With the help of HTML, CSS, and JavaScript, you can create a simple yet powerful news aggregator that pulls live data from an external source. In this tutorial, we'll be using the GNews API, which offers a free plan that provides 100 requests per day, making it a perfect choice for personal projects. However, if you're planning to use the API for business purposes or need more requests, you can purchase a paid plan for increased limits. By the end of this guide, you'll have a fully functional app that fetches the latest headlines and displays them in an easy-to-read format, with the ability to customize and expand your app as you progress.

Prerequisites:

Before we start, ensure you have:

  • Basic knowledge of HTML, CSS, and JavaScript.
  • A code editor like Visual Studio Code.
  • An API key from a news provider like GNews (you can get one for free).

Source Code

Step 1 (HTML Code):

Start by creating an index.html file. This file will contain the basic structure of your news app. Let's break down the HTML code:

1. Document Declaration

<!DOCTYPE html>
  • Specifies the document type and version of HTML (HTML5 in this case).

2. HTML Tag

<html lang="en">
  • The root element of the document, with the language set to English (lang="en").

3. Head Section

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>News Aggregator</title>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap">
  <link rel="stylesheet" href="styles.css">
</head>
  • <meta charset="UTF-8">: Specifies the character encoding for the document as UTF-8.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Ensures the page is responsive and scales properly on different devices.
  • <title>News Aggregator</title>: Sets the title of the page, which appears in the browser tab.
  • <script src="https://cdn.jsdelivr.net/"></script>: Includes the Axios library for making HTTP requests.
  • <link rel="stylesheet" href="https://fonts.googleapis.com/">: Imports the Poppins font from Google Fonts.
  • <link rel="stylesheet" href="styles.css">: Links to an external CSS file (styles.css) for styling the page.

4. Body Section

<body>
  <div class="header">
    <h1>News Aggregator</h1>
  </div>
  <div class="search-bar">
    <input type="text" id="search" placeholder="Search news...">
    <button onclick="handleSearch()">Search</button>
  </div>
  <div class="categories">
    <button onclick="filterNews('general')">General</button>
    <button onclick="filterNews('sports')">Sports</button>
    <button onclick="filterNews('technology')">Technology</button>
    <button onclick="filterNews('entertainment')">Entertainment</button>
  </div>
  <div class="news-container" id="news-container"></div>
  <script src="script.js"></script>
</body>
  • Header Section:
    • Contains a <h1> element displaying the title "News Aggregator".
  • Search Bar:
    • Includes an <input> field for entering search queries (id="search"), and a <button> that triggers the handleSearch() function when clicked.
  • Categories:
    • Four buttons (General, Sports, Technology, Entertainment), each triggering the filterNews() function with a corresponding category when clicked.
  • News Container:
    • A <div> with id="news-container" where the news articles will be dynamically displayed.

5. External Scripts

<script src="script.js"></script>
  • Links to an external JavaScript file (script.js) which will contain the logic for handling search and filtering news.

Step 2 (CSS Code):

Next, create a styles.css file to style your news app. This will make the app look more attractive and user-friendly. Here's a breakdown of each section:

1. Body Styling

body {
  font-family: 'Poppins', sans-serif;
  margin: 0;
  padding: 0;
  background-color: #f0f4f8;
  color: #333;
}
  • Font: Sets the default font to 'Poppins', with a fallback to sans-serif.
  • Margins and Padding: Removes any default margin and padding for the body to ensure consistent layout.
  • Background: Sets a light grayish-blue background (#f0f4f8).
  • Text Color: Sets the text color to a dark gray (#333).

2. Header Styling

.header {
  background-color: #825cff;
  color: #fff;
  text-align: center;
  padding: 1rem;
  position: sticky;
  top: 0;
  z-index: 1000;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.header h1 {
  margin: 0;
  font-size: 1.8rem;
}
  • Background Color: Sets a purple background color (#825cff).
  • Text Color: Sets the text color to white (#fff).
  • Text Alignment: Centers the text inside the header.
  • Padding: Adds 1rem padding around the header.
  • Sticky Position: Makes the header stick to the top of the page when scrolling (position: sticky; top: 0).
  • Z-index: Ensures the header stays above other content.
  • Box Shadow: Adds a subtle shadow below the header for depth.
  • Header Text: The <h1> inside the header has no margin and a larger font size (1.8rem).

3. Search Bar Styling

.search-bar {
  display: flex;
  justify-content: center;
  margin: 1rem auto;
  gap: 0.5rem;
  max-width: 800px;
}
.search-bar input {
  font-family: 'Poppins', sans-serif;
  flex: 1;
  padding: 0.7rem;
  border: 1px solid #ccc;
  border-radius: 5px;
  font-size: 1rem;
}
.search-bar button {
  font-family: 'Poppins', sans-serif;
  padding: 0.7rem 1rem;
  background-color: #cc2119;
  color: white;
  border: none;
  border-radius: 5px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
.search-bar button:hover {
  background-color: #a31a14;
}
  • Search Bar Layout: Uses Flexbox to center the search bar and its elements, with a gap between the input and button.
  • Input Field:
    • Takes up available space (flex: 1).
    • Styled with padding, a light gray border (#ccc), and rounded corners (border-radius: 5px).
    • Font size is set to 1rem.
  • Search Button:
    • Red background (#cc2119), white text, and rounded corners.
    • Changes to a darker red on hover (#a31a14).
    • Has a smooth transition effect on hover.

4. Categories Styling

.categories {
  display: flex;
  justify-content: center;
  gap: 1rem;
  margin: 1rem auto;
  flex-wrap: wrap;
}
.categories button {
  font-family: 'Poppins', sans-serif;
  padding: 0.7rem 1.2rem;
  background-color: #825cff;
  color: white;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: background-color 0.3s ease;
}
.categories button:hover {
  background-color: #693bcc;
}
  • Categories Layout:
    • Uses Flexbox to center the category buttons and allow them to wrap when necessary.
    • Provides a gap of 1rem between buttons.
  • Category Buttons:
    • Styled with a purple background (#825cff), white text, and rounded corners (border-radius: 20px).
    • The background changes to a darker purple (#693bcc) when hovered.
    • Smooth background transition effect on hover.

5. News Container Styling

.news-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.5rem;
  margin: 1rem auto;
  max-width: 1200px;
  padding: 0 1rem;
}
  • Grid Layout: Uses CSS Grid to display news cards in a flexible grid layout.
    • grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)): Automatically adjusts the number of columns based on screen size, with each column being at least 300px wide.
    • gap: 1.5rem: Adds space between grid items.
    • max-width: 1200px: Limits the container's width to 1200px.
    • padding: 0 1rem: Adds padding on the left and right sides.

6. News Card Styling

.news-card {
  background-color: #fff;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}
.news-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
}
.news-card img {
  width: 100%;
  height: 180px;
  object-fit: cover;
}
.news-card .content {
  padding: 1rem;
}
.news-card h2 {
  margin: 0 0 0.5rem;
  font-size: 1.2rem;
  color: #333;
}
.news-card p {
  margin: 0 0 1rem;
  color: #666;
  font-size: 0.9rem;
}
.news-card a {
  text-decoration: none;
  color: #cc2119;
  font-weight: bold;
}
.news-card a:hover {
  text-decoration: underline;
}
  • News Card Layout:
    • Each news card has a white background, rounded corners (border-radius: 10px), and a subtle shadow for depth.
    • On hover, the card slightly moves up (transform: translateY(-5px)) and the shadow becomes more prominent.
  • Image:
    • The image takes up the full width of the card and has a fixed height of 180px. It uses object-fit: cover to ensure it covers the area without distorting.
  • Content:
    • Padding is added to the content area of the card.
  • Headings and Text:
    • The title (h2) has a margin, larger font size (1.2rem), and dark color (#333).
    • The paragraph (p) has a smaller font size (0.9rem), gray color (#666), and bottom margin.
  • Links:
    • The links inside the card are styled with a red color (#cc2119), bold font, and no underline.
    • On hover, the underline appears.
body {
  font-family: 'Poppins', sans-serif;
  margin: 0;
  padding: 0;
  background-color: #f0f4f8;
  color: #333;
}

/* Header */
.header {
  background-color: #825cff;
  color: #fff;
  text-align: center;
  padding: 1rem;
  position: sticky;
  top: 0;
  z-index: 1000;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.header h1 {
  margin: 0;
  font-size: 1.8rem;
}

/* Search Bar */
.search-bar {
  display: flex;
  justify-content: center;
  margin: 1rem auto;
  gap: 0.5rem;
  max-width: 800px;
}
.search-bar input {
  font-family: 'Poppins', sans-serif;
  flex: 1;
  padding: 0.7rem;
  border: 1px solid #ccc;
  border-radius: 5px;
  font-size: 1rem;
}
.search-bar button {
  font-family: 'Poppins', sans-serif;
  padding: 0.7rem 1rem;
  background-color: #cc2119;
  color: white;
  border: none;
  border-radius: 5px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
.search-bar button:hover {
  background-color: #a31a14;
}

/* Categories */
.categories {
  display: flex;
  justify-content: center;
  gap: 1rem;
  margin: 1rem auto;
  flex-wrap: wrap;
}
.categories button {
  font-family: 'Poppins', sans-serif;
  padding: 0.7rem 1.2rem;
  background-color: #825cff;
  color: white;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: background-color 0.3s ease;
}
.categories button:hover {
  background-color: #693bcc;
}

/* News Container */
.news-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.5rem;
  margin: 1rem auto;
  max-width: 1200px;
  padding: 0 1rem;
}
.news-card {
  background-color: #fff;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}
.news-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
}
.news-card img {
  width: 100%;
  height: 180px;
  object-fit: cover;
}
.news-card .content {
  padding: 1rem;
}
.news-card h2 {
  margin: 0 0 0.5rem;
  font-size: 1.2rem;
  color: #333;
}
.news-card p {
  margin: 0 0 1rem;
  color: #666;
  font-size: 0.9rem;
}
.news-card a {
  text-decoration: none;
  color: #cc2119;
  font-weight: bold;
}
.news-card a:hover {
  text-decoration: underline;
} 

Step 3 (JavaScript Code):

Now, let’s write the JavaScript to fetch and display news articles from the GNews API. Here's a breakdown of each part:

1. Constants:

  • API_KEY: Holds the GNews API key, which is required to authenticate requests to the GNews API.
  • BASE_URL: The base URL for the GNews API, which is used to fetch news articles.

2. fetchNews(query, topic) Function:

  • This function fetches news articles from the GNews API based on optional search parameters (query and topic).
  • The URL is dynamically constructed using the BASE_URL, API key, and optional query (search term) and topic (category) parameters.
  • axios.get(url) sends a GET request to the API and retrieves the news articles.
  • If the request is successful, it calls the displayNews() function to display the articles.
  • If an error occurs, it logs the error and displays an error message on the page.

3. displayNews(articles) Function:

  • This function takes the articles array (fetched from the API) and displays them on the page.
  • It first clears the news-container element.
  • If no articles are found, it displays a message saying no articles were found.
  • For each article, it creates a div with the class news-card and populates it with the article's details (title, description, publish date, source, and image).
  • The newsCard is then appended to the news-container element.

4. handleSearch() Function:

  • This function is triggered when the user performs a search.
  • It gets the value from the search input field, trims any extra spaces, and checks if it's not empty.
  • If the search term is valid, it calls fetchNews() with the search term.
  • If the search input is empty, it shows an alert asking the user to enter a search term.

5. filterNews(topic) Function:

  • This function is used to filter news articles by a specific topic.
  • It calls fetchNews() with the given topic to fetch news articles related to that topic.

6. DOMContentLoaded Event Listener:

  • This event listener waits for the page to load and then calls fetchNews() to fetch the default news (i.e., news without any search term or topic).
const API_KEY = '2dd67da342577a207e6322bc4248e442'; // Replace with your GNews API key
const BASE_URL = 'https://gnews.io/api/v4';

async function fetchNews(query = '', topic = '') {
  const url = `${BASE_URL}/top-headlines?lang=en&country=us${
    query ? `&q=${query}` : ''
  }${topic ? `&topic=${topic}` : ''}&token=${API_KEY}`;
  console.log(url);
  try {
    const response = await axios.get(url);
    displayNews(response.data.articles);
  } catch (error) {
    console.error('Error fetching news:', error);
    const newsContainer = document.getElementById('news-container');
    newsContainer.innerHTML =
      '<p>Error fetching news. Please try again later.</p>';
  }
}

function displayNews(articles) {
  const newsContainer = document.getElementById('news-container');
  newsContainer.innerHTML = '';

  if (articles.length === 0) {
    newsContainer.innerHTML =
      '<p>No news articles found. Try a different search term or category.</p>';
    return;
  }

  articles.forEach((article) => {
    const newsCard = document.createElement('div');
    newsCard.className = 'news-card';

    const publishDate = new Date(article.publishedAt).toLocaleDateString(
      'en-US',
      {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
      }
    );

    newsCard.innerHTML = `
        <img src="${
          article.image ||
          'https://codewithfaraz.com/tools/placeholder?size=300x200'
        }" alt="News Image">
        <div class="content">
          <h2>${article.title}</h2>
          <p>${article.description || 'No description available.'}</p>
          <p><strong>Published:</strong> ${publishDate}</p>
          <p><strong>Source:</strong> ${article.source.name || 'Unknown'}</p>
          <a href="${article.url}" target="_blank">Read More</a>
        </div>
      `;
    newsContainer.appendChild(newsCard);
  });
}

function handleSearch() {
  const searchInput = document.getElementById('search').value.trim();
  if (searchInput) {
    fetchNews(searchInput);
  } else {
    alert('Please enter a search term.');
  }
}

function filterNews(topic) {
  fetchNews('', topic);
}

document.addEventListener('DOMContentLoaded', () => {
  fetchNews(); // Fetch default news on page load
});

Final Output:

create-real-time-news-app-with-html-css-and-javascript.gif

Conclusion:

Creating a real-time news app using HTML, CSS, and JavaScript opens up endless possibilities for customization and further learning. You can enhance the app by adding features like topic filtering, saving articles, or even integrating more APIs. With the skills gained from this project, you'll be able to build other dynamic applications and improve your web development abilities. Keep experimenting with new ideas, and soon you'll be creating more advanced projects that integrate real-time data seamlessly.

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺