News App with HTML, CSS & JavaScript
30 DAYS 30 PROJECT CHALLENGE
Day #22
Project Overview
The News App is a beginner-friendly project built with HTML, CSS, and JavaScript that fetches and displays news articles based on a search topic. Users can enter a keyword such as India and click the search button to retrieve the latest matching headlines.
This project uses the Google News RSS feed as its news source. Since browsers can face cross-origin restrictions when requesting external feeds directly, the JavaScript sends the RSS URL through the AllOrigins service and then processes the returned content.
After receiving the response, JavaScript converts the RSS content into XML and extracts the available news items. The app then displays up to five headlines with a Read more link for each article. Additionally, it shows a loading message while the request is running and provides clear messages when no news is available or the request fails.
Key Features
- News Search: Users can enter any topic or keyword in the search field and click the Search button to find related news articles. The project also uses “India” as the default search when the input is empty.
- Dynamic News Fetching: The application retrieves news dynamically instead of storing fixed headlines inside the HTML. Therefore, users can search for different topics and receive different results.
- Google News RSS Feed: The project uses a Google News RSS search URL to retrieve news based on the entered query. This provides a simple way to work with external news data in a frontend project.
- Cross-Origin Handling: The RSS request passes through the AllOrigins service before the application processes it. As a result, the browser can receive the external feed without the project needing its own backend.
- Loading State: The application immediately displays
"Loading..."when a search begins. This gives users feedback while the news request is being processed. - News Headlines: After a successful request, the app extracts news titles from the RSS response and displays them inside individual news cards.
- Read More Links: Each displayed headline includes a direct link to the full article. The link opens in a new browser tab, allowing users to read the complete news story.
- Limited Results: The JavaScript displays only the first five news items from the returned RSS feed. This keeps the interface compact and prevents too many articles from filling the page.
- No Results Handling: If the RSS response does not contain any news items, the application displays a clear
"No news found"message instead of leaving the results section empty. - Error Handling: The project uses a
.catch()block to handle failed requests. If something goes wrong while loading the news, the app displays an"Error loading news"message. - Dynamic Rendering: JavaScript creates the news cards by reading the title and link from each RSS item. It then adds the generated HTML directly to the
newsListelement. - Simple Interface: The project uses a compact card layout with a search field, button, and news results area. Therefore, beginners can easily understand the relationship between the interface and the JavaScript functionality.
- Frontend-Based Project: The complete interface works with HTML, CSS, and JavaScript, while external services provide the news data. This makes the project useful for learning asynchronous data fetching and dynamic content rendering.
What You'll Learn
- How to fetch external data using JavaScript
fetch(). - How to create dynamic URLs using template literals.
- How
encodeURIComponent()safely prepares a search query for a URL. - How to work with RSS and XML data in a frontend application.
- How to use
DOMParserto convert returned content into an XML document. - How to select multiple XML elements using
querySelectorAll(). - How to read article titles and links from RSS
<item>elements. - How to use
forEach()to process multiple news items. - How to limit displayed results with an index check.
- How to dynamically generate HTML using
innerHTML. - How to handle loading, empty-result, and error states.
- How to open external article links in a new browser tab.
HTML Code
HTML creates the basic structure of the News App. The .news-container holds the complete application, while the <h2> displays the Latest News heading. Inside the .search-box, the #searchInput field allows users to enter a topic, and the Search button calls the getNews() function when clicked.
Additionally, the #newsList div starts empty and provides the area where JavaScript will display the news cards. Finally, the page loads script.js after the main HTML structure so the JavaScript can access and update these elements.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>News App</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="news-container">
<h2>Latest News</h2>
<div class="search-box">
<input id="searchInput" placeholder="Search topic (e.g. India)" />
<button onclick="getNews()">Search</button>
</div>
<div id="newsList"></div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS Code
CSS controls the layout and appearance of the News App. The universal selector applies box-sizing: border-box and sets Arial as the main font. Meanwhile, the body uses Flexbox to center the application on the page and gives it the dark blue background.
This .news-container creates the main white card with a fixed width, padding, and rounded corners. Next, .search-box uses Flexbox to place the input and button together, while the input and button selectors control their spacing and appearance.
The .news-card class separates each news result with a bottom border and spacing. The .news-card h4 selector adjusts the headline spacing, while .news-card a styles the Read more link. Finally, the .error class displays error messages in red and centers them inside the result area.
* {
box-sizing: border-box;
font-family: Arial, sans-serif;
}
body {
min-height: 100vh;
background: #042453;
display: flex;
justify-content: center;
align-items: center;
}
.news-container {
background: white;
width: 420px;
padding: 25px;
border-radius: 12px;
}
.search-box {
display: flex;
margin-bottom: 15px;
}
input {
flex: 1;
padding: 10px;
}
button {
padding: 10px 16px;
background: #4f46e5;
color: white;
border: none;
}
.news-card {
margin-bottom: 15px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.news-card h4 {
margin-bottom: 6px;
}
.news-card a {
color: #4f46e5;
font-size: 13px;
}
.error {
color: red;
text-align: center;
}
Javascript Code
JavaScript controls the complete news-fetching process. The getNews() function first reads the value from #searchInput and uses "India" when the field is empty. It then displays "Loading..." and creates the Google News RSS URL with encodeURIComponent(query) so the search term works correctly inside the URL.
Next, the code sends the RSS URL through the AllOrigins endpoint using fetch(). After receiving the response, res.json() extracts the returned data, and DOMParser converts data.contents into an XML document. The script then selects all <item> elements and checks whether any news articles exist.
If results are available, the code clears the loading message and loops through the items with forEach(). It limits the output to five articles and extracts each item’s title and link. Finally, it creates a .news-card for every result and adds a Read more link. If no items exist, the app shows "No news found", while the .catch() block displays "Error loading news" when the request fails.
const newsList = document.getElementById("newsList");
function getNews() {
const query = document.getElementById("searchInput").value || "India";
newsList.innerHTML = "Loading...";
const rssUrl = `https://news.google.com/rss/search?q=${encodeURIComponent(
query
)}&hl=en-IN&gl=IN&ceid=IN:en`;
fetch(`https://api.allorigins.win/get?url=${encodeURIComponent(rssUrl)}`)
.then(res => res.json())
.then(data => {
const parser = new DOMParser();
const xml = parser.parseFromString(data.contents, "text/xml");
const items = xml.querySelectorAll("item");
if (!items.length) {
newsList.innerHTML = "<p class='error'>No news found</p>";
return;
}
newsList.innerHTML = "";
items.forEach((item, index) => {
if (index >= 5) return;
const title = item.querySelector("title").textContent;
const link = item.querySelector("link").textContent;
newsList.innerHTML += `
<div class="news-card">
<h4>${title}</h4>
<a href="${link}" target="_blank">Read more</a>
</div>
`;
});
})
.catch(() => {
newsList.innerHTML = "<p class='error'>Error loading news</p>";
});
}
Related Projects
Day 20 : Form Auto-Save (Local Storage)
Automatically saves form input data and restores it on reload.
Concepts: LocalStorage usage, input event handling, persistent UI state.
Day 24 : Crypto Price Tracker
Displays real-time cryptocurrency prices using a public crypto API.
Concepts: API integration, async data fetching, dynamic UI updates.
Day 25 : Stock Price UI (Mock / API)
Displays stock prices and daily changes using mock data with API-ready structure.
Concepts: UI state management, dynamic rendering, data simulation.