Make Your Own Notes App with HTML, CSS, and JavaScript

Faraz

By Faraz -

This detailed guide explains how to make a personalized notes app using HTML, CSS, and JavaScript. Create and store notes in your browser easily.


make-your-own-notes-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

Creating a notes app using HTML, CSS, and JavaScript is an easy and fun project, especially if you’re starting with web development. This notes app lets users add, edit, delete, and save notes. It also uses localStorage, so your notes stay available even after refreshing the page.

In this tutorial, you’ll learn how to build a basic notes app step-by-step with a simple interface and core features like:

  1. Adding a note
  2. Editing a note
  3. Deleting a note
  4. Saving notes using localStorage

Before we dive into the code, let’s quickly go through the tools and prerequisites required for this project.

Prerequisites

To create the notes app, you will need:

  • Text Editor: Use VS Code or any code editor.
  • Web Browser: Google Chrome, Firefox, or any modern browser.
  • Basic knowledge of HTML, CSS, and JavaScript.

Source Code

Step 1 (HTML Code):

The HTML part will contain the layout of the notes app, including an input field, buttons, and a container for displaying notes. Here’s a breakdown of the HTML code:

1. DOCTYPE Declaration

<!DOCTYPE html>
  • Specifies that this is an HTML5 document.

2. <html> Tag

<html lang="en">
  • Represents the root of the HTML document.
  • The lang="en" attribute declares the language as English, helping browsers and search engines understand the content.

3. <head> Section

The <head> section contains meta-information and resources that the webpage needs to load.

a. Character Encoding

<meta charset="UTF-8">
  • Ensures the webpage supports all characters (like emojis and special symbols) by using the UTF-8 encoding.

b. Viewport Meta Tag

<meta name="viewport" content="width=device-width, initial-scale=1.0">
  • Makes the page responsive by ensuring it scales properly on different screen sizes, especially mobile devices.

c. Title

<title>Notes App</title>
  • Defines the title that appears on the browser tab.

d. CSS Link

<link rel="stylesheet" href="styles.css">
  • Links an external CSS file (styles.css) that contains the styles for this page.

4. <body> Section

This is where the content of the webpage is defined.

a. Main Container

<div class="container">
  • A wrapper <div> element with the class container that holds the entire content.

b. Header Section

<header>
  <h1>📝 Notes</h1>
  <button id="themeToggle">🌙</button>
</header>
  • Displays the page title as “Notes” along with a notepad emoji.
  • Includes a button with an ID themeToggle and a moon emoji 🌙, likely to toggle between light and dark modes.

c. Note Input Section

<div class="note-input">
  <textarea id="newNote" placeholder="Type your note here..."></textarea>
  <button id="addNoteBtn">Add Note</button>
</div>
  • Contains:
    • A <textarea> where the user types a new note, with a placeholder "Type your note here...".
    • A button with the ID addNoteBtn to add the new note.

d. Notes Display Area

<div id="notesContainer" class="notes-container">
  <!-- Notes will appear here dynamically -->
</div>
  • An empty <div> with the ID notesContainer where notes will be displayed dynamically (likely using JavaScript).

5. JavaScript Inclusion

<script src="script.js"></script>
  • Links an external JavaScript file (script.js) to add functionality, such as:
    • Adding notes dynamically.
    • Handling theme toggling.

Step 2 (CSS Code):

We’ll use basic CSS to make the app look neat and user-friendly. Here’s a detailed explanation of the CSS code:

1. Global Styles (*)

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Arial', sans-serif;
}
  • * targets all elements, applying:
    • margin: 0 and padding: 0: Removes default margins and padding.
    • box-sizing: border-box: Ensures padding and borders are included within the element's width/height.
    • font-family: 'Arial', sans-serif: Sets a default font.

2. body Styles

body {
  background-color: #f0f0f0;
  color: #333;
  transition: background-color 0.3s, color 0.3s;
}
  • Sets a light gray background (#f0f0f0) and dark gray text (#333).
  • transition ensures smooth changes when switching colors (e.g., for theme toggling).

3. Container Styling

.container {
  max-width: 600px;
  margin: 50px auto;
  padding: 20px;
  background-color: #fff;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  border-radius: 10px;
}
  • Centers the container on the screen with:
    • max-width: 600px: Limits the width.
    • margin: 50px auto: Adds vertical space and centers horizontally.
    • box-shadow: Adds a subtle shadow for an elevated look.
    • border-radius: 10px: Rounds the corners.

4. Header Styling

header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}
  • Uses Flexbox to align the title and theme toggle button side-by-side.
  • justify-content: space-between pushes them to opposite ends.

