본 글은 '북클럽 스킨'을 기준으로 목차가 스크롤을 따라서 화면에 떠다니는 '플로팅 자동 목차'를 생성하는 2가지 방법에 대한 내용이다.
아래 일전 발행한 글에서 연결되는 내용임을 참고 바란다.
1] 레이아웃 작업
'플로팅 자동 목차'를 생성하기 전에, '북클럽 스킨'의 레이아웃이 어떻게 구성되어 있는지 알아야 하고 레이아웃을 일부 수정해야 한다. (레이아웃을 수정하는 것은 선택사항이며, 보다 깔끔하게 적용하고자 한다면 수정하는 것을 추천한다.)
1-1] '북클럽 스킨'의 레이아웃 구성
아래는 '북클럽 스킨 메인 페이지'의 초기 레이아웃으로, '사이드바 - 가로 230px', '본문 - 가로 740px'으로 구성되어 있다.
아래는 '북클럽 스킨 본문 페이지'의 레이아웃으로 '메인 페이지'와 동일하게 구성되어 있다.
'북클럽 스킨 메인 페이지'를 전체적으로 보면 '사이드바 & 본문 - 가로 1080px', 'Padding - 좌우 20px', 'Margin - 좌우 Auto'로 구성되어 있다.
아래는 '북클럽 스킨 본문 페이지'의 레이아웃으로 역시 '메인 페이지'와 동일하다.
이처럼 '북클럽 스킨'의 초기 레이아웃은 좌우 여백이 좁기 때문에 '플로팅 자동 목차'를 적용하기에는 부적합하다.
만약 위와 같은 상태에서 '플로팅 자동 목차'를 적용한다면 화면이 빽빽ㆍ답답하게 보이고 화면 상의 무게 중심과 시선이 한쪽으로 치우지는 현상이 발생된다.
1-2] '북클럽 스킨'의 레이아웃 수정 (CSS)
① '#container' 수정
나는 '사이드바'를 좌측에 두었기 때문에 '플로팅 자동 목차'를 우측에 적용하기로 했고, '사이드바'와 '본문'을 좌측으로 이동시켜서 우측 공간을 확보했다.
CSS에서 #container .content-wrap {를 검색해서 찾고, 아래 코드와 같이 수정한다.
// 수정 전
#container .content-wrap {
max-width: 1080px;
margin: 0 auto;
padding: 0 20px;
}
// 수정 후
#container .content-wrap {
max-width: 1080px;
padding: 0px 0px 0px 60px;
}
위와 같이 수정하면 'Padding - 좌측 60px'가 적용되고 '본문'은 정확히 화면 중앙에 위치되며, 자연히 우측에 '플로팅 자동 목차'를 적용할 공간이 확보된다.
② '#aside' 수정
다음은 좌측 공간('사이드바')과 우측 공간('플로팅 자동 목차')이 대칭되도록 '사이드바 - 가로 px'를 수정한다.
CSS에서 #aside {를 검색해서 찾고, 아래 코드와 같이 수정한다.
// 수정 전
#aside {
float: right;
width: 21.296296296296296%;
padding: 73px 0 32px;
box-sizing: border-box;
}
// 수정 후
#aside {
float: right;
width: 250px;
padding: 73px 0 32px;
box-sizing: border-box;
}
위와 같이 수정하면 '사이드바 - 가로 250px'가 적용된다. (이는 '구글 애드센스(Adsense)' 광고의 넓이가 '가로 250px'임을 고려한 것이기도 하다.)
③ 'layout-aside-left' 수정
아래 이미지를 보면 '사이드바'와 '본문'을 구분해주던 '세로 선'이 '본문'과 오버랩되어 있다.
앞서 '사이드바'와 '본문'을 좌측으로 이동시킨 것에 따라 '세로 선'도 좌측으로 이동시킨다.
CSS에서 layout-aside-left를 검색해서 찾고, 아래 코드와 같이 수정한다.
// 수정 전
.layout-aside-left #container .content-wrap:before {
margin-left: -256px;
}
// 수정 후
.layout-aside-left #container .content-wrap:before {
margin-left: -410px;
}
위와 같이 수정하면 'Margin - 좌측 -410px'가 적용되어, '세로 선'이 '사이드바'와 '본문'의 중앙에 위치하게 된다.
①~③ 모두 수정하면 아래와 같이 '본문'을 중심으로 좌우 대칭 레이아웃이 완성된다.
2] '플로팅 자동 목차' 생성 방법 ①
'플로팅 자동 목차'를 생성하는 첫 번째 방법으로, '본문 자동 목차'가 적용되어 있지 않아도 된다.
해당 방법으로 적용할 경우 모바일 화면에서는 나타나지 않는다. (정확하게는 화면 밖에 존재한다.)
2-1] HTML 작업
① '</head>' 위 삽입
아래 코드를 HTML의 </head> 위에 삽입한다.
<script src="./images/jquery.toc.min.js"></script> 코드는 '본문 자동 목차' 코드와 동일하며 'jquery.toc.min.js' 파일도 업로드해야 한다. ('본문 자동 목차' 콘텐츠 참고)
<!-- 본문 & 플로팅 목차 시작 -->
<script src="./images/jquery.toc.min.js"></script>
<!-- 본문 & 플로팅 목차 끝 -->
<!-- 플로팅 목차 시작 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.css">
<!-- 플로팅 목차 끝 -->
</head>
② '<s_permalink_article_rep>' 아래 삽입
아래 코드를 HTML의 <s_permalink_article_rep> 코드와 <div class="post-cover"> 코드 사이에 삽입한다.
<s_permalink_article_rep>
<!-- 플로팅 목차 시작 -->
<div class='toc'></div>
<!-- 플로팅 목차 끝 -->
<div class="post-cover" style="background-image:url(https://tistory3.daumcdn.net/tistory/5032540/skin/images/titlebackground.jpg);">
③ '</body>' 위 삽입
아래 코드를 HTML의 </body> 위에 삽입한다. ('.entry-content'는 '북클럽 스킨'에 해당되는 코드이니, 사용하는 스킨에 맞는 코드로 변경해야 한다.)
<!-- 플로팅 목차 시작 -->
<script>
var content = document.querySelector(".entry-content");
var headings = content.querySelectorAll("h1, h2, h3, h4, h5, h6, h7");
var headingMap = {};
Array.prototype.forEach.call(headings, function (heading) {
var id = heading.id
? heading.id
: heading.textContent
.trim()
.toLowerCase()
.split(" ")
.join("-")
.replace(/[\!\@\#\$\%\^\&\*\(\):]/gi, "");
headingMap[id] = !isNaN(headingMap[id]) ? ++headingMap[id] : 0;
if (headingMap[id]) {
heading.id = id + "-" + headingMap[id];
} else {
heading.id = id;
}
});
tocbot.init({
tocSelector: ".toc",
contentSelector: ".entry-content",
headingSelector: "h2, h3, h4",
hasInnerContainers: false,
});
$(document).ready(function () {
$(".toc").addClass("toc-absolute");
var toc_top = $(".toc").offset().top - 165;
$(window).scroll(function () {
if ($(this).scrollTop() >= toc_top) {
$(".toc").addClass("toc-fixed");
$(".toc").removeClass("toc-absolute");
} else {
$(".toc").addClass("toc-absolute");
$(".toc").removeClass("toc-fixed");
}
});
});
</script>
<!-- 플로팅 목차 시작 끝 -->
</body>
①~③ 모두 삽입하면 아래와 같이 목차가 본문 상단에 생성된다.
2-2] CSS 작업
이제 CSS 작업을 통해 생성된 목차의 위치와 스타일을 적용한다.
아래 코드를 CSS에 삽입한다.
/* 플로팅 목차 스타일 */
.toc-absolute {
position: absolute;
margin-top: 10px;
}
.toc-fixed {
position: fixed;
top: 100px;
}
.toc {
right: calc((100% - 1515px) / 2 - 0px);
width: 330px;
padding: 10px;
box-sizing: border-box;
}
.toc-list > li {
margin-top: 10px !important;
font-size: 0.9em;
}
.toc > .toc-list li {
margin-bottom: 10px;
}
.toc > .toc-list li:last-child {
margin-bottom: 0;
}
.toc > .toc-list li a {
text-decoration: none;
}
@media screen and (max-width: 800px) {
.toc {
display: none;
}
}
CSS 작업까지 완료하면 아래와 같이 목차가 우측 공간에 생성된다. (만약 '사이드바'를 우측 공간에 두고 '플로팅 자동 목차'를 좌측 공간에 적용하고자 한다면, 상기 코드에서 'right'를 'left'로 수정하고 '숫자'값을 조정하면 된다.)
2-3] '카테고리 글 더 보기' 플러그인 해제
그런데 아래와 같이 화면을 제일 아래로 내리면 목차 제일 아래에 '카테고리의 다른 글' 이 적용되어 있다.
이는 '본문 자동 목차' 콘텐츠에서 말했던 '카테고리의 다른 글 제거 코드'를 삽입해도 제거되지 않아서 애를 먹었는데, 아래의 '카테고리 글 더 보기' 플러그인을 해제하면 제거된다.
아래 영상은 '플로팅 자동 목차' 생성 첫 번째 방법의 적용 결과다.
화면을 위아래로 이동해도 목차는 고정되어 있다. 또한 현재 위치한 화면에 해당되는 목차가 자동으로 bold 처리되고, 자동으로 접히고 펼쳐진다.
목차를 클릭하면 해당 위치로 화면이 부드럽게 이동한다.
3] '플로팅 자동 목차' 생성 방법 ②
'플로팅 자동 목차'를 생성하는 두 번째 방법으로, '본문 자동 목차'가 적용되어 있어야 한다. 해당 방법으로 적용할 경우 모바일 화면에서도 나타난다.
3-1] HTML 작업
아래 코드를 HTML의 </body> 위에 삽입한다.
화면이 '본문 자동 목차'를 지나 아래로 내려가면 지정한 위치에 '플로팅 자동 목차'가 생성된다. 'Contents', 'OPEN', 'CLOSE' 부분은 기호에 맞게 수정하면 된다.
<!-- 본문 목차의 플로팅 효과 시작 -->
<div class="book-toc-floating"></div>
<script>
function appendToc() {
var bookToc = $('.book-toc');
var booktocfloating = $('.book-toc-floating');
if(bookToc.length > 0 && window.scrollY > bookToc.offset().top + bookToc.innerHeight()) {
if(booktocfloating.height() === 0) {
bookToc.css('width',bookToc.width()+"px");
bookToc.css('height',bookToc.height()+"px");
var tocTitle = $('<div id="toc-title"><p>Contents <span style="opacity:0.5;">OPEN</span></p></div>');
booktocfloating.append(tocTitle);
bookToc.css('height', bookToc.height());
var tocBody = $('<div id="toc-body" style="display:none;"></div>').append(bookToc.find('#toc'));
booktocfloating.append(tocBody);
$('#toc-title').on('click', function() {
$('#toc-body').slideToggle();
var title = $('#toc-title>p>span');
if(title.text() === "OPEN") {
title.text("CLOSE");
} else {
title.text("OPEN");
}
});
}
var positionX = 20; // 가로 20px
booktocfloating.css('top', (window.scrollY+100)+"px"); // 위를 기준으로 100px에 위치
booktocfloating.css('right', positionX+"px"); // 오른쪽을 기준으로 20px에 위치
booktocfloating.css('transition', "0.3s"); // 0.3초에 걸쳐 출력
} else {
$('#toc-title').off('click');
bookToc.append(booktocfloating.find('#toc'));
booktocfloating.find('div').remove();
booktocfloating.removeAttr('style');
}
}
$(document).ready(function() {
$(window).on('scroll', function() {
appendToc();
});
});
</script>
<!-- 본문 목차의 플로팅 효과 끝 -->
</body>
3-2] CSS 작업
아래 코드를 CSS에 삽입한다.
/* 본문 목차의 플로팅 효과 스타일 */
.book-toc-floating {
position: absolute;
cursor: pointer;
border-top: 2px solid black;
border-bottom: 2px solid black;
background: white;
padding: 10px;
z-index: 999;
line-height: 1.2em;
}
.book-toc-floating p {
font-weight: bold;
font-size: 1em !important;
color: black;
}
.book-toc-floating #toc-body {
margin-top: 10px;
}
.book-toc-floating #toc-body #toc * {
font-size: 12px;
}
.book-toc-floating #toc > li > ul {
margin-bottom: 5px;
}
CSS 작업까지 완료하면 아래와 같이 목차가 우측 공간에 생성된다.
'플로팅 자동 목차' 생성 두 번째 방법을 적용하면 PC와 Mobile 모두 나타난다.
화면을 '본문 자동 목차'의 아래로 내리면 우측 상단에 '플로팅 자동 목차'가 자동으로 나타나고, 화면을 다시 '본문 자동 목차'로 올리면 '플로팅 자동 목차'는 자동으로 사라진다.
또한 'OPEN'을 클릭하면 목차가 펼쳐지고, 'CLOSE'를 클릭하면 목차가 접힌다.