AD JB Toolbox 01

CSS 강좌 / ::before와 ::after로 가상 요소 꾸미기

CSS의 ::before와 ::after는 선택한 요소의 내용 앞이나 뒤에 가상 요소를 만들어 꾸미는 기능입니다. 장식용 점이나 선을 추가할 때 유용하며, 보통 content: ""로 빈 내용을 만든 뒤 크기·색·배치 속성을 지정합니다. 운영 시간이나 버튼 이름처럼 중요한 정보는 CSS로 생성하지 말고 HTML에 직접 넣어야 합니다.

가상 클래스와 가상 요소의 차이

가상 클래스는 기존 요소가 어떤 상태나 조건에 있는지 고릅니다. a:hover는 마우스를 올린 링크 자체가 대상입니다. 가상 요소는 요소의 특정 부분이나 생성한 표현을 대상으로 합니다. a::after는 링크 내용 뒤에 만들어지는 가상 요소를 꾸밉니다. 새 코드에서는 둘을 구별하기 쉽도록 가상 클래스에 콜론 하나, 가상 요소에 콜론 두 개를 사용하세요.

a:hover { color: #1d4ed8; }
a::after { content: ""; }

before와 after는 선택한 요소의 바깥에 실제 HTML 형제 태그를 추가하는 방식이 아닙니다. 해당 요소의 내용 앞·뒤에 표현을 생성합니다. 개발자 도구가 가상 요소를 별도 줄로 보여 줄 수 있지만, 원본 HTML에 span을 적어 넣은 것과는 다릅니다. 일반적인 자식 요소를 찾는 코드로 생성된 가상 요소를 그대로 가져올 수도 없습니다.

content와 display가 필요한 이유

h1::before {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  background-color: currentColor;
}

content: ""는 텍스트가 없는 가상 요소를 생성합니다. 내용이 비어 있어도 배경과 크기를 주면 장식 상자로 보일 수 있습니다. 반면 content를 생략하거나 none으로 바꾸면 이 가상 요소는 생성되지 않아 크기와 배경을 넣어도 점이 나타나지 않습니다.

before와 after의 기본 표시 방식은 inline입니다. 일반적인 inline 상자에는 width와 height가 기대하는 크기 조절 방식으로 적용되지 않으므로, 점처럼 너비와 높이가 필요한 장식에는 inline-block을 사용합니다. 내용 뒤에서 줄을 하나 차지하는 선에는 display: block을 사용합니다. content와 기본 표시 방식, 사용 범위는 MDN의 ::before 설명을 참고할 수 있습니다.

currentColor는 해당 요소의 color 값, 즉 현재 글자색을 참조하는 키워드입니다. 제목을 초록색에서 파란색으로 바꾸면 가상 요소의 배경에도 같은 색이 쓰입니다. border-radius: 50%는 같은 너비·높이의 상자 모서리를 둥글게 만들어 원처럼 보이게 합니다. margin-right는 점과 글자 사이의 바깥 여백입니다.

제목 앞의 점과 링크 뒤의 선 만들기

다음 전체 예제에서는 제목 앞에 12px 점을, 링크 아래에 2px 선을 만듭니다. 링크 자체의 기본 밑줄도 남겨 두므로 추가 선이 없어져도 링크의 구분이 유지됩니다. 마우스를 올리거나 키보드 포커스가 표시되는 상태에서는 장식 선이 4px로 두꺼워집니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>작은 정원</title>
  <style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; color: #333; }
    h1 { color: #087f5b; font-size: 30px; }
    h1::before {
      content: "";
      display: inline-block;
      width: 12px;
      height: 12px;
      margin-right: 10px;
      border-radius: 50%;
      background-color: currentColor;
    }
    a { display: inline-block; color: #087f5b; text-decoration: underline; }
    a::after {
      content: "";
      display: block;
      height: 2px;
      margin-top: 4px;
      background-color: currentColor;
    }
    a:hover::after, a:focus-visible::after { height: 4px; }
    a:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 4px; }
  </style>
</head>
<body>
<h1>작은 정원</h1>
  <p>매일 오전 9시에 문을 엽니다.</p>
  <a href="#visit">방문 안내</a>
  <h2 id="visit">방문할 때 준비할 것</h2>
  <p>물병과 편한 신발을 준비하세요.</p>
</body>
</html>

index.html로 저장해 실행하세요. 제목은 “작은 정원”이라는 실제 텍스트를 그대로 가지며 앞의 원은 CSS 장식입니다. 링크도 “방문 안내”라는 이름과 이동 주소를 HTML에 가지고 있습니다. a:hover::after는 hover 상태인 a의 after를 선택하는 표현입니다. 콜론 수와 선택 순서를 나누어 읽으면 긴 표기가 덜 복잡하게 느껴집니다.

같은 작은 정원 문서의 가상 요소 적용 전후 화면. 적용 후 제목 앞에 초록색 점, 방문 안내 링크 아래에 장식 선이 생겼다

위 비교는 같은 예제를 브라우저에서 렌더링하고, 왼쪽에서만 before와 after의 content를 none으로 바꾼 실제 결과입니다. 글자와 링크 주소는 동일하며 장식만 달라집니다. 오른쪽 링크의 장식 선은 기본 상태의 2px이며, hover나 키보드 포커스 상태에서는 4px가 됩니다.

정보와 장식을 나누는 기준

넣을 내용 권장 위치 이유
제목 앞 점, 구분선 CSS 가상 요소 없어도 문서의 의미와 작업 방법이 유지됩니다.
운영 시간, 가격, 주의사항 HTML 텍스트 CSS를 끄거나 다른 방식으로 읽어도 중요한 내용이 남아야 합니다.
버튼 이름, 링크 이름 HTML의 실제 콘텐츠 조작 대상의 이름이 장식 생성에 의존하지 않게 합니다.

스크린 리더와 브라우저에 따라 생성 콘텐츠의 전달 방식이 다를 수 있으므로, 필수 정보를 가상 요소에만 넣는 방법에 의존하지 마세요. content: "필수"로 입력 조건을 알려 주는 것보다 실제 label이나 안내 문장에 조건을 쓰는 편이 명확합니다. 가상 요소가 보인다는 사실만으로 접근성이 확인된 것은 아닙니다.

img처럼 대체 콘텐츠를 표시하는 요소에 before와 after를 붙이는 방식은 일반적인 장식 구현으로 의존하지 않는 편이 좋습니다. 이 예제처럼 h1이나 a처럼 내용을 담는 요소에 적용하세요. 이미지 주위에 장식이 필요하다면 이미지를 감싼 별도의 HTML 요소를 두고 그 요소의 가상 요소를 꾸미는 방식을 검토할 수 있습니다.

보이지 않는 가상 요소를 점검하는 실습

  1. h1::before의 content: "";를 content: none;으로 바꿉니다. 제목 글자는 그대로인데 점만 사라져야 합니다. 확인 후 빈 문자열로 복원합니다.
  2. 점의 display: inline-block;을 display: inline;으로 바꿉니다. 텍스트가 없는 inline 장식에서는 width·height만으로 원래 12px 점을 유지할 수 없다는 것을 확인합니다. inline-block으로 되돌립니다.
  3. h1의 color를 #1d4ed8로 바꿉니다. 점에도 파란색이 적용되고 링크의 초록색은 그대로인지 확인합니다. currentColor가 페이지 전체의 색 하나를 참조하는 것은 아닙니다.
  4. 마우스를 링크 위에 올리고 선이 두꺼워지는지 확인합니다. 마우스를 치운 뒤 Tab으로 링크에 포커스를 옮겨 선과 외곽선이 함께 보이는지 확인합니다.

점검할 때는 먼저 선택자가 실제 요소에 맞는지와 content가 유효한지 확인하고, 그 다음 display·크기·배경을 봅니다. 링크 선의 height를 0으로 바꾸면 선은 보이지 않지만 content로 생성한 가상 요소 자체가 반드시 사라지는 것은 아닙니다. “요소가 생성되지 않은 상태”와 “생성됐지만 그릴 면적이 없는 상태”를 구별하면 실패 원인을 좁힐 수 있습니다.

실습을 마친 뒤 바꾼 값을 원래대로 저장하세요. 가상 요소는 장식 때문에 HTML 태그를 늘리는 일을 줄여 주지만, 중요한 내용을 숨겨 넣는 수단은 아닙니다. 작은 점·선처럼 의미를 바꾸지 않는 표현부터 적용하고 실제 텍스트와 키보드 동작이 유지되는지 확인하는 것이 좋습니다.

같은 카테고리의 다른 글
CSS / Tutorial / 인용문(Blockquote) 꾸미는 방법

CSS / Tutorial / 인용문(Blockquote) 꾸미는 방법

blockquote 요소의 기본 모양은 양쪽에 여백이 있는 것입니다. 그대로 사용하기보다는 여러 가지 모양으로 꾸미는 것이 일반적입니다. 다음은 아래와 같은 인용문을 꾸미는 몇 가지 예제입니다.

CSS / Tutorial / 세로 가운데 정렬하는 방법

CSS / Tutorial / 세로 가운데 정렬하는 방법

CSS에서 텍스트의 가로 가운데 정렬은 text-align 속성을 이용합니다. 요소의 가로 가운데 정렬은 margin 속성을 이용합니다. 세로 정렬을 가운데로 하려면 어떻게 해야 할까요? 네 가지 방법을 소개합니다.

CSS / Tutorial / 표 꾸미기 / 테두리

CSS / Tutorial / 표 꾸미기 / 테두리

테두리는 border 속성으로 만듭니다. table, th, td 요소에 적용할 수 있습니다. tr 요소에는 적용되지 않습니다.

CSS / Tutorial / 상속(inheritance)

CSS / Tutorial / 상속(inheritance)

CSS 속성은 상속하는 속성과 상속하지 않는 속성이 있습니다. 상속하는 속성은 자식 요소에 영향을 미칩니다. 상속하지 않는 속성은 자식 요소에 영향을 미치지 않습니다.

CSS / Tutorial / 유튜브 동영상을 반응형으로 삽입하는 방법

CSS / Tutorial / 유튜브 동영상을 반응형으로 삽입하는 방법

유튜브 영상을 블로그나 홈페이지에 넣을 때 보통 iframe을 사용합니다. 코드는 유튜브 영상 공유에서 를 클릭하여 구할 수 있습니다. 아래와 같은 코드인데, 고정폭입니다. 즉 웹브라우저의 가로폭이 커지든 작아지든 가로폭이 일정합니다. 이를 반응형으로 만들고 싶다면 아래처럼 합니다.

CSS / Tutorial / 표 꾸미기 / 배경색

CSS / Tutorial / 표 꾸미기 / 배경색

배경색은 background-color 속성으로 만듭니다. table, tr, th, td, thead, tbody, tfoot에 적용할 수 있습니다. 다음 표를 기본으로 하고, 배경색을 여러 곳에 추가해보겠습니다.

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

요소·클래스·ID·속성 선택자를 같은 HTML에 적용해 대상과 결과를 비교합니다. 복합 클래스, 공백으로 구분한 속성값, 필수 입력칸을 포함한 전체 예제와 선택자 수정 실습을 제공합니다.

CSS / Tutorial / 변수 사용하는 방법

CSS / Tutorial / 변수 사용하는 방법

CSS 사용자 지정 속성을 :root와 특정 구성 요소에 선언하고 var()로 색과 간격을 재사용하는 방법을 설명합니다. 상속 범위, 값이 없을 때의 대체값, 유효하지 않은 값의 처리도 예제로 확인합니다.

CSS / Tutorial / position의 값이 fixed일 때 가운데 정렬하는 방법

CSS / Tutorial / position의 값이 fixed일 때 가운데 정렬하는 방법

position의 fixed를 이용하여 요소의 위치를 고정시킬 수 있습니다. 예를 들어 상단에 고정되는 메뉴바를 만들 때 사용합니다. 그런데, fixed를 하면 요소가 한쪽으로 치우칩니다. 만약 가운데에 위치시키고 싶다면 어떻게 할까요? transform 속성으로 해결할 수 있습니다.

CSS / Tutorial / 양쪽 배분(균등 분할) 정렬 방법

CSS / Tutorial / 양쪽 배분(균등 분할) 정렬 방법

문단 정렬을 양끝으로 꽉차게 하는 경우가 있습니다. 한글에서는 배분 정렬, 워드에서는 균등 분할이라고 합니다. 일반적인 문단에서는 거의 사용하지 않고, 표에서 제목을 넣을 때 많이 사용합니다.