{}const=>[]async()letfn</>var
JSWeb

Mini web application in JavaScript: application with notes

A step-by-step guide to creating a mini web application in pure JavaScript. In this tutorial, we will create a note-taking application using HTML, CSS, and JavaScript, and we will also connect localStorage to save data between browser sessions.

К

Kodik

Author

7 min read

Greetings! 👋 Today we will create mini web application in JavaScriptnotes app using HTML, CSS, and JavaScript.

This application will allow you to add, edit, and delete notes, which will be saved in localStorage browser. This means that your notes will not disappear even after reloading the page!

We will consider every step of creating an applicationso you can understand how it works and create your own mini web application on pure JS.

Ready? Let's go! 🚀

For the full source code and possibly additional improvements, check out our GitHub.


What our app does

Our note-taking app allows users to:

  1. Add notes with headings and descriptions.

  2. Save notes in the browser so that data is not lost when the page is reloaded.

  3. View a list of all created notes.

  4. Edit existing notes.

  5. Delete unnecessary notes.

Now let's get started!


1. Creating an HTML structure

HTML is responsible for the structure of our application. First, create a index.html file with the basic markup:

<!DOCTYPE html>
<html lang="ru" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Приложение для заметок на JavaScript | Coursme</title>
  <link rel="stylesheet" href="style.css">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- Подключение иконок -->
  <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css">
</head>
<body>
  <!-- Всплывающее окно для добавления/редактирования заметок -->
  <div class="popup-box">
    <div class="popup">
      <div class="content">
        <header>
          <p>Добавить новую заметку</p>
          <i class="uil uil-times"></i> <!-- Кнопка закрытия -->
        </header>
        <form action="#">
          <div class="row title">
            <label>Заголовок</label>
            <input type="text" spellcheck="false">
          </div>
          <div class="row description">
            <label>Описание</label>
            <textarea spellcheck="false"></textarea>
          </div>
          <button>Сохранить заметку</button>
        </form>
      </div>
    </div>
  </div>

  <!-- Контейнер для добавления новой заметки -->
  <div class="wrapper">
    <li class="add-box">
      <div class="icon"><i class="uil uil-plus"></i></div>
      <p>Добавить новую заметку</p>
    </li>
  </div>

  <script src="script.js"></script>
</body>
</html>

Brief explanation of the code:

  • popup-box: Pop-up window for creating a new note. Contains a form with fields for the title and description.

  • add-box: An element that opens a pop-up window for adding a new note.


2. Styling with CSS

Create a style.css file to add styles to our application. Here are the main styles you need to know:

