HTML 설정 만으로 티스토리 자동 목차 생성하기 (별도 파일/서식 설정 X)
한 번 세팅 만으로 목차 생성 신경끄고 싶은 분에게
작성 계기 - 미래에 또 실수할 나를 위하여
팁만 보실 분은 바로 목차에서 목차 생성하기 란으로 가시면 됩니다. 이 글의 작성 계기는 심플합니다. 저 또한 티스토리 글쟁이로서 목차 생성기를 세팅해두고 있었습니다. 다만, 글쓰는 것도 귀찮은데 하나하나 세팅하긴 귀찮아서 찾아보다가 어느 은둔의 티스토리에서 HTML 만으로 세팅하는 방법을 보았죠. 그 후로 약간 조악하지만 편하게 목차를 설정해서 신경 안 쓰고 살았습니다. ...만 며칠 전 사건이 터졌죠. 난생 처음 티스토리 스킨을 변경해 보았습니다. 북클럽 스킨이 참 이뻐 보이더군요. 그리고 목차 HTML 코드를 날려 먹었죠. 스킨을 바꾸면 부가적으로 변경한 HTML이 증발한다는 사실을 새로이 깨닫게 되었습니다.
그래서 다른 사람들 쓴 팁을 찾아봤는데
제가 쓰는 방식이랑 영 안 맞습니다. 뭐를 깔아야하고, 파일 등록하고, 서식에서 갖다쓰고... 전 그런거 꾸미는 거 별로 안 좋아하는 공돌이라서요.. 생각보다 잘 적용되지도 않고요. 그래서 챗지피티한테 만들어 달라고 빌었습니다. 그러니 하나 만들어 주더군요. 여기서 글씨 크기 등을 손보고, 챗지피티의 제안에 따라 [숨기기] 버튼도 만들었답니다. 모바일 기기에서 볼 때도 문제없도록 반응형 디자인으로 만들었구요. 누군가에게 도움이 되길바라며, 언젠가 또 실수할 나를 위한 보험이 되기 위하여 기록을 남깁니다.
티스토리 자동메뉴 HTML 코드와 그 적용 방법 ★★★
사실 이 것만 보러 오신 거 다 압니다. 시작하시죠.
※ 해당 HTML 코드는 " Book Club " 스킨 기준으로 작성되었습니다.
1) 티스토리 스킨 편집으로 이동
- 티스토리 관리자 화면에 로그인합니다.
- 왼쪽 메뉴에서 꾸미기 → 스킨 편집으로 이동합니다.
- HTML 편집 화면을 엽니다.
2) 코드 삽입
1. HTML 편집 화면에서 다음을 찾습니다: </body>, <head>
이 글에서는 2개의 태그를 삽입합니다. <script>와 <style> 입니다.
- <script> 태그는 </body> 태그 바로 위에 삽입합니다.
- <style> 태그는 <head> 태그 안 또는 CSS 파일 끝부분에 삽입합니다.
태그 | 권장 위치 | 이유 |
<script> | </body> 태그 바로 위 | DOM 요소가 모두 로드된 후 스크립트 실행 및 렌더링 차단 방지 |
<style> | <head> 태그 안 또는 CSS 파일 끝 | 페이지 스타일 즉시 적용 및 커스터마이징 스타일 우선 적용 |
① <script> 스크립트 삽입:
아래의 스크립트를 HTML 파일의 </body> 태그 바로 위에 추가합니다.
<!-- 목차 자동 생성 스크립트 -->
<script>
document.addEventListener('DOMContentLoaded', function () {
const postContent = document.querySelector('.tt_article_useless_p_margin'); // 본문 컨테이너 선택
if (!postContent) return; // 본문이 없을 경우 실행 중지
const tocContainer = document.createElement('div');
tocContainer.id = 'table-of-contents';
tocContainer.innerHTML = `
<h2>Contents <button id="toggle-toc">[숨기기]</button></h2>
<ul></ul>
`;
const headings = postContent.querySelectorAll('h1, h2, h3'); // h1, h2, h3 태그를 탐색
const ul = tocContainer.querySelector('ul');
headings.forEach((heading, index) => {
const id = `section-${index}`;
heading.id = id; // 각 제목에 고유 ID 부여
const li = document.createElement('li');
li.classList.add(`toc-level-${heading.tagName.toLowerCase()}`); // 계층 구분 클래스 추가
li.innerHTML = `<a href="#${id}">${heading.textContent}</a>`;
ul.appendChild(li);
});
if (headings.length > 0) {
postContent.prepend(tocContainer); // 본문 상단에 목차 삽입
}
// 숨기기/펼치기 버튼 기능
const toggleButton = document.getElementById('toggle-toc');
const tocList = tocContainer.querySelector('ul');
toggleButton.addEventListener('click', function () {
if (tocList.style.display === 'none') {
tocList.style.display = 'block';
toggleButton.textContent = '[숨기기]';
} else {
tocList.style.display = 'none';
toggleButton.textContent = '[펼치기]';
}
});
});
</script>
② <style> 삽입:
아래의 스타일 코드를 HTML <head> 안에, 또는 CSS 파일 끝부분에 추가합니다.
→ 저는 <head> 와 </head> 사이에 붙여넣었습니다.
<!-- 목차 스타일 -->
<style>
#table-of-contents {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 20px;
background: #f9f9f9;
font-size: 14px; /* 목차 내용 글씨 크기 */
line-height: 1.6;
}
#table-of-contents h2 {
font-size: 16px; /* 목차 제목 글씨 크기 조정 */
margin-bottom: 10px;
margin-left: 20px; /* 제목 앞 공백 추가 */
display: flex;
justify-content: space-between;
align-items: center;
color: #333;
}
#table-of-contents button {
background: none;
border: none;
color: #007BFF;
cursor: pointer;
font-size: 0.9em;
padding: 0;
}
#table-of-contents button:hover {
text-decoration: underline;
}
#table-of-contents ul {
padding-left: 20px;
list-style: none;
}
#table-of-contents ul li {
margin-bottom: 5px;
}
#table-of-contents ul li a {
text-decoration: none;
color: #007BFF;
}
#table-of-contents ul li a:hover {
text-decoration: underline;
color: #0056b3;
}
/* 계층별 들여쓰기 */
#table-of-contents .toc-level-h1 {
font-weight: bold;
margin-left: 0;
list-style-type: disc; /* ● 표시 */
}
#table-of-contents .toc-level-h2 {
margin-left: 15px;
list-style-type: circle; /* ○ 표시 */
}
#table-of-contents .toc-level-h3 {
margin-left: 30px;
list-style-type: square; /* ■ 표시 */
}
/* 반응형 디자인 */
@media (max-width: 768px) {
#table-of-contents {
font-size: 12px;
padding: 10px;
}
#table-of-contents ul li {
margin-bottom: 3px;
}
}
</style>
③ 저장 후 확인:
코드를 삽입한 후, 저장하고 블로그 글 페이지를 새로고침(F5)하여 목차가 표시되는지 확인합니다.
코드 구성 설명
챗지피티가 어떤 구성으로 우리에게 이 코드를 제시했는지 설명한 부분입니다. 귀찮으시면 넘어가셔도 무방합니다.
2-1. 목차 자동 생성 스크립트
- document.addEventListener: HTML 문서가 모두 로드된 후 스크립트를 실행합니다.
- postContent.querySelectorAll('h1, h2, h3'): 본문에서 h1, h2, h3 태그를 검색해 목차 항목을 만듭니다.
- postContent.prepend(tocContainer): 생성된 목차를 본문 상단에 삽입합니다.
- 숨기기 버튼 기능: [숨기기] 클릭 시 목차가 접히고, 버튼 이름이 [펼치기]로 변경됩니다.
2-2. 목차 스타일
- #table-of-contents: 목차 전체 스타일을 정의합니다 (테두리, 배경, 글씨 크기 등).
- h2: 목차 제목(Contents)의 글씨 크기와 위치를 정의합니다.
- ul 및 li: 목차의 계층 구조와 각 항목의 들여쓰기, 간격을 설정합니다.
- 계층별 클래스:
- toc-level-h1 → ●, toc-level-h2 → ○, toc-level-h3 → ■.
2-3. 반응형 디자인
- @media (max-width: 768px): 화면 크기가 768px 이하일 때 목차의 글씨 크기를 줄이고, 여백을 조정합니다.
결과 예시
해당 코드 사용시 어떻게 나오는지 제시된 내용입니다. 실제 적용 사례는 글 처음에 사진으로 붙여두었죠.
PC 화면에서
Contents [숨기기]
● 대제목 1
○ 중제목 1.1
■ 소제목 1.1.1
○ 중제목 1.2
● 대제목 2
○ 중제목 2.1
모바일 화면에서
- 글씨 크기와 여백이 줄어들어 화면에 최적화된 목차가 표시됩니다.
- 숨기기 버튼은 그대로 작동합니다.
유의점 및 해결 방안
위 코드로 목차를 생성할 때 발생 가능한 문제점과 그 대응 입니다. 해당 문제 발생하였거나 수정 원할시 제가 올린 코드에서 해당 부분을 수정하거나 추가하시면 됩니다. 사실 미래의 저를 위해 남겨둔 내용입니다.
1. 스킨 구조에 따라 본문 클래스가 다를 수 있음 ☆
티스토리에서 사용하는 스킨(블로그 디자인 템플릿)은 각 스킨마다 HTML 구조와 클래스명이 다릅니다. 목차 스크립트는 본문을 특정 클래스명(.tt_article_useless_p_margin)으로 선택해서 동작하는데, 사용하는 스킨의 본문 클래스명이 다르면 목차가 제대로 생성되지 않습니다.
문제의 원인
- HTML 구조가 스킨마다 다름:
티스토리 스킨은 기본적으로 본문 영역을 포함하지만, 본문 영역을 감싸는 요소의 클래스명이 스킨마다 다릅니다.
예) .tt_article_useless_p_margin / .article-content / .entry-content - 선택자가 잘못된 경우 발생하는 문제:
스크립트가 document.querySelector('.tt_article_useless_p_margin')를 사용하여 본문 컨테이너를 찾지만, 실제 스킨의 본문 클래스명이 다르면 스크립트가 동작하지 않음.
본문 클래스 확인 방법
Step 1: 블로그 글 화면 열기
- 티스토리 블로그에서 목차를 적용하려는 글을 엽니다.
Step 2: 개발자 도구 열기
- 브라우저의 개발자 도구(Developer Tools)*를 엽니다.
- 단축키:
- Chrome: Ctrl + Shift + I (Windows) 또는 Cmd + Option + I (Mac)
- Edge/Firefox: F12
- 단축키:
Step 3: 본문 영역 선택
1) 개발자 도구에서 돋보기 아이콘(Inspect Element)를 클릭합니다.
2) 블로그 본문 영역 위로 마우스를 가져가면 HTML 요소가 강조 표시됩니다.
3) 강조된 HTML 태그를 확인합니다.
Step 4: 클래스명 확인
- 선택된 HTML 태그의 class 속성을 찾습니다. 예를 들어:
<div class="article-content">
<h1>대제목</h1>
<p>본문 내용...</p>
</div>
- 여기서 class="article-content"가 본문 클래스명입니다.
본문 클래스 명을 확인하였으면, 코드 내의 [.tt_article_useless_p_margin] 부분을 해당하는 클래스 명으로 변경하여 줍니다.
2. 글에 제목 태그(h1, h2, h3)가 없을 경우 목차가 생성되지 않음
제목 태그가 없으면 목차가 생성되기 어려운 건 다른 코드도 마찬가지이므로 제목 태그를 활용합시다. 티스토리에서 제목태그는 단순히 글 작성시 제목1/제목2/제목3 설정하시면 됩니다.
유의점:
- 글에 h1, h2, h3 태그가 없다면 목차가 빈 상태로 표시되거나 생성되지 않습니다.
해결 방안:
1) 글 작성 시 제목 태그 사용:
- 제목은 h1, h2, h3 태그로 작성합니다.
- 예: 글 작성 화면에서 제목1, 제목2, 제목3 스타일을 활용합니다.
2) 태그 없는 경우 안내 표시 추가: - 스크립트에 목차가 없을 때 안내 문구를 표시하도록 수정합니다:
if (headings.length === 0) {
tocContainer.innerHTML = `<h2>Contents</h2><p>목차를 생성할 제목이 없습니다.</p>`;
postContent.prepend(tocContainer);
}
3. 긴 목차로 인해 디자인이 깨질 수 있음
유의점:
- 제목이 너무 많거나 길면 목차가 페이지 디자인을 넘어가거나 가독성이 떨어질 수 있습니다.
해결 방안:
1) 목차 스크롤 기능 추가:
#table-of-contents ul {
max-height: 300px; /* 최대 높이 설정 */
overflow-y: auto; /* 스크롤 추가 */
}
2) 긴 제목 줄임 표시: 제목이 너무 길 경우 텍스트를 생략 표시(...)로 처리합니다:
#table-of-contents ul li a {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
4. 모바일에서 목차가 작동하지 않거나 보기 어려움
반응형 디자인을 추가하시면 됩니다. 제가 공유드린 코드엔 이미 적용되어 있습니다.
유의점:
- 모바일 화면에서 목차가 화면에 맞게 조정되지 않을 수 있습니다.
- 숨기기/펼치기 버튼이 너무 작게 보일 수도 있습니다.
해결 방안:
1) 반응형 디자인 추가 : CSS에 모바일 전용 스타일을 추가합니다:
@media (max-width: 768px) {
#table-of-contents {
font-size: 12px; /* 글씨 크기 축소 */
padding: 10px;
}
#table-of-contents ul {
max-height: 200px; /* 스크롤 높이 제한 */
}
}
2) 숨기기 버튼 크기 조정 : 숨기기 버튼 크기를 키워 터치가 용이하도록 수정합니다:
#table-of-contents button {
font-size: 1em; /* 버튼 크기 조정 */
padding: 5px 10px;
}
5. SEO(검색 엔진 최적화)와의 충돌
유의점:
- 목차에 추가한 ID가 검색 엔진 최적화(SEO)에 영향을 미칠 수 있습니다.
- 중복된 제목으로 인해 동일한 ID가 여러 번 생성될 가능성도 있습니다.
해결 방안:
1) ID 중복 방지: ID를 생성할 때 제목 텍스트를 포함해 고유하게 만듭니다.
const id = `${heading.textContent.replace(/\s+/g, '-').toLowerCase()}-${index}`;
heading.id = id;
2) SEO 최적화 확인: 목차가 SEO에 긍정적인 영향을 줄 수 있도록 제목과 목차 링크의 내용이 일치하도록 작성합니다.
6. 특정 스킨에서 목차 디자인이 어울리지 않음
유의점:
- 목차의 색상, 글씨 크기, 배경 등이 스킨의 디자인과 조화롭지 않을 수 있습니다.
해결 방안:
1) 목차 스타일 커스터마이징: CSS에서 색상과 스타일을 수정합니다:
#table-of-contents {
border: 2px solid #ccc; /* 테두리 색상 조정 */
background: #fff; /* 배경색 조정 */
color: #000; /* 글씨 색상 조정 */
}
2) 목차 숨김 설정: 목차를 기본적으로 숨겨두고 버튼 클릭 시 표시되도록 설정합니다:
#table-of-contents ul {
display: none;
}
7. 특수문자 포함 제목의 링크가 잘못 동작
유의점:
- 제목에 특수문자(예: &, %, !)가 포함되면 목차 링크가 제대로 작동하지 않을 수 있습니다.
해결 방안:
- 특수문자 제거 후 ID 생성: 제목에서 특수문자를 제거하고 ID를 생성합니다:
const id = `section-${index}-${heading.textContent.replace(/[^a-zA-Z0-9가-힣]/g, '')}`;
heading.id = id;
8. 목차 생성 성능 문제
유의점:
- 글의 제목이 많거나 페이지가 길면 목차 생성에 시간이 오래 걸릴 수 있습니다.
해결 방안:
1) 대상 태그 제한: h2, h3만 포함하도록 태그를 제한합니다:
const headings = postContent.querySelectorAll('h2, h3');
2) 페이지 로드 속도 확인: 목차가 표시되는 데 오래 걸린다면 스크립트를 최적화하거나, 목차 생성을 비동기적으로 처리합니다.