CSS modules

CSS modules

Mantine의 모든 컴포넌트는 스타일링에 CSS modules를 사용해요. 프로젝트에서도 CSS modules를 사용하는 것이 권장되지만 필수는 아니에요 – Mantine 컴포넌트는 어떤 서드파티 스타일링 솔루션이나 네이티브 CSS와도 완전히 호환돼요.

출처: 문서

본문

사용법

CSS modules는 모든 주요 프레임워크와 빌드 도구에서 바로 사용할 수 있어요. 보통 *.module.css 파일을 만들기만 하면 돼요:

/* Button.module.css */
.button {
  color: red;
}

그리고 컴포넌트에서 import 하면 돼요:

import classes from './Button.module.css';

function Demo() {
  return <button className={classes.button}>Button</button>;
}

CSS modules가 동작하는 방식

*.module.css 파일을 만들면 빌드 도구가 파일 안의 각 클래스에 대해 고유한 클래스 이름을 생성해요. 예를 들어 .js/.ts 파일에서 다음 파일을 import 하면:

/* Button.module.css */
.button {
  color: red;
}

.text {
  color: blue;
}

고유한 클래스 이름을 가진 객체를 얻게 돼요:

import classes from './Button.module.css';

console.log(classes);
// -> 스코프된 클래스 이름 객체: key는 클래스 이름, value는 생성된 고유 클래스 이름
// { button: 'button-Xh3s7ER', text: 'text-js65s3Se' }
// 생성된 클래스 이름은 빌드 도구에 따라 다를 수 있다는 점에 주의하세요

CSS modules를 사용하면 클래스 이름 충돌에 대해 걱정할 필요가 없어요. 원하는 어떤 클래스 이름이든 사용할 수 있어요.

전역 클래스 이름 참조

CSS Modules에서 전역 클래스 이름을 참조하려면 :global 선택자를 사용할 수 있어요:

.test {
  & :global(.global-class-name) {
    color: red;
  }
}

위 코드는 다음 CSS로 컴파일돼요:

.m-dj3w33 .global-class-name {
  color: red;
}

Mantine 컴포넌트에 스타일 추가

대부분의 Mantine 컴포넌트에는 일반 HTML 요소에 하듯이 className prop을 사용해 스타일을 추가할 수 있어요. theme 값에 속성을 설정하려면 Mantine CSS variables를 사용할 수 있어요:

import { Box } from '@mantine/core';
import classes from './Demo.module.css';

function Demo() {
  return <Box className={classes.box}>Box component with some styles</Box>;
}

CSS modules로 Mantine 컴포넌트의 내부 요소에 스타일을 적용하려면 classNames prop을 사용할 수 있어요(자세한 내용은 Styles API 참고):

import { useState } from 'react';
import { TextInput } from '@mantine/core';
import classes from './Demo.module.css';

function Demo() {
  const [value, setValue] = useState('');
  const [focused, setFocused] = useState(false);
  const floating = focused || value.length > 0 || undefined;

  return (
    <TextInput
      label="Floating label input"
      classNames={{ label: classes.label, input: classes.input }}
      onFocus={() => setFocused(true)}
      onBlur={() => setFocused(false)}
      value={value}
      onChange={(event) => setValue(event.currentTarget.value)}
    />
  );
}

CSS modules 없이 Mantine 컴포넌트 스타일링

모든 Mantine 컴포넌트는 어떤 서드파티 스타일링 솔루션이나 네이티브 CSS와도 완전히 호환돼요. 서드파티 라이브러리로 스타일을 적용하는 두 가지 주요 전략이 있어요:

  • className, classNames, style, styles props

  • 정적 선택자(static selectors), 예를 들어 .mantine-Text-root

유틸리티 CSS 라이브러리로 스타일을 적용하는 예시:

import { TextInput } from '@mantine/core';

function Demo() {
  return <TextInput className="text-red" />;
}

전역 CSS로 스타일을 적용하는 예시:

/* styles.css */

/* 이 스타일은 스코프되지 않고
   모든 TextInput 컴포넌트에 적용된다는 점에 주의하세요 */
.mantine-TextInput-root {
  margin-top: 0.8rem;
}

.mantine-TextInput-input {
  background-color: var(--mantine-color-red-filled);
  color: var(--mantine-color-white);
}

두 접근 방식을 결합해 원하는 결과를 얻을 수 있어요. 예를 들어 @emotion/styled와 styled-components 패키지는 주어진 컴포넌트에 className prop을 전달하고, 정적 선택자로 내부 요소에 스타일을 적용할 수 있어요:

import styled from '@emotion/styled';
import { Slider } from '@mantine/core';

const StyledSlider = styled(Slider)`
  & .mantine-Slider-bar {
    background-color: var(--mantine-color-pink-5);
  }

  & .mantine-Slider-thumb {
    border-color: var(--mantine-color-pink-5);
    background-color: white;
    width: 1.5rem;
    height: 1.5rem;
  }
`;

function Demo() {
  return <StyledSlider />;
}

CSS modules를 먼저 고려하세요

CSS modules는 Mantine 컴포넌트를 스타일링하는 권장 방식이에요. 다른 스타일링 솔루션을 선택하기 전에 CSS modules가 요구사항에 맞지 않는지 확인해 보세요. 다른 솔루션에는 제한이 있어요. 예를 들어:

  • 유틸리티 기반 CSS 라이브러리를 사용할 때 data-* 속성에 기반한 스타일 커스터마이즈가 어려워요

  • styled-components나 그와 유사한 라이브러리에서 컴포넌트가 Portal을 사용하면 일부 요소가 컴포넌트 루트 바깥에 렌더링되고 내부 요소가 컴포넌트 트리의 일부가 아니므로 정적 선택자로 Mantine 컴포넌트의 내부 요소에 스타일을 적용하는 것이 불가능해요

더 알아보기 (Learn more)