0169

FE

디자인은 디테일에 있다, ::after를 활용한 밑줄 애니메이션

가운데에서 퍼지는 밑줄 효과, ::after로 만드는 동적인 스타일링

React 프로젝트에서 메뉴 탭이나 버튼과 같은 인터랙티브한 UI를 만들 때, 사용자의 선택을 시각적으로 명확하게 표현해 주는 것은 중요하다. 그 대표적인 방식 중 하나가 border-bottom을 이용한 밑줄 효과이다. 하지만 border는 애니메이션 표현이 제한적이기 때문에, 부드러운 전환이나 동적인 효과를 주기에는 한계가 있다.

이럴 때 유용하게 사용할 수 있는 것이 바로 CSS 가상 요소(Pseudo-element) 이다. 그중에서도 ::after는 특정 요소의 내부가 아닌 외부에 시각적 효과를 추가할 수 있는 수단으로 매우 유용하다.

?잠깐!!? CSS 가상 요소에 대해서는 아래 글을 참고하자!https://pangil-log.tistory.com/326

::after란 무엇인가?

::after는 HTML 요소 뒤에 추가되는 가상의 시각 요소이다. HTML 구조를 변경하지 않고도 시각적인 장식을 더할 수 있기 때문에, 마크업을 깔끔하게 유지하면서도 다양한 효과를 구현할 수 있는 장점이 있다. 흔히 장식선, 말풍선 꼬리, 강조 효과 등에 활용된다.

CSS
selector::after {
  content: "";
  display: block;
  ...
}

위와 같이 사용되며, 필수적으로 content 속성이 필요하다. 내용이 없더라도 ""를 넣어줘야 화면에 나타나게 된다.

가운데에서 퍼지는 밑줄 효과 구현하기

React 프로젝트에서 styled-components를 활용해 메뉴 선택 시 가운데에서 밑줄이 퍼지는 효과를 다음과 같이 구현할 수 있다.

JavaScript
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>
    );
}
CSS
/* 전체 컨테이너 중앙 정렬 */
.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%로 보여줌 */
}

이 스타일은 다음과 같은 방식으로 작동한다.

  1. position: relative::after 가상 요소를 부모 요소 내부의 기준 위치에 배치하기 위해 필요하다.

  2. ::after 내부에서 position: absolute부모 요소의 왼쪽 아래에 위치한 밑줄을 생성한다. 시각적으로는 border-bottom과 유사하나, 더 많은 제어가 가능하다.

  3. transform: scaleX(...)밑줄의 가로 길이를 변화시키는 방식이다. scaleX(1)이면 정상 크기, scaleX(0)이면 보이지 않게 된다.

  4. transform-origin: center밑줄이 퍼지거나 사라질 때 가운데를 기준으로 좌우로 펼쳐지거나 수축되는 효과를 만든다.

  5. 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는 분명히 좋은 선택지가 될 것이다.