외부에서 가져온 SVG 아이콘이나 컴포넌트 기반의 아이콘 라이브러리를 사용할 때, 프로젝트에서 미리 정의한 CSS 변수를 적용하는 것이 쉽지 않을 때가 있다. 예를 들어, className=”bg-primary”처럼 배경색을 적용하는 것은 가능하지만, fill이나 stroke 같은 SVG 속성에는 동일한 방식이 적용되지 않는다. 그리고 테마가 존재할 수 있다. 이 경우에 어떻게 변화를 감지하고, 어떻게 가져올 것인지 정리한다.
예시 CSS 코드
:root {
--bg: #123456;
}
.dark {
--bg: #030e18;
}
.light {
--bg: #dbdbdb;
}
CSS 변수 값 가져오기
const rootStyle = getComputedStyle(document.documentElement);
const bg = rootStyle.getPropertyValue("--bg");
CSS 변수 변화 감지하고 다시 변수 값 가져오기
사실 하나의 컴포넌트에서만 사용할 것이면, 전역적으로 관리할 필요가 없고 이부분은 필요 없을 수 있다. 나에 경우에는 전역적으로 관리할 필요가 있었고, 특정 엘리먼트의 class값을 변화를 감지해서 state를 업데이트 해주는 로직을 작성했다.
import { create } from "zustand";
interface UseCSSStore {
brand: string;
foreground: string;
secondary: string;
border: string;
trendUp: string;
trendNeutral: string;
trendDown: string;
updateColors: (colors: Partial<typeof initialState>) => void;
}
const initialState = {
brand: "",
foreground: "",
secondary: "",
border: "",
trendUp: "",
trendNeutral: "",
trendDown: "",
};
const useCSSProperty = create<UseCSSStore>(set => {
return {
...initialState,
updateColors: colors => {
// 빈 문자열 또는 nullish 값을 제거한 새로운 객체 생성
const filteredColors = Object.fromEntries(
Object.entries(colors).filter(([_, value]) => value),
);
// 필터링된 객체만 상태에 적용
set(filteredColors);
},
};
});
export function updateColors() {
const rootStyle = getComputedStyle(document.documentElement);
const { updateColors } = useCSSProperty.getState();
updateColors({
brand: rootStyle.getPropertyValue("--brand").trim(),
foreground: rootStyle.getPropertyValue("--foreground").trim(),
secondary: rootStyle.getPropertyValue("--secondary").trim(),
border: rootStyle.getPropertyValue("--border").trim(),
trendUp: rootStyle.getPropertyValue("--trend-up").trim(),
trendNeutral: rootStyle.getPropertyValue("--trend-neutral").trim(),
trendDown: rootStyle.getPropertyValue("--trend-down").trim(),
});
}
export function useUpdateCSSPropertyStore() {
useEffect(() => {
const root = document.documentElement;
const observer = new MutationObserver(updateColors);
observer.observe(root, { attributes: true, attributeFilter: ["class"] });
// 처음 한번 실행
updateColors();
}, []);
}
export default useCSSProperty;
useCSSProperty Zustand Store 정의
- brand, foreground, secondary 등 CSS 변수 값을 저장하는 상태를 관리한다.
- updateColors(colors) 함수로 CSS 변수 값을 업데이트할 수 있다.
- 빈 문자열 또는 nullish(null 또는 undefined) 값을 제거하여 유효한 값만 저장한다.
updateColors() 함수
- getComputedStyle(document.documentElement)을 사용해 현재 CSS 변수 값을 가져온다.
- useCSSProperty.getState().updateColors({…})를 호출하여 Zustand Store를 업데이트한다.
useUpdateCSSPropertyStore() 커스텀 훅
- MutationObserver를 사용하여 요소의 class 속성 변화를 감지한다.
- 클래스가 변경되면 updateColors()를 실행하여 상태를 최신 CSS 변수 값으로 갱신한다.
- useEffect 내에서 초기 실행 시 updateColors()를 한 번 호출하여 현재 상태를 설정한다.