본문 바로가기
개발

HTML 페이지에서 JavaScript로 동적 목차 만들기

by new-fp 2024. 11. 12.
728x90
반응형

HTML 페이지에 동적 목차(TOC) 만들기

안녕하세요, 여러분! 오늘은 웹 페이지를 더 편리하게 만들어 줄 동적 목차(Table of Contents, TOC)를 JavaScript를 사용하여 생성하는 방법에 대해 알아보겠습니다. 특히, 긴 내용을 가진 페이지에서 독자들이 원하는 섹션으로 쉽게 이동할 수 있도록 도와주는 기능이죠.

이번 포스트에서는 동적 목차 생성에 필요한 단계별 코드를 소개하며, 실용적으로 어떻게 활용할 수 있는지에 대한 예제도 함께 살펴보겠습니다.

들어가며

웹 페이지가 길어질수록 사용자가 원하는 내용을 쉽게 찾는 것이 중요해집니다. 이때가 바로 TOC가 필요한 순간입니다. 클릭 한 번으로 특정 섹션으로의 이동이 가능하고, 스크롤을 통한 현재 위치 표시 기능까지 있으면 매우 유용하겠죠.

자, 그럼 TOC를 만들어보도록 하겠습니다!

1. 동적으로 목차 생성하기

먼저, 목차를 담을 공간을 HTML에 추가해 보겠습니다.

<aside>
  <div class="toc"></div>
</aside>

위의 <aside> 요소 내에 .toc 클래스를 가지는 div를 추가했습니다.

CSS 스타일링 추가

목차의 스타일링을 작성하여 깔끔하게 보이도록 만들어 보겠습니다.

body {
  background-color: #F2F0EE;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.toc {
    position: fixed;
    top: 20px;
    right: 20px;
    width: 250px;
    background-color: #f0f0f0;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}
.toc ul {
    list-style-type: none;
    padding: 0;
}
.toc ul li {
    margin-bottom: 5px;
}
.toc ul li a {
    text-decoration: none;
    color: #333;
    display: block;
    padding: 3px;
    transition: background-color 0.3s;
}
.toc ul li a:hover {
    background-color: #ddd;
    border-radius: 3px;
}

이제 JavaScript를 사용하여 목차에 사용할 헤더를 불러오겠습니다.

document.addEventListener('DOMContentLoaded', function() {
    const tocContainer = document.querySelector(".toc");
    const headers = document.querySelectorAll('h2, h3, h4');
    const tocList = document.createElement('ul');
    let headerCnt = 0; // 고유 ID를 위한 카운터

    headers.forEach(header => {
        const tocItem = document.createElement('li');

        // 헤더에 고유한 ID를 생성하여 추가
        const id = `header-${headerCnt++}`;
        header.id = id;

        // 링크를 만들어 li에 추가
        const anchor = document.createElement('a');
        anchor.href = `#${id}`;
        anchor.textContent = header.textContent;
        tocItem.appendChild(anchor);

        tocList.appendChild(tocItem);
    });
    tocContainer.appendChild(tocList);
});

이 코드는 다음과 같은 동작을 수행합니다:

  1. 헤더 태그 불러오기: h2, h3, h4 태그를 찾아 리스트에 추가합니다.
  2. 목차 리스트 생성하기: <ul> 요소를 생성하여 각 해더를 추가합니다.
  3. 헤더에 ID 추가 및 링크 만들기: 각 헤더에 고유 ID를 생성하고, 해당 링크를 만들줄 후 리스트에 삽입합니다.

2. 헤더 레벨에 맞춘 스타일링

목차의 가독성을 높이기 위해, 각 헤더의 레벨에 따라 들여쓰기를 추가할 것입니다. 이를 위해 tocItem에 헤더 레벨에 맞는 클래스를 추가하는 코드를 작성합니다.

headers.forEach(header => {
    tocItem.classList.add(`toc-${header.tagName.toLowerCase()}`);
    tocList.appendChild(tocItem);
});

그리고 CSS를 통해 각 레벨에 맞는 스타일을 적용해 줍니다.

.toc-h2 {
  padding-left: 0;
}
.toc-h3 {
  padding-left: 20px;
}
.toc-h4 {
  padding-left: 40px;
}

3. 스크롤 위치에 맞춰서 목차 강조하기

마지막으로, 사용자가 스크롤을 할 때 현재 보고 있는 섹션의 목차를 강조하는 기능을 추가해보겠습니다.

const updateCurrentToc = () => {
    let fromTop = window.scrollY;

    headers.forEach((header) => {
        const headerOffsetTop = document.getElementById(header.id).offsetTop;

        if (headerOffsetTop <= fromTop + 100) {
            const currentActive = tocList.querySelector(".current-header");
            if (currentActive) {
                currentActive.classList.remove("current-header");
            }

            const currentLink = tocList.querySelector(`[href="#${header.id}"]`);
            if (currentLink) {
                currentLink.classList.add("current-header");
            }
        }
    });
};
window.addEventListener("scroll", updateCurrentToc);

위 코드에서는 현재 스크롤 위치를 감지하여 해당 위치에 있는 헤더의 링크를 강조합니다. 강조는 다음과 같은 CSS로 표현됩니다.

.current-header {
  font-weight: bold;
  background-color: white;
  box-shadow: 0px 10px 10px -5px rgba(0, 0, 0, 0.3);
}

마무리하며

오늘은 JavaScript를 활용하여 동적 목차를 생성하고, 스크롤에 따른 강조 기능까지 추가해보았습니다. 큰 문서나 웹페이지에서 사용자가 원하는 내용을 쉽게 찾을 수 있도록 도와줄 수 있는 멋진 기능이죠! 여러분도 이 코드를 활용하여 여러분만의 웹 페이지에 유용하게 활용해 보시기 바랍니다.

질문이나 추가적인 아이디어가 있다면 언제든지 댓글로 남겨주세요! 다음 포스트에서 또 만나요! ����️

728x90
반응형