동적 클래스 바인딩 (Dynamic Class Binding)
Vue.js에서는 v-bind:class (또는 단축형 :class)를 사용하여 HTML 요소의 클래스를 동적으로 조작할 수 있습니다. 이는 조건부 렌더링이나 상태에 따른 UI 변경을 선언적으로 처리하는 데 매우 유용합니다.
1. 객체 구문 (Object Syntax)
클래스 이름을 키로, 해당 클래스의 적용 여부를 결정하는 불리언 값을 값으로 갖는 객체를 전달합니다.
<template>
<!-- 인라인 객체 사용 -->
<button :class="{ 'btn-active': isClicked, 'btn-disabled': isDisabled }">
제출
</button>
<!-- 데이터 속성에 정의된 객체 사용 -->
<section :class="panelClasses">
대시보드 패널
</section>
</template>
<script>
export default {
data() {
return {
isClicked: true,
isDisabled: false,
panelClasses: {
'panel-dark': true,
'panel-shadow': false
}
};
}
};
</script>
2. 배열 구문 (Array Syntax)
여러 클래스를 동적으로 적용해야 할 때 배열을 사용하면 직관적입니다.
<template>
<div :class="[baseClass, themeClass]">
알림 메시지
</div>
</template>
<script>
export default {
data() {
return {
baseClass: 'notification',
themeClass: 'notification-warning'
};
}
};
</script>
배열 내에서 조건부 클래스를 적용하기 위해 삼항 연산자를 함께 사용할 수도 있습니다.
<div :class="[baseClass, isImportant ? 'highlight' : '']"></div>
3. 삼항 연산자 및 메서드 활용
복잡한 조건에 따라 클래스를 결정해야 할 경우, 삼항 연산자나 컴포넌트 메서드를 활용하면 템플릿을 깔끔하게 유지할 수 있습니다.
<template>
<!-- 삼항 연산자 -->
<span :class="userRole === 'admin' ? 'text-red font-bold' : 'text-gray'">
{{ userName }}
</span>
<!-- 메서드 호출 -->
<div :class="getStatusClass(serverStatus)">
서버 상태 표시등
</div>
</template>
<script>
export default {
data() {
return {
userRole: 'admin',
userName: 'Alice',
serverStatus: 'offline'
};
},
methods: {
getStatusClass(status) {
const statusMap = {
online: 'bg-green-500',
offline: 'bg-red-500',
maintenance: 'bg-yellow-500'
};
return statusMap[status] || 'bg-gray-500';
}
}
};
</script>
4. 정적 클래스와 동적 클래스의 공존
:class 디렉티브는 기존의 정적 class 속성을 덮어쓰지 않고 병합합니다.
<!-- 렌더링 결과: class="card card-elevated" -->
<div class="card" :class="{ 'card-elevated': isElevated }"></div>
동적 인라인 스타일 바인딩 (Dynamic Inline Style Binding)
v-bind:style (또는 :style)를 사용하면 CSS 인라인 스타일을 동적으로 바인딩할 수 있습니다. CSS 속성명은 카멜 케이스(camelCase) 또는 케밥 케이스(kebab-case, 따옴표 필수)로 작성할 수 있습니다.
1. 객체 구문 (Object Syntax)
JavaScript 객체와 매우 유사한 형태를 띠며, 동적 값과 단위를 결합하여 사용할 수 있습니다.
<template>
<div :style="{ backgroundColor: themeColor, fontSize: textSize + 'px' }">
스타일링된 텍스트
</div>
</template>
<script>
export default {
data() {
return {
themeColor: '#3498db',
textSize: 18
};
}
};
</script>
객체를 직접 템플릿에 작성하는 대신, 데이터 속성에 정의하여 재사용성을 높이는 것이 좋습니다.
<template>
<button :style="buttonStyles">저장</button>
</template>
<script>
export default {
data() {
return {
buttonStyles: {
backgroundColor: '#2ecc71',
color: '#ffffff',
padding: '10px 20px',
borderRadius: '4px'
}
};
}
};
</script>
2. 배열 구문 (Array Syntax)
배열 구문을 사용하면 여러 스타일 객체를 하나의 요소에 적용할 수 있습니다. 이는 기본 스타일과 조건부 스타일을 분리할 때 유용합니다.
<template>
<div :style="[baseStyles, customOverrides]">
멀티 스타일 적용 영역
</div>
</template>
<script>
export default {
data() {
return {
baseStyles: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
},
customOverrides: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
height: '200px'
}
};
}
};
</script>
실전 활용 예시
1. 반응형 이미지 너비 설정
데이터의 상태나 배열의 길이에 따라 이미지의 너비를 동적으로 조절해야 하는 경우, :style을 활용할 수 있습니다.
<template>
<img
:src="imageUrl"
:style="{ width: galleryItems.length > 1 ? '48%' : '100%' }"
alt="Gallery Image"
/>
</template>
<script>
export default {
data() {
return {
imageUrl: 'https://example.com/images/sample.jpg',
galleryItems: ['item1', 'item2']
};
}
};
</script>
2. 무작위 테마 클래스 적용
사용자 이벤트에 따라 미리 정의된 여러 테마 중 하나를 무작위로 적용하는 로직을 구현할 수 있습니다.
<template>
<div>
<div :class="currentTheme">테마 테스트 박스</div>
<button @click="randomizeTheme">테마 변경</button>
</div>
</template>
<script>
export default {
data() {
return {
currentTheme: 'theme-light'
};
},
methods: {
randomizeTheme() {
const themes = ['theme-light', 'theme-dark', 'theme-solarized', 'theme-nord'];
const randomIndex = Math.floor(Math.random() * themes.length);
this.currentTheme = themes[randomIndex];
}
}
};
</script>