/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body {
  background: #FFB3B3;
}
::selection {
  color: #fff;
  background: #FF6F61;
}
.wrapper {
  margin: 40px;
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, 270px);
}
.wrapper li {
  height: 260px;
  list-style: none;
  border-radius: 8px;
  padding: 15px 18px 18px;
  background: #ffffff;
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
  transition: transform 0.3s ease-in-out;
}
.wrapper li:hover {
  transform: translateY(-5px);
}
.add-box,
.icon,
.bottom-content,
.popup,
header,
.settings .menu li {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.add-box {
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
}
.add-box .icon {
  height: 80px;
  width: 80px;
  color: #FF6F61;
  font-size: 42px;
  border-radius: 50%;
  justify-content: center;
  border: 3px dashed #FF6F61;
}
.add-box p {
  color: #FF6F61;
  font-weight: 500;
  margin-top: 18px;
}
.note {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.note .details {
  max-height: 170px;
  overflow-y: auto;
}
.note .details::-webkit-scrollbar,
.popup textarea::-webkit-scrollbar {
  width: 0;
}
.note .details:hover::-webkit-scrollbar,
.popup textarea:hover::-webkit-scrollbar {
  width: 6px;
}
.note .details:hover::-webkit-scrollbar-track,
.popup textarea:hover::-webkit-scrollbar-track {
  background: #f3f3f3;
  border-radius: 20px;
}
.note .details:hover::-webkit-scrollbar-thumb,
.popup textarea:hover::-webkit-scrollbar-thumb {
  background: #ddd;
  border-radius: 20px;
}
.note p {
  font-size: 20px;
  font-weight: 500;
}
.note span {
  display: block;
  color: #626262;
  font-size: 15px;
  margin-top: 6px;
}
.note .bottom-content {
  padding-top: 8px;
  border-top: 1px solid #bbb;
}
.bottom-content span {
  color: #7A7A7A;
  font-size: 13px;
}
.bottom-content .settings {
  position: relative;
}
.bottom-content .settings i {
  color: #7A7A7A;
  cursor: pointer;
  font-size: 16px;
}
.settings .menu {
  z-index: 1;
  bottom: 0;
  right: -5px;
  padding: 6px 0;
  background: #ffffff;
  position: absolute;
  border-radius: 6px;
  transform: scale(0);
  transform-origin: bottom right;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.18);
  transition: transform 0.3s ease;
}
.settings.show .menu {
  transform: scale(1);
}
.settings .menu li {
  height: 28px;
  font-size: 15px;
  margin-bottom: 2px;
  padding: 18px 16px;
  cursor: pointer;
  box-shadow: none;
  border-radius: 0;
  justify-content: flex-start;
}
.menu li:last-child {
  margin-bottom: 0;
}
.menu li:hover {
  background: #f4f4f4;
}
.menu li i {
  padding-right: 8px;
}

.popup-box {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  height: 100%;
  width: 100%;
  background: rgba(0, 0, 0, 0.5);
}
.popup-box .popup {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 3;
  width: 100%;
  max-width: 420px;
  justify-content: center;
  transform: translate(-50%, -50%) scale(0.9);
}
.popup-box,
.popup {
  opacity: 0;
  pointer-events: none;
  transition: all 0.35s ease;
}
.popup-box.show,
.popup-box.show .popup {
  opacity: 1;
  pointer-events: auto;
}
.popup-box.show .popup {
  transform: translate(-50%, -50%) scale(1);
}
.popup .content {
  border-radius: 8px;
  background: #ffffff;
  width: calc(100% - 20px);
  box-shadow: 0 0 18px rgba(0, 0, 0, 0.12);
}
.content header {
  padding: 16px 28px;
  border-bottom: 1px solid #bbb;
}
.content header p {
  font-size: 21px;
  font-weight: 500;
}
.content header i {
  color: #9a9898;
  cursor: pointer;
  font-size: 24px;
}
.content form {
  margin: 18px 28px 40px;
}
.content form .row {
  margin-bottom: 22px;
}
form .row label {
  font-size: 17px;
  display: block;
  margin-bottom: 7px;
}
form :where(input, textarea) {
  height: 52px;
  width: 100%;
  outline: none;
  font-size: 16px;
  padding: 0 16px;
  border-radius: 5px;
  border: 1px solid #aaa;
}
form :where(input, textarea):focus {
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
}
form .row textarea {
  height: 155px;
  resize: none;
  padding: 10px 16px;
}
form button {
  width: 100%;
  height: 52px;
  color: #fff;
  outline: none;
  border: none;
  cursor: pointer;
  font-size: 17px;
  border-radius: 5px;
  background: #FF6F61;
}

@media (max-width: 660px) {
  .wrapper {
    margin: 12px;
    gap: 12px;
    grid-template-columns: repeat(auto-fill, 100%);
  }
  .popup-box .popup {
    max-width: calc(100% - 12px);
  }
  .bottom-content .settings i {
    font-size: 18px;
  }
}

Brief explanation:

  • Background: We set a nice pink background for the page.

  • add-box: Element with a "+" icon for adding a new note.

  • popup-box: A pop-up window that will be displayed when adding/editing a note.

Style code is available in repositories.


3. JavaScript application logic

Create a script.js file to add application functionality. We will look at the basic functions required for the application to work.

const addBox = document.querySelector(".add-box"),
    popupBox = document.querySelector(".popup-box"),
    popupTitle = popupBox.querySelector("header p"),
    closeIcon = popupBox.querySelector("header i"),
    titleTag = popupBox.querySelector("input"),
    descTag = popupBox.querySelector("textarea"),
    addBtn = popupBox.querySelector("button");

// Months in Russian
const months = ["January", "February", "March", "April", "May", "June", "July",
    "August", "September", "October", "November", "December"];

// Get saved notes from localStorage, if any
const notes = JSON.parse(localStorage.getItem("notes") || "[]");
let isUpdate = false, updateId;

// Open a window to add a new note
addBox.addEventListener("click", () => {
    popupTitle.innerText = "Add a new note";
    addBtn.innerText = "Add a note";
    popupBox.classList.add("show");
    document.querySelector("body").style.overflow = "hidden";
    if(window.innerWidth > 660) titleTag.focus();
});

// Close the window for adding/editing a note
closeIcon.addEventListener("click", () => {
    isUpdate = false;
    titleTag.value = descTag.value = "";
    popupBox.classList.remove("show");
    document.querySelector("body").style.overflow = "auto";
});

// Display all notes function
function showNotes() {
    if(!notes) return;
    document.querySelectorAll(".note").forEach(li => li.remove());
    notes.forEach((note, id) => {
        let filterDesc = note.description.replaceAll("\n", '<br/>');
        let liTag = `<li class="note">
                        <div class="details">
                            <p>${note.title}</p>
                            <span>${filterDesc}</span>
                        </div>
                        <div class = "bottom-content">
                            <span>${note.date}</span>
                            <div class="settings">
                                <i onclick="showMenu(this)" class="uil uil-ellipsis-h"></i>
                                <ul class="menu">
                                    <li onclick="updateNote(${id}, '${note.title}', '${filterDesc}')"><i class="uil uil-pen"></i>Edit</li>
                                    <li onclick="deleteNote(${id})"><i class="uil uil-trash"></i>Delete</li>
                                </ ul>
                            </ div>
                        </ div>
                    </ li>`;
        addBox.insertAdjacentHTML("afterend", liTag);
    });
}
showNotes();

// Show settings menu for note
function showMenu(elem) {
    elem.parentElement.classList.add("show");
    document.addEventListener("click", e => {
        if(e.target.tagName != "I" || e.target != elem) {
            elem.parentElement.classList.remove("show");
        }
    });
}

// Delete note
function deleteNote(noteId) {
    let confirmDel = confirm("Are you sure you want to delete this note?");
    if(!confirmDel) return;
    notes.splice(noteId, 1);
    localStorage.setItem("notes", JSON.stringify(notes));
    showNotes();
}

// Update note
function updateNote(noteId, title, filterDesc) {
    let description = filterDesc.replaceAll('<br/>', '\r\n');
    updateId = noteId;
    isUpdate = true;
    addBox.click();
    titleTag.value = title;
    descTag.value = description;
    popupTitle.innerText = "Update note";
    addBtn.innerText = "Update note";
}

// Adding or updating a note
addBtn.addEventListener("click", e => {
    e.preventDefault();
    let title = titleTag.value.trim(),
        description = descTag.value.trim();

    if(title || description) {
        let currentDate = new Date(),
            month = months[currentDate.getMonth()],
            day = currentDate.getDate(),
            year = currentDate.getFullYear();

        let noteInfo = {title, description, date: `${month} ${day}, ${year}`}
        if(!isUpdate) {
            notes.push(noteInfo);
        } else {
            isUpdate = false;
            notes[updateId] = noteInfo;
        }
        localStorage.setItem("notes", JSON.stringify(notes));
        showNotes();
        closeIcon.click();
    }
});

Detailed explanation:

  1. addBox and popupBox: These variables refer to the elements for adding a new note and a pop-up window.

  2. Form opening function: When you click on "add", a form for entering data opens.

  3. Adding and saving notes: When you click the "Save" button, the data is saved in localStorage.

  4. Display notes: All saved notes are displayed on the page using the showNotes() function.

The rest of the code is available in repositories.


Conclusion

Now you have a full application with notes on JavaScript! You can download the source code and try to improve it by adding new features. Good luck with your development! 🚀

🎯Stop procrastinating

Liked the article?
Time to practice!

In Kodik, you don't just read — you write code immediately. Theory + practice = real skills.

Instant practice
🧠AI explains code
🏆Certificate

No registration • No card