티스토리 뷰
이 포스팅은 tistory 스킨 #1을 기준으로 작성된 것입니다.
계기
현재 Tistory에서 제공하는 #1 스킨을 사용중입니다.
평소 모니터를 3대를 사용중인데 이 스킨을 사용하면서 피벗 모니터에서 블로그 글을 보았을 때는 세로가 길어 가독성이 괜찮아 보였다가 반대로 피벗이 아닌 평범한 16:9 비율의 환경에서 글을 보았을 때 글의 내용이 상단바에 가려져 가독성이 좋지 않아 글을 읽기가 불편한 것 같다라는 생각을 하게 되었습니다.
'글을 읽을 경우 상단바를 없애면 읽기 편하지 않을까?' 라는 호기심에 이 기능을 만들어보게 되었습니다. :)
github 저장소는 아래에 있습니다! :)
sukvvon/tistory-top-bar-visible
css
.hidden {
animation: hide 0.1s linear forwards;
}
@keyframes hide {
from {
opacity: 1;
}
to {
opacity: 0;
visibility: hidden;
}
}
.shown {
animation: show 0.1s linear forwards;
}
@keyframes show {
from {
visibility: hidden;
opacity: 0;
}
to {
opacity: 1;
}
}
.hidden, .shown
.hidden {
animation: hide 0.1s linear forwards;
}
.shown {
animation: show 0.1s linear forwards;
}
숨김과 보임을 의미하는 hidden
과 shown
으로 class 이름을 지었습니다.
animation을 활용하였습니다. hidden
에서는 hide라는 이름의 애니메이션을, shown
에서는 show라는 이름의 애니메이션 효과를 주고,
hidden
과 shown
에서 animation-duration은 0.1초로 설정하여 0.1초동안 애니메이션이 실행되도록 하고, animation-timing-funcion은 linear
로 설정하여 균일한 속도로 진행되게 하며, animation-fill-mode는 forwards
로 설정하여 실행 된 애니메이션의 마지막 @keyframes에 의해 설정된 계산 된 값을 유지하도록 합니다.
@keyframe hide and show
@keyframes hide {
from {
opacity: 1;
}
to {
opacity: 0;
visibility: hidden;
}
}
@keyframes show {
from {
visibility: hidden;
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes hide
@keyframes hide
에서 전형적인 오프셋 from
과 to
를 기준으로 opacity: 1
로부터 opacity: 0
과 visibiliy: hidden
속성으로 가게끔 하여,
opacity 즉 요소의 불투명도를 1에서 0으로 하여 완전히 불투명하였다가 완전히 투명하도록 하고,
visibility 즉 요소의 보임을 hidden
즉 숨겨지게 하여 opacity
에 의해서 투명해졌지만 물리적으로 존재했던 요소를 숨김처리를 하여 물리적으로 존재하지 않고 레이아웃 상으로만 존재하게 합니다.
@keyframes show
@keyframes show
에서는 @keyframes hide
와 반대가 되도록 합니다.
js
const HIDDEN_CLASSNAME = "hidden";
const SHOWN_CLASSNAME = "shown";
const dkHead = document.getElementById("dkHead");
const areaMenu = document.querySelector(".area_menu");
const areaTitle = document.querySelector(".area_title");
let beforeScrollY = [];
const handleTopBar = (useClassName, unuseClassName) => {
dkHead.classList.add(useClassName);
dkHead.classList.remove(unuseClassName);
areaMenu.classList.add(useClassName);
areaMenu.classList.remove(unuseClassName);
};
window.addEventListener("scroll", () => {
if (window.scrollY > areaTitle.offsetHeight) {
if (beforeScrollY.pop() < window.scrollY) {
handleTopBar(HIDDEN_CLASSNAME, SHOWN_CLASSNAME);
} else {
handleTopBar(SHOWN_CLASSNAME, HIDDEN_CLASSNAME);
}
beforeScrollY.push(window.scrollY);
}
});
자주 쓰이는 변수 선언
const HIDDEN_CLASSNAME = "hidden";
const SHOWN_CLASSNAME = "shown";
2번 이상 쓰이는 String은 오타가 날 수 있기 때문에 변수 선언을 꼭 해주는 편입니다.
class의 역활을 가지고 있는 "hidden"
, "shown"
을 HIDDEN_CLASSNAME
과 SHOWN_CLASSNAME
으로 대문자만으로 이름을 지어 변수를 선언해줍니다.
id 혹은 class 요소를 찾아 변수 선언
const dkHead = document.getElementById("dkHead");
const areaMenu = document.querySelector(".area_menu");
const areaTitle = document.querySelector(".area_title");
dkHead
const dkHead = document.getElementById("dkHead");
getElementById 메서드를 활용하여 상단바 전체를 의미하는 id 속성을 가진 요소 #dkHead
를 찾아서 호출한 후 dkHead
로 변수를 선언합니다.
areaMenu
const areaMenu = document.querySelector(".area_menu");
querySelector 메서드를 활용하여 상단바 전체를 의미하는 dkHead
와 달리 상단바에 독립적으로 위치한 요소인 .area_menu
를 호출한 후 areaMenu
로 변수를 선언합니다.
areaTitle
const areaTitle = document.querySelector(".area_title");
querySelector 메서드를 활용하여
글의 제목을 의미하지만 여기서는 상단바를 숨기는 기준이 되는 요소인 .area_title
을 호출한 후 areaTitle
로 변수를 선언합니다.
handleTopBar()
const handleTopBar = (useClassName, unuseClassName) => {
dkHead.classList.add(useClassName);
dkHead.classList.remove(unuseClassName);
areaMenu.classList.add(useClassName);
areaMenu.classList.remove(unuseClassName);
};
상단바를 숨기고 보이게 하는 함수입니다.
추가하여 사용할 예정이라는 의미인 useClassName
, 삭제하여 사용하지 않을 예정이라는 의미인 unuseClassName
라고 이름지은 두 개의 매개변수를 포함하는 함수로 구성합니다.
handelTopBar
함수가 실행되면 classList가 사용되며 add
와 remove
를 통해 dkHead
와 areaMenu
의 class 목록에서 useClassName
을 추가하고 unuseClassName
를 삭제시킵니다.
beforeScrollY
let beforeScrollY = [];
언제든 새로운 값이 들어올 수 있도록 const
가 아닌 let
으로 이전의 window.scrollY
값을 받는다는 뜻의 beforeScrollY
로 배열을 선언합니다.
addEventListener("scroll", () => {})
window.addEventListener("scroll", () => {
if (window.scrollY > areaTitle.offsetHeight) {
if (beforeScrollY.pop() < window.scrollY) {
handleTopBar(HIDDEN_CLASSNAME, SHOWN_CLASSNAME);
} else {
handleTopBar(SHOWN_CLASSNAME, HIDDEN_CLASSNAME);
}
beforeScrollY.push(window.scrollY);
}
});
addEventListener()
addEventListener()을 통해 scroll이벤트가 발생할 경우 화살표 함수가 실행되도록 합니다.
if else
window.scrollY가 areaTitle.offsetHeight보다 클 경우 즉 화면 전체의 세로 방향으로 스크롤된 값이 전체 글의 제목 높이보다 크다는 조건에서
beforeScrollY.pop()이 window.scrollY
보다 작을 경우 즉 페이지가 아래로 스크롤 되면서 beforeScrollY
배열의 마지막 값이 화면 전체의 높이보다 작을 경우 handleTopBar(HIDDEN_CLASSNAME, SHOWN_CLASSNAME)
함수가 실행되며 상단바를 보이지 않게 하고
아닐 경우 즉 반대로 페이지가 위로 스크롤 되면서 beforeScrollY
배열의 마지막 값이 화면 전체의 높이보다 클 경우 handleTopBar(SHOWN_CLASSNAME, HIDDEN_CLASSNAME)
함수가 실행되며 상단바를 보이게 합니다.
push()
위의 과정이 끝난 후 beforeScrollY.push(window.scrollY) 로 인하여 조건문에서 사용되었던 window.scrollY
값이 beforeScrollY
배열에 추가됩니다.
그리고 scroll
이벤트가 발생될 때마다 모든 과정이 반복됩니다.
'JavaScript' 카테고리의 다른 글
Tistory(#1) theme toggle 구현기 (0) | 2022.02.22 |
---|