Vue scoped 스타일에서 자식 컴포넌트 색상이 안 먹히는 이유
클래스는 분명히 붙어 있는데, 왜 CSS가 안 먹히지?
🎯 이런 상황이었어요
그리드 행(row)마다 상태값에 따라 배경색을 다르게 주고 싶었어요.
예를 들면 이런 식으로요.
- 새로 추가된 행 → 초록색 배경
- 수정된 행 → 노란색 배경
- 삭제된 행 → 빨간색 배경 + 취소선
구조는 간단했어요.
부모 컴포넌트에서 상태에 따라 rowClass를 정해서, 자식 컴포넌트로 props로 전달하는 방식이었죠.
📦 현재 구조
부모 컴포넌트 — 상태값에 따라 클래스 이름을 세팅해요.
if (row.status === 'I') row.rowClass = 'row-inserted'
else if (row.status === 'U') row.rowClass = 'row-updated'
else if (row.status === 'D') row.rowClass = 'row-deleted'
else row.rowClass = ''
그리고 이 데이터를 자식 컴포넌트로 넘겨줘요.
<DataTableComponent :data="displayList" />
자식 컴포넌트 — 받은 rowClass를 <tr>에 바인딩해요.
<tr :class="[b.rowClass, { 'selected-row': selectedRow === bi || b.isSelected }]">
부모 컴포넌트 스타일 — 이렇게 색상을 정의했어요.
.row-inserted {
background-color: #e8f5e9;
}
❓ 그런데 왜 색이 안 입혀질까요?
브라우저 개발자 도구를 열어보면 <tr class="row-inserted">는 분명히 잘 붙어 있어요.
그런데 배경색이 없어요. 왜 그럴까요?
원인은 <style scoped> 에 있어요.
scoped가 뭔가요?
Vue에서 <style scoped>를 쓰면, 그 스타일은 현재 컴포넌트가 직접 그린 DOM에만 적용돼요.
Vue는 내부적으로 이걸 구현하기 위해, 컴포넌트마다 고유한 속성을 DOM에 붙여요.
예를 들면 이런 식이에요.
<!-- 부모 컴포넌트가 렌더링한 DOM -->
<div data-v-a1b2c3>...</div>
그리고 CSS도 이렇게 변환돼요.
/* 내가 쓴 코드 */
.row-inserted { ... }
/* Vue가 실제로 적용하는 코드 */
.row-inserted[data-v-a1b2c3] { ... }
즉, data-v-a1b2c3이 붙은 DOM에만 스타일이 적용되는 거예요.
문제가 뭔가요?
<tr class="row-inserted">는 자식 컴포넌트(DataTableComponent) 내부에서 렌더링돼요.
자식 컴포넌트가 만든 DOM에는 부모의 data-v-a1b2c3이 붙지 않아요.
그래서 아무리 클래스가 잘 붙어 있어도, 부모의 scoped CSS가 닿지 않는 거예요.
정리하면
| 항목 | 상태 |
|---|---|
| props 전달 | ✅ 정상 |
| class 바인딩 | ✅ 정상 |
| CSS 적용 범위 | ❌ 자식 내부까지 도달 못 함 |
클래스는 붙어 있었지만, 그 클래스를 꾸미는 CSS가 자식 컴포넌트 내부까지 닿지 못한 게 문제였어요.
✅ 해결 방법 — :deep() 사용하기
이럴 때는 :deep()을 사용하면 돼요.
#acbas3001MainGrd :deep(.row-inserted) {
background-color: #e8f5e9 !important;
}
#acbas3001MainGrd :deep(.row-updated) {
background-color: #fff9c4 !important;
}
#acbas3001MainGrd :deep(.row-deleted) {
background-color: #ffebee !important;
text-decoration: line-through;
}
:deep()은 scoped 스타일 안에서 특정 선택자만 자식 컴포넌트 내부까지 적용되도록 열어주는 역할을 해요.
⚠️
:deep()앞에 부모 선택자(#acbas3001MainGrd)를 붙이는 게 좋아요.
그냥:deep(.row-inserted)만 쓰면 페이지 전체에 영향을 줄 수 있거든요.
💡 한 줄 요약
props로 class를 넘겨도, 부모가
scoped스타일을 쓰고 있으면 자식 컴포넌트가 만든 DOM에는 CSS가 닿지 않아요.
이때는:deep()으로 자식 내부까지 스타일 적용 범위를 열어줘야 해요.