Question:
Javascript: Modal not closing with a button

Problem

I have the following dialog:


const gridContainer = document.querySelector(".grid-container");

const addBookBtn = document.querySelector("#add-book-btn");

const dialog = document.querySelector("dialog");

const dialogCloseBtn = document.querySelector("#dialog-close-btn")

addBookBtn.addEventListener('click', () => dialog.showModal());

dialogCloseBtn.addEventListener('click', () => dialog.close());


body {

    margin: 0;

    font-family: 'Poppins', sans-serif;

    font-size: 12px;

}


.container {

    display: grid;

    grid-template-rows: 150px 3fr;

}


.header {

    background-color: white ;

    font-size: 1.6rem;

    font-weight: 900;

    display: flex;

    justify-content: left;

    align-items: center;

    padding-left: 5vw;

    box-shadow: 0 5px 5px darkgray;

    z-index: 1;

}


.main-content {

    background-color: lightgray;

    display: grid;

    grid-template-rows: 150px 4fr;

}


.main-content>button {

    grid-column: 1 / -1;

    width: 200px;

    height: 60px;

    margin: 20px;

    background-color: silver;

    border: none;

    box-shadow: 0px 2px 4px darkgray;

    border-radius: 15px;

    justify-self: center;

    align-self: center;

    font-size: 1.5rem;

    font-family: 'Poppins', sans-serif; /* why does it not inherit the family? */

}


.main-content>button:hover {

    background-color: darkgray;

}


.grid-container {

    display: grid;

    padding: 0 5rem 5rem 5rem;

    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

    grid-auto-rows: 1fr;

    gap: 4em

}


.book-card {

    background-color: white;

    border-radius: 15px;

    box-shadow: 0px 1px 4px darkgray;

    min-height: 300px;

    display: flex;

    flex-direction: column;

    justify-content: space-evenly;

    align-items: center;

    padding: 30px;

    font-size: 1.4rem;

}


.book-card>p {

    margin: 0;

}


.remove-btn {

    font-size: 1.3rem;

    border-radius: 5px;

    width: 100px;

    height: 50px;

    box-shadow: 0px 2px 4px darkgray;

}


.remove-btn:hover {

    background-color: red;

}


dialog {

    display: flex;

    max-height: auto;

    max-width: auto;

    z-index: 10;

    justify-content: center;

    align-items: center;

    padding: 40px;

}


.modal>form {

    font-size: 1.1rem;

    display: grid;

    grid-template: repeat(5, 1fr) / 1fr 1fr;

    gap: 15px;

}


::backdrop {

    opacity: 0.5;

}


<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>My Library</title>

    <script src="main.js" defer></script>

    <link rel="stylesheet" href="styles.css">

    <link rel="preconnect" href="https://fonts.googleapis.com">

    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

    <link href="https://fonts.googleapis.com/css2?family=Chicle&family=Poppins&display=swap" rel="stylesheet">

</head>

<body>

    <div class="container">

        <div class="header">

            <h1>library</h1>

        </div>

        <div class="main-content">

            <button type="button" id="add-book-btn">+ Add book</button>

            <div class="grid-container"></div>

        </div>

    </div>


    <div>

        <dialog class="modal">

            <form method="dialog">

                <label for="author">Author</label>

                <input type="text" id="author" placeholder="J.R.R. Tolkien">

                <label for="title">Title</label>

                <input type="text" id="title" placeholder="The Lord of The Rings">

                <label for="pages">Pages</label>

                <input type="number" id="pages"> 

                <label for="read">Have you read it?</label>

                <input type="checkbox" id="read">

                <button type="submit">Submit</button>

                <button type="submit" id="dialog-close-btn">Close</button>

            </form>

        </dialog>

    </div>

</body>

</html>


However, somehow it's not working properly. I see the backdrop change back to a bit less dark but the modal is still there. What am I doing wrong? Though when I tried it here it looks like it's working. Can it be VSC? All the answers I found are related to Bootstrap which I'm not using...


Solution

The issue is that your modal dialog is always visible. You need to set it to display: none by default then display: flex when showModalDialog() is called.


To do that you can make this change to your CSS:


dialog {

  display: none;

  /* other properties... */

}


dialog[open] {

  display: flex;

}


