section 태그로 3개를 생성해 보았다.
<section>
을 식별할 수단이 필요했다. (참고: https://developer.mozilla.org/ko/docs/Web/HTML/Element/section) <div class="container">
<section>
<h2>1번</h2>
</section>
<section>
<h2>2번</h2>
</section>
<section>
<h2>3번</h2>
</section>
</div>
<div>
로 작성한다. <section>
<h2>1번</h2>
<div>
<p>Ipsum Lorem...</p>
</div>
</section>
section 안의 div 의 display dafault 값을 none 으로 지정해준다.
이후에 <script>
에서 <section>
클릭시의 이벤트를 관리해준다.
작성하려는데, 한 가지 의문점이 생겼다.
const section = document.querySelector("section")
위와 같은 식으로 코드를 작성하면 1번인지 2번인지 3번인지 알 수 있을까?
일단 확인해보기로 했다.
console.log(event.target)
확인해본 결과 1번만 section 에 할당된 것을 알 수 있었다.
혹시나 하는 마음에 querySelectorAll 을 사용해보았다.
const section = document.querySelectorAll("section")
그러자 section.addEventListener is not a function
라는 오류가 나왔다.
그렇다면 하나하나의 섹션에 모두 Id 값을 주고 각각 const 로 선언해주어야 하나?
각각의 섹션을 잡기 위해 각각의 섹션 모두에 각각 addEventListener 를 달아주었다.
for (let i = 0; i < section.length; i++ ) {
section[i].addEventListener("click", event => {
this.classList.toggle("active");
})
};
Uncaught TypeError: Cannot read property 'toggle' of undefined
에러가 발생하였다.
console.log 에는 this 가 Window, 즉 최상위 객체가 잡히게 되었다.
이유를 찾아보니 문제는 Arrow function 에 있었다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Arrow_functions
각 섹션을 눌렀을 때 반응(toggle) 할 수 있게 만들어 주었으니 이제는 섹션 내부 <div>
의 class를 변경해줘야한다.
for (let i = 0; i < section.length; i++ ) {
section[i].addEventListener("click", function() {
const div = this.querySelector("div");
div.classList.toggle("active");
})
};
.active {
display: inline ;
}
위와 같이 하니 이미
!important 속성을 부여하고서야 작동이 되었다.
따라서 !important를 사용하지 않고 하는 방법은 없을까 고민해보았다.
for (let i = 0; i < section.length; i++ ) {
section[i].addEventListener("click", function() {
const div = this.querySelector("div");
// div.classList.toggle("active");
if ( div.style.display === "none") {
div.style.display = "block"
} else {
div.style.display = "none"
};
})
};
위와 같은 방법으로 해주니 작동이 된다!
이제는 애니메이션을 넣어보자
section > div {
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: green;
}
for (let i = 0; i < section.length; i++ ) {
section[i].addEventListener("click", function() {
const div = this.querySelector("div");
if ( div.style.maxHeight) {
div.style.maxHeight = null;
} else {
div.style.maxHeight = div.scrollHeight + "px";
};
})
};
display: none;
방식이 아니라
max-height 속성을 null
값으로 줘서 안보이게 해주는 방식으로 변경 한 뒤
눌렀을 때 scrollHeight 를 이용하여 표현해준다.
css 에서는 transition 을 통해 max-height 값 변화시의 애니메이션을 준다
Element.scrollHeight
number
Arrow Fucntion 은 this 를 바인딩 하지 않음
같은 요소들 중 하나를 선택했을 때 인식 시키는 법
각 섹션에 열고 닫는 부분이 있어야 하나?
상세 매뉴가 닫히는 조건 설정
해당 섹션을 다시 눌렀을 때
다른 섹션을 눌렀을 때 자동으로 닫혀야 하나?
섹션이 아닌 다른 부분을 눌렀을 때 닫혀야 하나?
=> 만약에 모바일 환경이라면, 원래 열려있던 것은 닫히는 것이 나을 듯 하다.
=> 화면이 넓은 웹이라면 선택 사항이 되지 않을까?
=> 각 섹션 하위 내용의 양에 따라서, 그 일정 기준 이상으로 많다면 닫히는게 낫지 않을까?
아코디언 네비게이션을 만들면 어떨까?
이걸 응용해서 만들 수 있는게 정말 많을 거 같다