Introduction:
In this tutorial, we will create a dynamic web application that generates random quotes and allows users to save their favorite quotes. We’ll be using HTML, CSS, and JavaScript to build this project. By the end of this tutorial, you’ll have a fully functional quote generator that you can use to discover and save inspiring quotes.
Things You Will Learn:
By following this tutorial, you will learn the following key concepts:
- How to fetch data from an external API (in this case, a random quote generator API).
- Manipulating the DOM (Document Object Model) using JavaScript.
- Saving data to and retrieving data from local storage.
- Building a user-friendly web interface with HTML and CSS.
Video Tutorial:
If you are interested to learn by watching a video tutorial rather than reading a blog post you can check out the video down below. Also, subscribe to my YouTube channel where I post new tutorials every alternate day.
Project Folder Structure:
Before we start coding we take a look at the project folder structure. We begin by creating a folder called – ”Random Quote Generator With Local Storage”. Inside this folder, we have 3 files. These files are :
- index.html
- style.css
- script.js
HTML:
We begin with the HTML code. Copy the code below and paste it into your HTML document.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Random Quote Generator</title> <!-- Font Awesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" /> <!-- Google Font --> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet" /> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="wrapper"> <div class="container"> <div class="button-container"> <button id="favourite"><i class="fa-regular fa-heart"></i></button> <button id="show-list"> <i class="fa-solid fa-list"></i> </button> <button id="copy"><i class="fa-solid fa-copy"></i></button> </div> <p id="quote"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Voluptas, magni. </p> <h3 id="author">Lorem, ipsum.</h3> <button id="btn">Generate</button> </div> </div> <div class="favorite-container"> <h3>Favorite Quotes</h3> <ul id="list-of-favourite-quotes"></ul> <button id="clear-button">Clear</button> <button id="close-favorite">Close</button> </div> <script src="./script.js"></script> </body> </html>
Â
CSS:
Next, we style our code using CSS. For this copy, the code provided to you below and paste it into your stylesheet.
* { padding: 0; margin: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body { background-color: #f7f7ff; } .wrapper, .favorite-container { width: min(500px, 90%); position: absolute; transform: translate(-50%, -50%); top: 50%; left: 50%; padding: 5em 3em; box-shadow: 0 5px 40px 0 rgba(88, 83, 153, 0.15); border-radius: 1em; background-color: rgb(69, 121, 225); } .container { text-align: center; } .container p { color: #d6d6d6; margin: 1em 0 1.5em 0; } .container h3 { color: #ffffff; } .wrapper #btn, .favorite-container button { background-color: #ffffff; border: none; padding: 1em 2em; border-radius: 3em; margin-top: 4em; } .button-container { display: flex; justify-content: end; gap: 1em; } .button-container button { background-color: transparent; border: none; color: #ffffff; font-size: 1.2em; } .favorite-container h3 { color: #ffffff; } .favorite-container ul { list-style: none; color: #d6d6d6; } .favorite-container li { padding: 1em 0; } .active { color: red; }
Â
JS:
The script.js
file contains the JavaScript code responsible for generating random quotes, managing favorite quotes, and handling user interactions. Here’s a snippet of the JavaScript code:
let quote = document.getElementById('quote'); let author = document.getElementById('author'); let btn = document.getElementById('btn'); let favourite = document.getElementById('favourite'); let list = document.getElementById('list-of-favourite-quotes'); let copyButton = document.getElementById('copy'); let showAllListOfFavourite = document.getElementById('show-list'); let clearButton = document.getElementById('clear-button'); let favoriteContainer = document.querySelector('.favorite-container'); let closeButton = document.getElementById('close-favorite'); const url = 'https://api.quotable.io/random'; let favorites = []; // Function to update the displayed quote and author const updateQuote = (content, authorName) => { quote.innerText = content; author.innerText = authorName; let existsInFavorites = checkExistence(content, authorName); let heartIcon = favourite.firstElementChild; if (existsInFavorites) { heartIcon.classList.remove('fa-regular'); heartIcon.classList.add('fa-solid', 'active'); } else { heartIcon.classList.add('fa-regular'); heartIcon.classList.remove('fa-solid', 'active'); } }; // Function to display favorite quotes const displayFavorites = () => { list.innerHTML = ''; favorites.forEach((q, index) => { const listItem = document.createElement('li'); listItem.textContent = `${index + 1}. ${q.content} - ${q.author}`; list.appendChild(listItem); }); }; // Function to save favorites to local storage const saveFavoritesToLocalStorage = () => { localStorage.setItem('favorites', JSON.stringify(favorites)); }; // Function to fetch a random quote from the API const getQuote = () => { fetch(url) .then((data) => data.json()) .then((item) => { updateQuote(item.content, item.author); }); }; const checkExistence = (content, authorName) => { return favorites.some( (q) => q.content === content && q.author === authorName ); }; // Function to add a quote to favorites const addToFavorites = () => { let heartIcon = favourite.firstElementChild; // if (heartIcon.classList.contains('fa-regular')) { heartIcon.classList.remove('fa-regular'); heartIcon.classList.add('fa-solid', 'active'); const content = quote.innerText; const authorName = author.innerText; // Check if the quote is already in favorites const existsInFavorites = checkExistence(content, authorName); if (!existsInFavorites) { favorites.push({ content, author: authorName }); saveFavoritesToLocalStorage(); // Save to local storage displayFavorites(); // Call this function to update the favorite quotes list } }; // Function to copy text to clipboard const copyToClipboard = (text) => { const textarea = document.createElement('textarea'); textarea.value = text; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); }; // list-of-favourite-quotes copyButton.addEventListener('click', () => { copyToClipboard(quote.innerText); }); // Function to clear favorites from local storage const clearFavoritesFromLocalStorage = () => { localStorage.removeItem('favorites'); favorites = []; // Clear the favorites array displayFavorites(); // Display the cleared favorites list favoriteContainer.style.display = 'none'; list.style.display = 'none'; let heartIcon = favourite.firstElementChild; if (heartIcon.classList.contains('fa-solid')) { heartIcon.classList.add('fa-regular'); heartIcon.classList.remove('fa-solid', 'active'); } }; showAllListOfFavourite.addEventListener('click', () => { if (favorites.length == 0) { list.innerHTML = "<p>You haven't added a favorite yet</p>"; } list.style.display = 'block'; favoriteContainer.style.display = 'block'; }); //close button closeButton.addEventListener('click', () => { list.style.display = 'none'; favoriteContainer.style.display = 'none'; }); // Attach event listeners window.addEventListener('load', () => { list.style.display = 'none'; // hide when window load or refresh favoriteContainer.style.display = 'none'; favourite.addEventListener('click', addToFavorites); clearButton.addEventListener('click', clearFavoritesFromLocalStorage); // Load favorites from local storage if available const storedFavorites = localStorage.getItem('favorites'); if (storedFavorites) { favorites = JSON.parse(storedFavorites); displayFavorites(); } getQuote(); }); btn.addEventListener('click', getQuote); quote.addEventListener('click', () => { copyToClipboard(quote.innerText); });
Â
Conclusion:
Congratulations! You’ve successfully built a dynamic quote generator web application using HTML, CSS, and JavaScript. Users can now generate random quotes, save their favorite quotes, and even copy them to the clipboard. This project is a great way to practice your web development skills and create a useful tool for yourself and others.