Here's a full working example:


const gridContainer = document.querySelector(".grid-container");

const addBookBtn = document.querySelector("#add-book-btn");

const dialog = document.querySelector("dialog");

const dialogCloseBtn = document.querySelector("#dialog-close-btn")

addBookBtn.addEventListener('click', () => dialog.showModal());

dialogCloseBtn.addEventListener('click', () => dialog.close());



body {

  margin: 0;

  font-family: 'Poppins', sans-serif;

  font-size: 12px;

}


.container {

  display: grid;

  grid-template-rows: 150px 3fr;

}


.header {

  background-color: white;

  font-size: 1.6rem;

  font-weight: 900;

  display: flex;

  justify-content: left;

  align-items: center;

  padding-left: 5vw;

  box-shadow: 0 5px 5px darkgray;

  z-index: 1;

}


.main-content {

  background-color: lightgray;

  display: grid;

  grid-template-rows: 150px 4fr;

}


.main-content>button {

  grid-column: 1 / -1;

  width: 200px;

  height: 60px;

  margin: 20px;

  background-color: silver;

  border: none;

  box-shadow: 0px 2px 4px darkgray;

  border-radius: 15px;

  justify-self: center;

  align-self: center;

  font-size: 1.5rem;

  font-family: 'Poppins', sans-serif;

  /* why does it not inherit the family? */

}


.main-content>button:hover {

  background-color: darkgray;

}


.grid-container {

  display: grid;

  padding: 0 5rem 5rem 5rem;

  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

  grid-auto-rows: 1fr;

  gap: 4em

}


.book-card {

  background-color: white;

  border-radius: 15px;

  box-shadow: 0px 1px 4px darkgray;

  min-height: 300px;

  display: flex;

  flex-direction: column;

  justify-content: space-evenly;

  align-items: center;

  padding: 30px;

  font-size: 1.4rem;

}


.book-card>p {

  margin: 0;

}


.remove-btn {

  font-size: 1.3rem;

  border-radius: 5px;

  width: 100px;

  height: 50px;

  box-shadow: 0px 2px 4px darkgray;

}


.remove-btn:hover {

  background-color: red;

}


dialog {

  display: none;

  max-height: auto;

  max-width: auto;

  z-index: 10;

  justify-content: center;

  align-items: center;

  padding: 40px;

}


dialog[open] {

  display: flex;

}


.modal>form {

  font-size: 1.1rem;

  display: grid;

  grid-template: repeat(5, 1fr) / 1fr 1fr;

  gap: 15px;

}


::backdrop {

  opacity: 0.5;

}


<link href="https://fonts.googleapis.com/css2?family=Chicle&family=Poppins&display=swap" rel="stylesheet">


<div class="container">

  <div class="header">

    <h1>library</h1>

  </div>

  <div class="main-content">

    <button type="button" id="add-book-btn">+ Add book</button>

    <div class="grid-container"></div>

  </div>

</div>


<div>

  <dialog class="modal">

    <form method="dialog">

      <label for="author">Author</label>

      <input type="text" id="author" placeholder="J.R.R. Tolkien">

      <label for="title">Title</label>

      <input type="text" id="title" placeholder="The Lord of The Rings">

      <label for="pages">Pages</label>

      <input type="number" id="pages">

      <label for="read">Have you read it?</label>

      <input type="checkbox" id="read">

      <button type="submit">Submit</button>

      <button type="submit" id="dialog-close-btn">Close</button>

    </form>

  </dialog>

</div>


Suggested blog

>How to get the date and time and display it in a defineProps in Vuejs?

>Why logged user object is all strings in Vuejs and Laravel 10?

>What is meant by progressive framework?

>How can I replace this.$parent in composition API in Vuejs?

>How do I fix an invalid route component in the new VueJs Project?

>How to get all the rows selected in Vuejs?

>How to set up a dynamic grid based on flex or grid in Vuejs?

>Create a project using Vue.js: Beginners Guide

>Authentication with Vue 3 and Firebase

>Plugins and Presets for Vuejs project

>Create a Vue.js application with CLI Services

>Create a project using Vue.js: Beginners Guide

>Create Vue.js application API


Nisha Patel

Nisha Patel

Submit
0 Answers