HTML&CSS

CSS 가상 요소 "::before"와 "::after" 완벽 정리

apost 2021. 8. 18. 15:55

가상 요소와 가상 클래스

 

CSS 가상 요소는 선택자로 선택한 요소의 뒤에 붙여 표기하는 미리 약속된 키워드를 말합니다.

요소의 특정한 부분에 정해진 기능을 하도록 가상 요소 키워드 별로 미리 기능이 정의되어 있으며, 요소에 CSS 속성을 적용하는 것과 같은 방법으로 다양한 CSS 속성을 적용할 수 있기 때문에 마치 하나의 하위 요소처럼 사용할 수 있어서 가상 요소(Pseudo-Element)라고 합니다.

 

가상 요소 키워드 중에는 HTML 태그로 표현하기 어려운 콘텐츠의 특정 부분만 동적으로 선택하거나, HTML 콘텐츠 내용을 변경하지 않고도 선택한 요소의 앞 뒤에 새 콘텐츠를 추가하는 기능을 하는 키워드도 있습니다.

 

요소를 꾸미는 다양한 기능들을 제공하기 때문에 잘 사용하면 CSS만으로도 미려하고 고급스러운 레이아웃을 만들 수 있습니다.

 

가상 요소는 다음 6가지가 있습니다.

가상 요소 설명
::before 요소 내용 앞쪽에 새 컨텐츠를 추가.
::after 요소 내용 끝에 새 컨텐츠를 추가.
::selection 마우스 드래그로 선택한 텍스트 컨텐츠 영역을 선택.
::marker 목록 아이템 앞에 붙는 마커를 선택.
::first-letter 현재 웹 브라우저에 보이는 상태를 기준으로 요소의 텍스트 컨텐츠 첫 글자를 선택.
::first-line 현재 웹 브라우저에 보이는 상태를 기준으로 요소의 텍스트 컨텐츠 첫 줄 내용을 선택.

 

"::before", "::after" 2개만 새 컨텐츠를 추가하는 가상 요소이고, 나머지 4개는 콘텐츠의 특정 부분을 선택하는 가상 요소입니다.

 

"::before", "::after" 가상 요소는 HTML 태그나 자바스크립트 없이도 HTML 페이지 안에 콘텐츠, 또는 디자인 요소를 추가할 수 있는 특별한 기능을 합니다.

CSS로 HTML 컨텐츠를 변경할 수 있는 몇 안 되는 중요한 키워드입니다.

CSS를 작성할 때 가장 많이 사용하는 가상 요소가 "::before", "::after" 2개입니다.

그만큼 중요하기 때문에 이 2가지 가상 요소에 대해서 집중적으로 알아보도록 하겠습니다.

 


가상 요소 작성 방법

 

가상 요소는 키워드 앞에 콜론(:) 2개를 연달아 붙여 표기해서 가상 요소임을 표시합니다.

가상 클래스는 콜론(:) 1개로 표시합니다. CSS1, CSS2 때는 가상 요소 또한 콜론 1개로만 표시를 했었지만, CSS3에 오면서 가상 클래스와 가상 요소를 구분하기 위해서 가상 요소에 콜론 2개를 붙이게 되었습니다.

가상 클래스와 가상 요소는 새로운 가상의 요소를 생성하는지에 따라 구분합니다.

호환성을 위해서 대부분의 메이저 웹 브라우저들은 ":before", "::before" 표기 모두를 지원합니다.

두 가지 표기 방법 모두 사용 가능하지만 가상 요소는 "::before"로 표기하는 것이 CSS3 표준 표기 방법입니다.

기본 사용 구문 구조는 다음과 같습니다.

 

선택자::가상요소 {

    속성: 속성 값;

}

 

실제로 사용할 때는 다음처럼 사용합니다.

 

p::before {
    content: "■ ";
}
article.content::selection {
    color: #00ff00;
}

 

가상 요소는 선택된 요소에 의존적인 키워드입니다. 가상 요소를 적용하기 위해 CSS 선택자로 선택한 요소가 여러 개면 가상 요소로 적용하는 속성도 선택된 요소들에 모두 적용됩니다.

 


content 속성과 속성 값

 

