FE
디자인은 디테일에 있다, ::after를 활용한 밑줄 애니메이션
가운데에서 퍼지는 밑줄 효과, ::after로 만드는 동적인 스타일링
React 프로젝트에서 메뉴 탭이나 버튼과 같은 인터랙티브한 UI를 만들 때, 사용자의 선택을 시각적으로 명확하게 표현해 주는 것은 중요하다. 그 대표적인 방식 중 하나가 border-bottom을 이용한 밑줄 효과이다. 하지만 border는 애니메이션 표현이 제한적이기 때문에, 부드러운 전환이나 동적인 효과를 주기에는 한계가 있다.
이럴 때 유용하게 사용할 수 있는 것이 바로 CSS 가상 요소(Pseudo-element) 이다. 그중에서도 ::after는 특정 요소의 내부가 아닌 외부에 시각적 효과를 추가할 수 있는 수단으로 매우 유용하다.
?잠깐!!? CSS 가상 요소에 대해서는 아래 글을 참고하자!https://pangil-log.tistory.com/326
::after란 무엇인가?
::after는 HTML 요소 뒤에 추가되는 가상의 시각 요소이다. HTML 구조를 변경하지 않고도 시각적인 장식을 더할 수 있기 때문에, 마크업을 깔끔하게 유지하면서도 다양한 효과를 구현할 수 있는 장점이 있다. 흔히 장식선, 말풍선 꼬리, 강조 효과 등에 활용된다.
selector::after {
content: "";
display: block;
...
}위와 같이 사용되며, 필수적으로 content 속성이 필요하다. 내용이 없더라도 ""를 넣어줘야 화면에 나타나게 된다.
가운데에서 퍼지는 밑줄 효과 구현하기
React 프로젝트에서 styled-components를 활용해 메뉴 선택 시 가운데에서 밑줄이 퍼지는 효과를 다음과 같이 구현할 수 있다.
import React from "react";
import "./TestPage.css"; // CSS 따로 분리
export default function TestPage() {
return (
<div className="container">
<h2 className="title">가상 요소 ::after를 이용한 밑줄 애니메이션</h2>
<button className="button">호버해보세요</button>
</div>
);
}/* 전체 컨테이너 중앙 정렬 */
.container {
display: flex; /* Flexbox 사용 */
flex-direction: column; /* 세로 방향으로 정렬 */
align-items: center; /* 가로 기준 중앙 정렬 */
justify-content: center; /* 세로 기준 중앙 정렬 */
padding-top: 100px; /* 상단 여백 */
}
/* 제목 스타일 */
.title {
font-size: 24px; /* 글자 크기 */
margin-bottom: 30px; /* 아래쪽 여백 */
}
/* 버튼 기본 스타일 */
.button {
position: relative; /* ::after의 기준이 되는 상대 위치 */
padding: 10px 20px; /* 내부 여백 */
font-weight: bold; /* 글자 굵게 */
cursor: pointer; /* 마우스 커서를 손가락으로 표시 */
background: none; /* 배경 제거 */
border: none; /* 테두리 제거 */
font-size: 16px; /* 글자 크기 */
color: royalblue; /* 글자 색상 */
}
/* ::after 가상 요소로 밑줄 구현 */
.button::after {
content: ""; /* 가상 요소 필수, 내용 없음 */
position: absolute; /* 부모 기준 절대 위치 */
bottom: 0; /* 아래쪽에 위치 */
left: 0; /* 왼쪽부터 시작 */
height: 3px; /* 밑줄 두께 */
width: 100%; /* 버튼 전체 너비만큼 */
background-color: royalblue; /* 밑줄 색상 */
transform: scaleX(0); /* 처음엔 가로 크기 0으로 숨김 */
transform-origin: center; /* 가운데 기준으로 확대/축소 */
transition: transform 0.3s ease; /* 부드럽게 전환 */
}
/* hover 시 밑줄 퍼지게 만들기 */
.button:hover::after {
transform: scaleX(1); /* 가로 크기 100%로 보여줌 */
}이 스타일은 다음과 같은 방식으로 작동한다.
position: relative::after 가상 요소를 부모 요소 내부의 기준 위치에 배치하기 위해 필요하다.
::after 내부에서 position: absolute부모 요소의 왼쪽 아래에 위치한 밑줄을 생성한다. 시각적으로는 border-bottom과 유사하나, 더 많은 제어가 가능하다.
transform: scaleX(...)밑줄의 가로 길이를 변화시키는 방식이다. scaleX(1)이면 정상 크기, scaleX(0)이면 보이지 않게 된다.
transform-origin: center밑줄이 퍼지거나 사라질 때 가운데를 기준으로 좌우로 펼쳐지거나 수축되는 효과를 만든다.
transition부드러운 전환 애니메이션을 적용한다. 클릭 시 자연스럽게 효과가 반응하게 된다.
border-bottom 대신 ::after를 선택한 이유
항목 | border-bottom 사용 시 | ::after 사용 시 |
애니메이션 표현 | 제한적 | transform으로 다양하게 표현 가능 |
커스터마이징 범위 | 좁음 | 두께, 위치, 애니메이션 등 자유로움 |
마크업 간결함 | 동일 | 동일 (DOM 구조는 그대로 유지됨) |
border-bottom은 간단한 정적 표현에는 적합하지만, 부드러운 전환을 요하는 인터랙션에는 다소 불리하다. 반면 ::after는 별도의 가상 박스를 이용하기 때문에, 보다 풍부한 사용자 경험을 제공할 수 있다.
적용할 수 있는 UI 예시
탭 메뉴 또는 네비게이션 바
버튼 클릭 시 강조 효과
리스트 선택 시 하단 밑줄
카드 hover 시 강조 선 표현
이러한 UI들은 사용자에게 명확한 피드백을 주고, 선택 상태를 직관적으로 알려주는 데 큰 역할을 한다.
마무리
::after는 간단하면서도 강력한 CSS 기능이다. styled-components와 같은 CSS-in-JS 라이브러리와 결합할 경우, 컴포넌트 상태에 따라 시각 효과를 자연스럽게 제어할 수 있다.
이번 예제처럼 transform, transition, transform-origin을 함께 활용하면, 단순한 UI도 더욱 풍부하고 세련되게 만들 수 있다. 깔끔한 마크업을 유지하면서도 동적인 인터페이스를 구현하고자 한다면, ::after는 분명히 좋은 선택지가 될 것이다.