웹퍼블리싱 - 해시링크 오프셋 조절하기
Html, Css, Publishing해시링크란?
<a>
코드의 href 링크 안에 문서 내 id값을 넣어서 해당 id 위치로 이동하게 하는 해시 링크(Hash Link). 문서 내 주석이나 참조를 쓸 때나 nav list에 많이 쓴다. 내가 DLC 웹사이트 하드코딩 할 때 가장 많이 쓰는 기능 중 하나다.
ex: 문서의 nav list에 쓰인 해시링크
<ul>
<li><a href="#intro">JavaScript 소개</a></li>
<li><a href="#specification">표준 명세</a></li>
</ul>
ex: 문서의 주석 역할로 쓰인 해시링크
<p>var, let 정의 키워드를 앞에 둔 변수에 초기값을 지정하지 않았다면 그 변수는 <a href="#nullUndefined">undefined</a> 값을 할당받습니다.</p>
이슈 내용: 해시링크로 이동했을 때 컨텐츠가 너무 위에 붙음
그런데 해시 링크로 이동하게 하면 가끔 의도한 위치에서 조금 벗어난 위치로 스크롤이 멈추는 경우가 많다. 해당 id값이 margin값 등 요소 바깥 여백이 따로 설정된 div에 있더라도, div 내에서 가시적으로 보이는 영역의 최상단 (예를 들어 <h1>
)으로 스크롤이 이동한다.
이슈 발생 시 예상되는 문제점
만약 스크린에서 header가 fixed 되어있고, 해당 링크 요소에 여백이 충분히 설정되어있지 않다면, 해시링크로 스크롤이 이동되면 <h1>
등 보여지길 원하는 콘텐츠가 header에 가려져버리는 이슈가 발생한다. 이 이슈가 발생하면 사용자는 스크롤이 이상하게 이동되었다고 느끼고, 원하는 콘텐츠로 정확히 이동되었는지 파악하기 힘들어진다. 해시링크의 제 역할을 다하지 못하는 것이다.
이슈 해결과정
1. 요소의 margin & padding-top: fixed-header의 height값 + @
그렇다면 해시링크가 걸릴 요소들은 header의 height를 고려해서 margin, padding 여백을 충분히 주면 되지 않을까? 난 처음에 요소값에 padding-top을 크게 주어서 해결했다. (margin-top을 주어봤지만 요소 내 여백이 아니기때문에 이슈 해결에 영향을 미치지 않았다.)
그런데 이런 해결방법은 효율적인 해결책은 아니었다.
- 기존에 구상했던 페이지 디자인과 크게 어긋났고, 결국 여백값과 전체 타이포그래피를 다시 설계해야했다. 결과적으로 페이지 디자인의 자유도를 크게 해치고, 새로운 타이포그래피를 위한 리디자인을 2시간동안 해야했다.
- 그리고 여백을 크게 주다보니 모바일 등 작은 화면으로 봤을 때 컨텐츠가 없는 빈 화면도 종종 보였다.
- 미디어쿼리를 사용하지 않았기 때문에 wrapper 레이아웃은 margin: x auto 이지만 font-size 변화는 주지 않았다. 미디어쿼리를 넣으면 달라지겠지만 이 페이지는 적응형보다 컨텐츠 업데이트에 집중하고있다.
- 사용자가 지나치게 넓은 여백을 봤을 때 자칫하면 콘텐츠가 비어있거나 페이지가 덜 만들어졌다고 잘못 인식할 수도 있다.
요소의 여백 디자인을 해치지 않으면서 문제를 해결할 수는 없을까?
2. height값을 준 가상 요소 :before 생성
이후 우연히 다른 개발자분의 블로그를 서핑하다가 해당 이슈를 다룬 글을 발견했고, 내가 생각하지 못했던 좋은 해결책을 발견했다. 요소 앞에 가상 선택자 :before을 만들고 거기에 height값을 주는 것이다. 아래에 해당 링크를 적어놓았다. 해쉬 링크 오프셋 조정하기 | mulder 님의 블로그
:target:before{
content: "";
display: block;
height: 2em; /* fixed header 높이 만큼 부여 or 브라우저 상단에서 띄워놓기 원하는 높이 */
margin-top: -2em; /* 위에서 설정한 높이와 동일한 만큼을 음수로 제공 */
visibility: hidden;
}