content 속성은 ::before와 ::after 가상 요소에 사용할 수 있는 속성들 중 가장 중요한 역할을 하는 속성입니다. 그리고 가상 요소에만 사용할 수 있습니다.

::before와 ::after 가상 요소로 추가하는 콘텐츠의 내용에 해당하는 것을 표시하는 속성입니다.

content 속성 값에는 문자열, 이미지, HTML 속성, 변수, 함수 등 CSS로 표현할 수 있는 대부분의 콘텐츠를 사용할 수 있습니다.

 

문자열 내용을 표시할 때는 content: '내용'과 같이 따옴표로 문자열 내용을 감싸서 표시합니다. 문자열은 일반 문자열일 수도 있고, 코드 값일 수도 있습니다. 이모지도 사용할 수 있습니다.

 

p::before {
  content: ''; /* 빈 컨텐츠 표시 */
}
p::before {
  content: '문단 맨 앞에 텍스트 표시';
}
p::before {
  content: '👨🏽‍💻'; /* 이모지 */
}
p::before {
  content: '\0244'; /* 캐릭터 코드 */
}

 

 

이미지는 content: url(이미지 경로)와 같이 표시할 수 있습니다. <img> 태그로 표시하는 이미지의 표시 위치와 크기, 배치를 정하는 속성들을 똑같이 사용해서 가상 요소로 추가한 이미지를 제어할 수 있습니다.

 

