Intro

Tailwind로 스타일링을 해오던 중, CSS-in-JS로 구현하면 어떤 차이가 있을지 궁금해졌습니다. 그러던 중 관련 아티클을 접하게 되었고, 읽으면서 새롭게 알게 된 개념과 인사이트를 정리해 보았습니다. 이번 글에서는 단순한 코드 변환을 넘어, 두 방식이 코드를 구조화하는 방식과 개발 흐름에 주는 영향을 함께 살펴보겠습니다.

1. CSS 변수 기본 개념

CSS 변수는 특정 요소와 그 하위 요소에서만 유효한 스코프를 가집니다. 변수는 --로 시작하며, CSS 속성 값 어디서든 사용할 수 있습니다.
<style>
  p {
    --highlight-color: yellow; /* p와 그 자식 요소에서만 적용 */
  }
  em {
    background: var(--highlight-color);
  }
</style>

<p>This <em>emphasized</em> text works!</p>
<h1>This <em>won't work</em></h1>
전역에서 사용하려면 html이나 :root에 선언하여 모든 요소에서 접근 가능하게 합니다.
:root {
  --color-red: hsl(0deg, 80%, 50%);
}

2. React에서의 활용

React에서는 CSS 변수를 직접 사용할 수도 있고, ThemeProvider를 통해 스타일 토큰을 관리할 수도 있습니다.

ThemeProvider 방식

컴포넌트에 타입 지원과 구조화를 제공하지만, 값 변경을 위해선 React 렌더링이 필요합니다.
<ThemeProvider theme={{ colors: { primary: 'rebeccapurple' }}}>
  <Button>Click</Button>
</ThemeProvider>

const Button = styled.button`
  background: ${(props) => props.theme.colors.primary};
`;

CSS 변수 방식

전역 스타일에서 변수로 정의하면, CSS 내 어디서든 var(--변수명)으로 접근할 수 있습니다. 값 변경 시 전체 UI에 즉시 반영됩니다.
const GlobalStyles = createGlobalStyle`
  html {
    --color-primary: rebeccapurple;
  }
`;

const Button = styled.button`
  background: var(--color-primary);
`;
CSS 변수는 JS로 읽고 변경도 가능합니다.
// 읽기
getComputedStyle(document.documentElement)
  .getPropertyValue('--color-primary');

// 변경
document.documentElement.style.setProperty(
  '--color-primary', 'hsl(245deg, 100%, 60%)'
);

3. 반응형 설계 – 입력 방식 기준

전통적인 max-width 기반 미디어 쿼리 대신, 입력 방식에 따라 스타일을 변경하면 UX 정확도가 높아집니다.
html { --min-tap-target-height: 32px; }
@media (pointer: coarse) {
  html { --min-tap-target-height: 48px; }
}

button, input { min-height: var(--min-tap-target-height); }
  • pointer: coarse → 손가락 위주의 터치 입력
  • pointer: fine → 마우스나 펜과 같이 정밀한 입력

4. 다크모드 적용

다크모드는 CSS 변수 값만 바꿔 전체 UI 색상을 변경할 수 있습니다.
html {
  --color-text: black;
  --color-background: white;
}
@media (prefers-color-scheme: dark) {
  html {
    --color-text: white;
    --color-background: black;
  }
}
  • prefers-color-scheme 미디어 쿼리를 사용하면, 사용자 시스템 설정에 맞춰 자동 적용됩니다.

5. 읽고 나서 배운 점

  1. CSS 변수 스코프의 중요성:
    1. 선언된 위치와 계층 구조에 따라 변수의 적용 범위가 결정된다는 것을 알았습니다.
  2. 입력 방식 기반 반응형 설계:
    1. 화면 크기가 아닌 입력 장치 특성에 맞춘 디자인이 더 정확한 UX를 제공할 수 있다는 사실을 알았습니다.
  3. ThemeProvider와 CSS 변수 비교:
    1. ThemeProvider는 타입·구조 관리에 강점, CSS 변수는 선언과 변경이 간결하며 전역 적용이 쉽습니다.

6. 적용 아이디어

  • 입력 방식 기반 반응형을 설계해보기
    • 언제 어느 방식이 좋을지 좋은 UX를 고민해봐야겠습니다.
  • JS 이벤트 기반 실시간 테마 변경해보기

7. 참고 링크

  • https://velog.io/@cookie004/css-variables-for-react-devs
  • https://css-for-js.dev/