디자인적으로 잘 갖춰진 웹을 돌아다니다 보면 메뉴의 요소들에 마우스를 이동할 때 hover 효과가 끊어지는 효과가 아닌 부드러운 배경의 이동을 사용하는 경우가 있다.

이번 과제는 상단 메뉴뿐만 아니라 페이지 전체에서 스크롤을 해도 모든 <a> 태그에 그런 효과를 주며 마우스를 이동할 때 마다 흰 배경이 따라다니게 구현하는 것을 목적으로 한다.

CSS 이해하기

1
2
3
4
5
6
7
8
9
10
11
12
13
/* highlight는 span 객체 */
.highlight {
transition: all 0.2s;
border-bottom: 2px solid white;
position: absolute;
top: 0;
background: white;
left: 0;
z-index: -1;
border-radius: 20px;
display: block;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}

미리 작성된 css를 보면 absolute 위치 속성과 z-index: -1을 적용했다. 객체의 절대적인 위치 값과 화면의 가로, 세로 값을 이용할 것이기 때문이다. transition: all 0.2s;는 객체에서 css의 변화가 일어날 때 모든 효과 변화에 대해 0.2초 간격의 부드러운 변환을 제공한다.

사실 이런 것들이 css에서 암기보다는 이해에 가깝다고 생각한다. 외우지 않아도 된다는 말을 많이 하지만, 적어도 이런 효과를 어떤 로직으로 주어야 할 지는 알아야 구글에 뭐라고 검색해야 할 지라도 알기 때문이다.

Script 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function highlightLink() {
const linkCoords = this.getBoundingClientRect();
console.log(linkCoords);
const coords = {
width: linkCoords.width,
height: linkCoords.height,
top: linkCoords.top + window.scrollY,
left: linkCoords.left + window.scrollX,
};

highlight.style.width = `${coords.width}px`;
highlight.style.height = `${coords.height}px`;
highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;
}

getBoundingClientRect()는 요소의 각종 좌표값이 들어있는 객체를 반환한다. 예를 들어 getBoundingClientRect().top은 Viewport의 시작지점을 기준으로 한 상대좌표 Y 값을 구할 수 있다.

그런데 이번 과제에서는 스크롤을 내려도 highlight 객체가 정확히 이동해야 하므로 window.scrollX, window.scrollY로 스크롤한 X, Y 값을 가져와서 더해주어야 정확한 요소의 위치에 객체가 이동한다.

이제 a 태그에 mouseenter 이벤트만 걸어주면 된다.

1
triggers.forEach((a) => a.addEventListener("mouseenter", highlightLink));