p::before {
  content: url(https://unsplash.it/15/15);
  margin-right: 0.625rem;
}

 

content 속성에 표시하는 속성 값은 선택자로 선택한 요소의 속성 값을 가져올 수도 있습니다.

빈번하게 사용되고, 또 동적인 웹 페이지를 구성하는 중요한 사용 방식입니다.

content: attr(속성명)으로 콘텐츠로 사용할 내용을 정의하면 가상 요소가 부착되는 요소의 "속성명"인 속성에서 값을 가져와 콘텐츠로 표시합니다. 뒤에서 동적 데이터를 가져오는 방법을 배우면서 자세히 알게 됩니다.

 

p::before {
  content: attr(data-before-text);
  background-color: aqua;
  margin-right: 0.625rem;
  padding: 0.625rem;
}

 


가상 요소의 컨텐츠 표시 위치

 

::before와 ::after 가상 요소로 추가한 콘텐츠는 일반 HTML 태그 요소처럼 배치 속성을 사용해 자유롭게 배치할 수 있습니다. 그리고 가장 중요한 가상 요소의 생성 위치는 ::before 가상요소 -> 요소의 콘텐츠 -> ::after 가상요소 순서입니다.

웹 브라우저 개발자 도구를 이용해 가상 요소를 추가한 요소를 선택하면 다음과 같이 태그 안에 가상 요소가 추가되어 있는 것을 볼 수 있습니다.

 

 

이때 중요한 것은 선택된 요소의 태그 안에  가상 요소가 위치하는 것입니다.

가상 요소는 선택자로 선택한 요소의 하위 요소로 위치하며, 요소의 기본 속성들을 상속해서 받게 됩니다.

인라인 요소에 가상 요소를 추가하면 가상 요소는 상속되는 인라인 요소의 기본 속성들을 모두 상속하게 됩니다.

반대로 블록 요소에 가상 요소를 추가하면 가상 요소는 블록 요소의 속성을 상속받게 됩니다.

 

가상 요소는 실제 요소처럼 배치 속성을 부여해서 자유롭게 위치를 조절할 수 있습니다.

 


가상 요소에 동적 컨텐츠 표시하기

 

::before와 ::after 가상 요소 content 속성에는 HTML 태그의 속성 값을 가져오는 attr() 함수를 사용할 수 있습니다.

특히 데이터 속성("data-") 값을 가져올 수 있기 때문에 콘텐츠에 표시하는 동적인 내용들을 다루고 관리하기가 훨씬 쉬워집니다.

HTML과 CSS 코드의 관리와 유지보수 측면에서도 훨씬 효율적이므로 동적인 데이터를 웹에 표시할 때 체계적인 데이터 관리가 가능합니다.

 

다음과 같이 태그 데이터 속성으로 동적인 데이터를 표시한 후

 

<button class="coupon" data-username="어포스트"></button>

 

::before 가상 요소와 attr() 함수를 이용해 버튼에 표시할 텍스트를 다음과 같이 표시할 수 있습니다.

 

button.coupon::before {
    display: block;
    content: attr(data-username) " 님을 위한 쿠폰";
    padding: 10px 20px;
    color: #ff8822;
}

 

버튼은 다음과 같이 표현이 됩니다. 단순한 버튼 텍스트 표현이지만, 버튼의 기능은 그대로 사용하면서 동적으로 버튼의 표시 내용을 변경할 수 있습니다.

 

 

표시할 컨텐츠 내용을 수정하기 위해 HTML을 수정할 필요가 없고, 동적인 데이터 부분만 태그 속성으로 따로 관리하기 때문에 데이터의 관리도 편해집니다.

 

attr() 함수는 하나의 컨텐츠 속성에 여러 번 사용할 수 있습니다.

다음처럼 2개의 데이터 속성 값을 이용해서 날짜 범위에 대한 안내 문구를 표현하면

 

<p class="eventnotice" data-startday="2021-08-16" data-endday="2021-09-05"></p>

 

가상 요소를 이용해 다음과 같이 콘텐츠를 완성할 수 있습니다. 컨텐츠 속성을 제외한 나머지 속성은 장식을 위한 것입니다.

 

p.eventnotice::before {
    content: "이벤트 기간은 " attr(data-startday) "일부터 " attr(data-endday) "까지입니다.";
    padding: 0.5em 2em;
    border-radius: 1em;
    background-color: #f0f0f0;
    border: 1px solid #a22;
}

 

 


가상 요소로 디자인 장식하기

::before와 ::after 가상 요소를 이용하면 디자인적인 요소를 표현하기 위해 추가 태그를 사용하지 않아도 콘텐츠에 디자인 장식을 추가할 수 있습니다.

 

다음의 타이틀 태그에 가상 요소를 이용해서 다양한 디자인 장식을 추가해보겠습니다.

 

<h1>CSS 가상 요소 "::before"와 "::after" 완벽 정리</h1>

 

다음처럼 타이틀 위아래에 라인을 그려서 헤드라인 장식 효과를 만들 수 있습니다.

블록(display: block)으로 가상 요소의 표시 타입을 변경하는 것이 중요합니다. 블록 타입으로 가상 요소의 타입이 변경되면 콘텐츠 영역 너비를 모두 차지하면서 타이틀 콘텐츠 위와 아래에 가상 요소가 배치되는 특징을 이용한 것입니다.

 

h1{
    text-align: center;
}
h1::before, h1::after {
    content: '';
    background-color: #00a;
    display: block;
    height: 0.1em;
}

 

 

 

앞서 만든 장식 효과를 조금 변형해서 트릭을 쓰면 다음 같은 타이틀 영역 강조 효과를 만들 수도 있습니다.

콘텐츠 속성 값으로 마침표를 사용한 것에 주의해야 합니다. 콘텐츠 속성 값이 비어 있으면 너비를 차지하지 않기 때문에 배경색으로 만드는 영역이 보이지 않기 때문에 작은 글자로 영역을 차지하도록 일종의 꼼수를 활용한 것입니다.

마진 속성은 세로 바와 타이틀 콘텐츠의 사이를 띄우기 위한 여백입니다.

 

h1::before, h1::after {
    content: '.';
    color: #000;
    background-color: #000;
    margin: 0 0.25em;
}

 

 

인라인 요소로 표현된 가상 요소를 인라인 블록(display: inline-block) 타입으로 변경하면 가상요소의 너비를 자유롭게 조절할 수도 있습니다.

 

h1::before, h1::after {
    content: '.';
    color: #000;
    background-color: #000;
    margin: 0 0.25em;
    display: inline-block;
    width: 3em;
}

 

 

 

앞서 예에서 블록 속성(display: block)을 사용할 수 있는 것을 알았습니다. 블록 속성을 사용할 수 있다는 것은 위치 속성을 절대 위치(position: absolute)로 해서 가상요소의 표시 위치를 자유롭게 제어할 수 있다는 뜻이 됩니다.

다음처럼 절대 위치로 가상 요소를 배치하면 다양한 도형을 만들 수도 있습니다.

 

h1 {
    position: relative; /* 자식 요소인 가상 요소가 절대 위치를 가지도록 */
    display: inline-block;
    background-color: #fff; /* 배경색을 지정해서 타이틀 바깥으로 일부 벗어난 가상 요소만 보이도록 */
    padding: 0 0.5em; /* 타이틀 컨텐츠와 가상 요소가 달라붙지 않게 */
    margin-left: 1em;
}
h1::before, h1::after {
    content: ''; /* 배경색으로 테두리션을 표현하므로 컨텐츠는 필요 없음 */
    background-color: #a00;
    width: 0.25em;
    height: 0.25em;
    padding: 0.25em; /* 선 길이 조절 */
    display: block;
    position: absolute;
    z-index: -1; /* 타이틀 컨텐츠 뒤로 가상요소를 배치 */
}

/* 가상 요소 일부가 보이도록 위치 조정 */
h1::before {
    left: -0.25em;
    top: -0.25em;
}
h1::after{
    right: -0.25em;
    bottom: -0.25em;
}

 

 

 

커스텀 아이콘이나 이모지를 사용하면 그래픽 요소들을 추가할 수도 있습니다.

앞서 사용한 타이틀 태그에 구글 메터리얼 아이콘을 가상 요소를 이용해 추가하면 다음처럼 강조 효과를 추가할 수 있습니다.

 

@import url('https://fonts.googleapis.com/icon?family=Material+Icons');

h1:before, h1:after{
    content: '\e244';
    font-family: 'Material Icons';
    font-size: 2em;
}

 

구글 메터리얼 아이콘으로 쌍따옴표 효과를 표현

 


가상 요소로 순서 있는 목록 만들기

 

순서 있는 목록 태그(<ul>)을 사용하면 순서대로 번호가 있는 목록을 만들 수 있습니다.

숫자, 영문자, 로마자 숫자를 순서대로 표시를 할 수 있지만, 표시하는 숫자 표현에 제약이 많이 따릅니다.

가상 요소를 이용하면 다양한 형태로 만든 순서 있는 목록의 숫자 표현을 구현할 수 있습니다.

 

가상 요소에 숫자 표현을 구현할 때는 counter() 함수를 사용합니다.

 

카운터 함수(counter())의 기본 사용법은 다음 글을 읽어보면 됩니다.

 

> CSS 카운터 함수(counter())로 목차형 순번 붙이기

 

카운터 함수를 이용해 홀수로 번호가 붙는 테두리를 장식한 숫자 목록을 구현해보겠습니다.

HTML 태그로 목록 하나를 만듭니다. 순서 있는 목록이어도 되고 순서 없는 목록이어도 됩니다. 기존의 마커(불릿이나 숫자번호)를 안 보이게 하고 ::before 가상 요소로 새로운 번호를 만들어 붙입니다.

 

<ul class="ulist">
    <li><a href="#" class="item"><div>프로필</div></a></li>
    <li><a href="#" class="item"><div>데이터사용량</div></a></li>
    <li><a href="#" class="item"><div>내URL</div></a></li>
    <li><a href="#" class="item"><div>구매내역</div></a></li>
    <li><a href="#" class="item"><div>추천목록</div></a></li>
    <li><a href="#" class="item"><div>설정</div></a></li>
</ul>

 

ul.ulist {
    list-style: none;
    counter-reset: list_counter -1; /* 카운터 -1로 초기화 */
}

li {
    margin-bottom: 2em;
    margin-left: 2em;
    position: relative;
}

li::before {
    content: counter(list_counter); /* 가상요소 표시 컨텐츠를 카운터 숫자로 */
    counter-increment: list_counter 2; /* 2씩 늘어남*/
    position: absolute; /* 절대 위치로 가상 요소 위치 설정 */
    left: -3em;
    top: -0.5em;
    border-radius: 50%;
    font-size: 1em;
    font-weight: bold;
    width: 2em;
    height: 2em;
    display: flex; /* 가상 요소 가운데 정렬 */
    justify-content: center;
    align-items: center;
    border: 3px solid #b080cf;
    background-color: #9060af;
}

 

가상요소로 만든 홀수 숫자 목록