5. Theme Toggle Button

#themeToggle {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
}
  • Removes the default background and border.
  • Increases font size to 1.5rem (for better visibility).
  • cursor: pointer changes the cursor to a hand icon on hover.

6. Note Input Section

.note-input {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}
  • Flexbox layout ensures the textarea and button are aligned horizontally.
  • gap: 10px adds space between the input elements.

7. Textarea Styling

textarea {
  flex: 1;
  resize: none;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}
  • flex: 1 makes the textarea take available space.
  • resize: none disables resizing.
  • Adds padding, border, and rounded corners.

8. Add Note Button

#addNoteBtn {
  padding: 10px 20px;
  border: none;
  background-color: #28a745;
  color: #fff;
  cursor: pointer;
  border-radius: 5px;
}

#addNoteBtn:hover {
  background-color: #218838;
}
  • Styled with a green background (#28a745).
  • On hover, the background becomes a darker green (#218838).

9. Notes Container

.notes-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
  • Uses Flexbox with flex-direction: column to stack notes vertically.
  • Adds gap: 10px between notes.

10. Individual Note Styling

.note {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
  background-color: #fafafa;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
  • Each note has:
    • Padding, border, and rounded corners.
    • A light gray background (#fafafa).
    • Flexbox layout to align the content horizontally.

11. Note Content and Button Styling

.note p {
  flex: 1;
  margin-right: 10px;
  word-break: break-word;
}
  • flex: 1 allows the paragraph to use remaining space.
  • word-break: break-word ensures long text wraps properly.
.note button {
  background-color: #dc3545;
  color: #fff;
  border: none;
  padding: 5px 10px;
  border-radius: 5px;
  cursor: pointer;
}

.note button:hover {
  background-color: #c82333;
}
  • Delete button is styled with a red background (#dc3545).
  • On hover, it becomes a darker red (#c82333).

12. Dark Theme Styling

body.dark {
  background-color: #333;
  color: #f0f0f0;
}

body.dark .container {
  background-color: #444;
}

body.dark textarea {
  background-color: #555;
  color: #fff;
  border: 1px solid #666;
}

body.dark .note {
  background-color: #666;
}
  • Dark theme is activated when the body has the class dark.
  • The background, text, and elements are adjusted to darker shades.

13. Additional Note Styles

.note button {
  margin-left: 5px;
}

.note pre {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  flex: 1;
}
  • pre tags inside notes preserve whitespace but wrap lines (using pre-wrap).
  • word-break: break-word ensures long words don’t overflow.
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Arial', sans-serif;
}

body {
  background-color: #f0f0f0;
  color: #333;
  transition: background-color 0.3s, color 0.3s;
}

.container {
  max-width: 600px;
  margin: 50px auto;
  padding: 20px;
  background-color: #fff;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  border-radius: 10px;
}

header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

h1 {
  font-size: 2rem;
}

#themeToggle {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
}

.note-input {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

textarea {
  flex: 1;
  resize: none;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}

#addNoteBtn {
  padding: 10px 20px;
  border: none;
  background-color: #28a745;
  color: #fff;
  cursor: pointer;
  border-radius: 5px;
}

#addNoteBtn:hover {
  background-color: #218838;
}

.notes-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.note {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
  background-color: #fafafa;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.note p {
  flex: 1;
  margin-right: 10px;
  word-break: break-word;
}

.note button {
  background-color: #dc3545;
  color: #fff;
  border: none;
  padding: 5px 10px;
  border-radius: 5px;
  cursor: pointer;
}

.note button:hover {
  background-color: #c82333;
}

body.dark {
  background-color: #333;
  color: #f0f0f0;
}

body.dark .container {
  background-color: #444;
}

body.dark textarea {
  background-color: #555;
  color: #fff;
  border: 1px solid #666;
}

body.dark .note {
  background-color: #666;
}

.note button {
  margin-left: 5px;
}

.note pre {
  white-space: pre-wrap; 
  word-break: break-word;
  margin: 0;
  flex: 1;
} 

Step 3 (JavaScript Code):

Now, let’s add the core functionality using JavaScript to allow adding, editing, deleting, and saving notes. Here's a detailed explanation of the JavaScript code:

1. Variable Initialization

const addNoteBtn = document.getElementById('addNoteBtn');
const newNote = document.getElementById('newNote');
const notesContainer = document.getElementById('notesContainer');
const themeToggle = document.getElementById('themeToggle');

let editingNoteIndex = null; 
  • addNoteBtn: Button for adding or updating a note.
  • newNote: Text area for entering the note content.
  • notesContainer: Div where all notes will be displayed.
  • themeToggle: Button to switch between light and dark themes.
  • editingNoteIndex: Keeps track of the index of the note being edited, if any.

2. Loading Saved Notes on Page Load

window.addEventListener('load', () => {
  const savedNotes = JSON.parse(localStorage.getItem('notes')) || [];
  savedNotes.forEach((note, index) => createNoteElement(note, index));
});
  • window.addEventListener('load'): When the page loads, it retrieves saved notes from localStorage.
  • localStorage.getItem('notes'): Fetches saved notes (if any) from localStorage. If there are no notes, it returns an empty array.
  • createNoteElement(): For each saved note, a visual element (note card) is created and added to the UI.

3. Adding or Updating a Note

addNoteBtn.addEventListener('click', () => {
  const noteText = newNote.value;
  if (noteText.trim() === '') return;

  if (editingNoteIndex !== null) {
    updateNoteInLocalStorage(noteText, editingNoteIndex);
    resetInput();
  } else {
    createNoteElement(noteText);
    saveNoteToLocalStorage(noteText);
  }
  newNote.value = '';
});
  • addNoteBtn triggers this function when clicked.
  • If the newNote text area is empty, it returns early to prevent saving an empty note.
  • If editingNoteIndex is not null, the user is updating an existing note:
    • Calls updateNoteInLocalStorage() to update the note in storage.
    • Resets the input field and button text using resetInput().
  • If not editing, it creates a new note and saves it to localStorage using saveNoteToLocalStorage().

4. Creating a Note Element

function createNoteElement(text, index = null) {
  const noteDiv = document.createElement('div');
  noteDiv.classList.add('note');

  const noteText = document.createElement('pre');
  noteText.textContent = text;

  const editBtn = document.createElement('button');
  editBtn.textContent = 'Edit';
  editBtn.addEventListener('click', () => editNote(text, index || getNoteIndex(text)));

  const deleteBtn = document.createElement('button');
  deleteBtn.textContent = 'Delete';
  deleteBtn.addEventListener('click', () => {
    noteDiv.remove();
    deleteNoteFromLocalStorage(text);
  });

  noteDiv.appendChild(noteText);
  noteDiv.appendChild(editBtn);
  noteDiv.appendChild(deleteBtn);
  notesContainer.appendChild(noteDiv);
}
  • createNoteElement() creates a visual note element with:
    • Text displayed using a <pre> element to preserve formatting.
    • Edit button to allow modifying the note.
    • Delete button to remove the note from the UI and localStorage.
  • Note Editing: If the user clicks the edit button, the note is loaded into the input field for editing.
  • Note Deletion: The delete button removes the note from the UI and storage.

5. Saving a New Note to LocalStorage

function saveNoteToLocalStorage(note) {
  const notes = JSON.parse(localStorage.getItem('notes')) || [];
  notes.push(note);
  localStorage.setItem('notes', JSON.stringify(notes));
}
  • Fetches existing notes from localStorage.
  • Adds the new note to the array.
  • Updates the localStorage with the new array.

6. Updating an Existing Note

function updateNoteInLocalStorage(newText, index) {
  const notes = JSON.parse(localStorage.getItem('notes'));
  notes[index] = newText;
  localStorage.setItem('notes', JSON.stringify(notes));

  // Refresh the UI
  notesContainer.innerHTML = '';
  notes.forEach((note, i) => createNoteElement(note, i));
  editingNoteIndex = null;
}
  • Updates the specified note in localStorage.
  • Refreshes the UI by clearing and re-creating all notes.
  • Resets the editing state by setting editingNoteIndex to null.

7. Deleting a Note from LocalStorage

function deleteNoteFromLocalStorage(note) {
  const notes = JSON.parse(localStorage.getItem('notes')) || [];
  const updatedNotes = notes.filter(n => n !== note);
  localStorage.setItem('notes', JSON.stringify(updatedNotes));
}
  • Filters out the deleted note from the notes array.
  • Updates localStorage with the modified array.

8. Editing a Note

function editNote(text, index) {
  newNote.value = text; // Load the note into the input field
  editingNoteIndex = index; // Track the index for update
  addNoteBtn.textContent = 'Update Note'; // Change button text
}
  • Loads the selected note into the input field.
  • Tracks the note’s index using editingNoteIndex for future updates.
  • Changes the button text to 'Update Note'.

9. Helper Function: Get Note Index

function getNoteIndex(text) {
  const notes = JSON.parse(localStorage.getItem('notes'));
  return notes.indexOf(text);
}
  • Finds the index of a specific note in localStorage.

10. Resetting Input and Button Text

function resetInput() {
  newNote.value = '';
  addNoteBtn.textContent = 'Add Note';
}
  • Clears the input field and resets the button text to 'Add Note'.

11. Theme Toggle (Dark/Light Mode)

themeToggle.addEventListener('click', () => {
  document.body.classList.toggle('dark');
  themeToggle.textContent = document.body.classList.contains('dark') ? '☀️' : '🌙';
});
  • Toggles the dark mode class on the body.
  • Changes the theme button's icon based on the current mode.
const addNoteBtn = document.getElementById('addNoteBtn');
const newNote = document.getElementById('newNote');
const notesContainer = document.getElementById('notesContainer');
const themeToggle = document.getElementById('themeToggle');

let editingNoteIndex = null; 

window.addEventListener('load', () => {
  const savedNotes = JSON.parse(localStorage.getItem('notes')) || [];
  savedNotes.forEach((note, index) => createNoteElement(note, index));
});

addNoteBtn.addEventListener('click', () => {
  const noteText = newNote.value;
  if (noteText.trim() === '') return;

  if (editingNoteIndex !== null) {
    updateNoteInLocalStorage(noteText, editingNoteIndex);
    resetInput();
  } else {
    createNoteElement(noteText);
    saveNoteToLocalStorage(noteText);
  }
  newNote.value = '';
});

function createNoteElement(text, index = null) {
  const noteDiv = document.createElement('div');
  noteDiv.classList.add('note');

  const noteText = document.createElement('pre');
  noteText.textContent = text; 

  const editBtn = document.createElement('button');
  editBtn.textContent = 'Edit';
  editBtn.addEventListener('click', () => editNote(text, index || getNoteIndex(text)));

  const deleteBtn = document.createElement('button');
  deleteBtn.textContent = 'Delete';
  deleteBtn.addEventListener('click', () => {
    noteDiv.remove();
    deleteNoteFromLocalStorage(text);
  });

  noteDiv.appendChild(noteText);
  noteDiv.appendChild(editBtn);
  noteDiv.appendChild(deleteBtn);
  notesContainer.appendChild(noteDiv);
}

function saveNoteToLocalStorage(note) {
  const notes = JSON.parse(localStorage.getItem('notes')) || [];
  notes.push(note);
  localStorage.setItem('notes', JSON.stringify(notes));
}

function updateNoteInLocalStorage(newText, index) {
  const notes = JSON.parse(localStorage.getItem('notes'));
  notes[index] = newText;
  localStorage.setItem('notes', JSON.stringify(notes));

  notesContainer.innerHTML = '';
  notes.forEach((note, i) => createNoteElement(note, i));
  editingNoteIndex = null;
}

function deleteNoteFromLocalStorage(note) {
  const notes = JSON.parse(localStorage.getItem('notes')) || [];
  const updatedNotes = notes.filter(n => n !== note);
  localStorage.setItem('notes', JSON.stringify(updatedNotes));
}

function editNote(text, index) {
  newNote.value = text;
  editingNoteIndex = index; 
  addNoteBtn.textContent = 'Update Note';
}

function getNoteIndex(text) {
  const notes = JSON.parse(localStorage.getItem('notes'));
  return notes.indexOf(text);
}

function resetInput() {
  newNote.value = '';
  addNoteBtn.textContent = 'Add Note';
}

themeToggle.addEventListener('click', () => {
  document.body.classList.toggle('dark');
  themeToggle.textContent = document.body.classList.contains('dark') ? '☀️' : '🌙';
});

Final Output:

make-your-own-notes-app-with-html-css-and-javascript.gif

Conclusion:

Congratulations! You have successfully created a notes app using HTML, CSS, and JavaScript. This project is great for beginners and introduces essential concepts like:

  • Using localStorage to save data.
  • Creating dynamic content with JavaScript.
  • Adding simple dark mode functionality.

With just a few lines of code, you now have a functional notes application. Try extending this project by adding features like search, categories, or a better user interface.

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🥺