I am trying to toggle a class list on and off so that when the button is clicked, the opacity of the modal is changed to 1 and when the close button is clicked, the class list is toggled off.
In the console, I see the error: Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
I checked to make sure I had no typos and I don't see any. I can't figure out why there is an error.
HTML (index.html)
<button >RULES</button>
<div >
<div >
<header >
<h2 >RULES</h2>
<button >
<img src="/images/icon-close.svg" alt="Close button">
</button>
</header>
<img src="/images/image-rules.svg" alt="Rules image" >
</div>
</div>
CSS (styles.css)
.rulesButton {
background: transparent;
border: 2px solid white;
border-radius: 0.8rem;
bottom: 2rem;
color: white;
cursor: pointer;
font-family: inherit;
font-size: 1.3rem;
letter-spacing: 0.1rem;
right: 2rem;
outline: none;
padding: 0.6rem 2.4rem;
position: absolute;
}
.modal {
background: #0000004d;
display: grid;
height: 100%;
left: 0;
opacity: 0;
place-items: center;
pointer-events: none;
position: absolute;
top: 0;
transition: opacity 0.3s ease-in-out;
width: 100%;
}
.modalContainer {
background: white;
border-radius: 1.5rem;
}
.modalHeader {
display: flex;
justify-content: space-between;
padding: 2rem;
width: 100%;
}
.modalHeading {
color: hsl(229, 25%, 31%);
font-size: 1.5rem;
}
.closeButton {
background: none;
border: none;
cursor: pointer;
outline: none;
}
.rulesImage {
padding: 2rem 4rem;
}
.showModal { /* toggles on and off */
opacity: 1;
pointer-events: initial;
}
JavaScript (index.js)
const buttonRules = document.querySelector(".rulesButton");
const buttonClose = document.querySelector(".closeButton");
const modal = document.querySelector(".modal");
//Toggle Modal
buttonRules.addEventListener("click", () => {
modal.classList.toggle("showModal");
});
buttonClose.addEventListener("click", () => {
modal.classList.toggle("showModal");
});
CodePudding user response:
Where is your script tag located in your HTML document? If it's in the <head>
then the JavaScript will begin running before the browser has parsed the rest of the document. This means the button won't exist yet and therefore be null
.
If this is the case, you can fix it by adding the script tag after the elements being queried in the HTML document.
Example:
JavaScript
const testDiv = document.querySelector(".test");
console.log(testDiv.addEventListener);
HTML Script Before
<!DOCTYPE html>
<html>
<head>
<script src="select.js"></script>
</head>
<body>
<div >Hello world</div>
</body>
</html>
produces null returned from document.querySelector
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') at select.js:3:21
HTML Script After
<!DOCTYPE html>
<html>
<body>
<div >Hello world</div>
<script src="select.js"></script>
</body>
</html>
produces a defined function
ƒ addEventListener() { [native code] }