[CSS-08] Pseudo-element & Shadow DOM

Comely·2025년 6월 6일

CSS

목록 보기
8/12

🎯 Pseudo-element란?

Pseudo-element는 HTML 요소의 특정 부분만 선택해서 스타일을 줄 수 있는 CSS 선택자입니다. 콜론 2개(::)를 사용합니다.

📝 기본 Pseudo-element 종류

텍스트 관련

/* 첫 번째 글자만 스타일링 */
.text::first-letter {
  color: red;
  font-size: 2em;
  font-weight: bold;
}

/* 첫 번째 줄만 스타일링 */
.text::first-line {
  color: blue;
  text-transform: uppercase;
}

컨텐츠 추가

/* 요소 앞에 컨텐츠 추가 */
.text::before {
  content: '📌 ';
  color: red;
  font-weight: bold;
}

/* 요소 뒤에 컨텐츠 추가 */
.text::after {
  content: ' ✨';
  color: gold;
}

실전 활용 예제

/* 인용문 디자인 */
.quote::before {
  content: '"';
  font-size: 3em;
  color: #ccc;
  vertical-align: top;
}

.quote::after {
  content: '"';
  font-size: 3em;
  color: #ccc;
}

/* 리스트 커스텀 마커 */
.custom-list li::before {
  content: '→ ';
  color: #007bff;
  font-weight: bold;
}

🛠️ Pseudo-element 실무 활용

Clear:both 박스 만들기

/* float 해제용 가상 요소 */
.clearfix::after {
  content: '';
  display: block;
  clear: both;
}

툴팁 만들기

.tooltip {
  position: relative;
  cursor: help;
}

.tooltip::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  background: #333;
  color: white;
  padding: 5px 10px;
  border-radius: 4px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s;
}

.tooltip:hover::after {
  opacity: 1;
}
<span class="tooltip" data-tooltip="도움말 텍스트">도움말</span>

버튼 호버 효과

.btn-hover {
  position: relative;
  overflow: hidden;
}

.btn-hover::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
  transition: left 0.5s;
}

.btn-hover:hover::before {
  left: 100%;
}

👻 Shadow DOM이란?

Shadow DOM은 브라우저가 복잡한 HTML 구조를 숨겨서 단순하게 보여주는 기술입니다. <input>, <progress>, <video> 등의 태그 내부에 숨겨진 HTML 요소들이 있습니다.

Shadow DOM 확인 방법

  1. 크롬 개발자도구 열기 (F12)
  2. Settings 열기 (F1 또는 ⚙️ 아이콘)
  3. "Show user agent shadow DOM" 체크
  4. 요소 검사로 내부 구조 확인

🔍 Shadow DOM 스타일링

Input Placeholder 스타일링

/* 크롬, 사파리, Edge */
input::-webkit-input-placeholder {
  color: #ff6b6b;
  font-style: italic;
  opacity: 0.8;
}

/* 파이어폭스 */
input::-moz-placeholder {
  color: #ff6b6b;
  font-style: italic;
  opacity: 0.8;
}

/* IE/Edge (구버전) */
input:-ms-input-placeholder {
  color: #ff6b6b;
  font-style: italic;
}

파일 업로드 버튼 스타일링

/* 파일 업로드 버튼 숨기기 */
input[type="file"] {
  width: 0.1px;
  height: 0.1px;
  opacity: 0;
  overflow: hidden;
  position: absolute;
  z-index: -1;
}

/* 커스텀 파일 업로드 버튼 */
input[type="file"] + label {
  display: inline-block;
  background: #007bff;
  color: white;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.3s;
}

input[type="file"] + label:hover {
  background: #0056b3;
}

스크롤바 스타일링

/* 웹킷 기반 브라우저 (크롬, 사파리) */
::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: #007bff;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: #0056b3;
}

선택 영역(Selection) 스타일링

::selection {
  background: #007bff;
  color: white;
}

::-moz-selection {
  background: #007bff;
  color: white;
}

📊 Progress 태그 스타일링

기본 Progress 태그

<progress value="0.7" max="1">70%</progress>

크로스 브라우저 Progress 스타일

progress {
  /* 기본 스타일 제거 */
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  
  width: 100%;
  height: 20px;
  border: none;
  border-radius: 10px;
  background: #e9ecef;
  
  /* IE10 호환성 */
  color: #007bff;
}

/* 웹킷 기반 브라우저 (크롬, 사파리, Edge) */
progress::-webkit-progress-bar {
  background: #e9ecef;
  border-radius: 10px;
  overflow: hidden;
}

progress::-webkit-progress-value {
  background: linear-gradient(45deg, #007bff, #0056b3);
  border-radius: 10px;
  transition: width 0.3s ease;
}

/* 파이어폭스 */
progress::-moz-progress-bar {
  background: linear-gradient(45deg, #007bff, #0056b3);
  border-radius: 10px;
}

애니메이션 Progress 바

progress {
  position: relative;
  overflow: hidden;
}

progress::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.3),
    transparent
  );
  animation: shine 2s infinite;
}

@keyframes shine {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

🌐 브라우저 접두사

벤더 프리픽스 종류

브라우저접두사예시
크롬, 사파리, Edge-webkit--webkit-transform
파이어폭스-moz--moz-transform
IE-ms--ms-transform

실전 크로스 브라우저 코드

.element {
  /* 표준 속성을 마지막에 */
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
  
  -webkit-transition: all 0.3s ease;
  -moz-transition: all 0.3s ease;
  -ms-transition: all 0.3s ease;
  transition: all 0.3s ease;
}

🎨 고급 활용 예제

카드 호버 효과

.card {
  position: relative;
  overflow: hidden;
  transition: transform 0.3s ease;
}

.card::before {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: linear-gradient(
    45deg,
    transparent,
    rgba(255, 255, 255, 0.1),
    transparent
  );
  transform: rotate(45deg);
  transition: all 0.6s;
  opacity: 0;
}

.card:hover::before {
  animation: shine 0.6s ease-in-out;
}

.card:hover {
  transform: translateY(-5px);
}

@keyframes shine {
  0% {
    top: -50%;
    left: -50%;
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    top: 50%;
    left: 50%;
    opacity: 0;
  }
}

리본 효과

.ribbon {
  position: relative;
  background: #007bff;
  color: white;
  padding: 10px 20px;
  margin: 20px 0;
}

.ribbon::before,
.ribbon::after {
  content: '';
  position: absolute;
  top: 0;
  width: 0;
  height: 0;
  border-style: solid;
}

.ribbon::before {
  left: -20px;
  border-width: 20px 20px 20px 0;
  border-color: transparent #005cbf transparent transparent;
}

.ribbon::after {
  right: -20px;
  border-width: 20px 0 20px 20px;
  border-color: transparent transparent transparent #005cbf;
}

💡 개발 팁

디버깅 방법

/* 가상 요소 디버깅용 */
.debug::before,
.debug::after {
  border: 1px solid red;
  background: rgba(255, 0, 0, 0.1);
}

주의사항

  1. content 속성 필수: ::before, ::aftercontent 속성이 반드시 필요
  2. 인라인 요소 제한: display: inline 요소에는 ::before, ::after 적용 불가
  3. 이미지 태그 제한: <img>, <input> 등 대체 요소에는 적용 불가

성능 고려사항

/* 좋은 예: transform 사용 */
.element::before {
  transform: translateX(100px);
}

/* 나쁜 예: left 사용 */
.element::before {
  left: 100px;
}

Pseudo-element와 Shadow DOM을 마스터하여 더욱 정교한 CSS 스타일링을 구현할 수 있습니다

profile
App, Web Developer

0개의 댓글