Preflight

Preflight

Preflight은 Tailwind 프로젝트를 위한 기본 스타일(baset styles) 세트예요. modern-normalize 위에 만들어져서, 브라우저 간 불일치를 완화하고 디자인 시스템의 제약 안에서 작업하기 쉽게 도와줘요.

출처: 문서

본문

개요 (Overview)

tailwindcss를 프로젝트에 임포트하면 Preflight이 자동으로 base 레이어에 주입돼요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);

대부분의 Preflight 스타일은 눈에 띄지 않도록 설계되어 있어요. 단순히 요소들이 기대하는 대로 동작하게 만들 뿐이죠. 하지만 일부는 조금 더 자신의 의견(opinionated)을 담고 있어서, 처음 만나면 의외로 느껴질 수 있어요.

Preflight이 적용하는 모든 스타일의 전체 레퍼런스는 stylesheet 문서를 참고하세요.

여백(margin)이 제거됩니다

Preflight은 제목(heading), 인용구(blockquote), 문단(paragraph) 등 모든 요소에서 기본 여백을 제거해요:

*, ::after, ::before, ::backdrop, ::file-selector-button {
  margin: 0;
  padding: 0;
}

이렇게 하면 사용자 에이전트 스타일시트가 적용한 것 중 우리의 spacing scale에 없는 여백 값을 실수로 의존하게 되는 일을 막아줘요.

테두리(border) 스타일이 초기화됩니다

border 클래스를 그냥 추가하는 것만으로도 테두리를 쉽게 추가할 수 있도록, Tailwind는 모든 요소의 기본 테두리 스타일을 아래 규칙으로 재정의해요:

*, ::after, ::before, ::backdrop, ::file-selector-button {
  box-sizing: border-box;
  border: 0 solid;
}

border 클래스는 border-width 속성만 설정하기 때문에, 이 초기화 덕분에 그 클래스를 추가하면 항상 currentColor를 사용하는 실선 1px 테두리가 생겨요.

이 때문에 Google Maps 같은 일부 서드파티 라이브러리를 통합할 때 예상치 못한 결과가 생길 수도 있어요.

이런 상황에 마주하면, Preflight 스타일을 우리만의 커스텀 CSS로 재정의해서 우회할 수 있어요:

@layer base {
  .google-map * {
    border-style: none;
  }
}

제목(heading)은 스타일이 지정되지 않습니다

모든 제목 요소는 기본적으로 완전히 스타일이 지정되지 않은(unstyled) 상태이며, 일반 텍스트와 같은 글꼴 크기와 굵기를 가져요:

h1, h2, h3, h4, h5, h6 {
  font-size: inherit;
  font-weight: inherit;
}

그 이유는 두 가지예요:

  • 우리가 실수로 타이포 스케일(type scale)에서 벗어나는 것을 막아줘요. 기본적으로 브라우저는 Tailwind의 기본 타이포 스케일에 없는 제목 크기를 지정하고, 우리만의 타이포 스케일에도 존재한다고 보장할 수 없기 때문이에요.
  • UI 개발에서 제목은 시각적으로 덜 강조되어야 하는 경우가 많아요. 제목을 기본적으로 스타일링하지 않으면, 제목에 적용하는 모든 스타일이 의식적이고 명확하게 이루어진다는 뜻이에요.

우리만의 base 스타일을 추가해서 프로젝트에 기본 헤더 스타일을 언제든 추가할 수 있어요.

목록(list)은 스타일이 지정되지 않습니다

순서 있는 목록과 순서 없는 목록은 기본적으로 불릿이나 번호 없이 스타일되지 않아요:

ol, ul, menu {
  list-style: none;
}

목록을 스타일링하고 싶다면 list-style-type과 list-style-position 유틸리티를 사용할 수 있어요:

<ul class="list-inside list-disc">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

우리만의 base 스타일을 추가해서 프로젝트에 기본 목록 스타일을 언제든 추가할 수 있어요.

접근성 고려사항 (Accessibility considerations)

스타일되지 않은 목록은 VoiceOver에서 목록으로 알려지지 않아요. 콘텐츠가 진짜 목록인데도 스타일을 유지하고 싶지 않다면, 요소에 "list" 역할을 추가하세요:

<ul role="list">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

이미지는 블록레벨(block-level)입니다

이미지와 기타 대체 요소(예: svg, video, canvas 등)는 기본적으로 display: block이에요:

img, svg, video, canvas, audio, iframe, embed, object {
  display: block;
  vertical-align: middle;
}

이렇게 하면 브라우저 기본값인 display: inline을 사용할 때 자주 겪게 되는 예상치 못한 정렬 문제를 피할 수 있어요.

이 요소 중 하나를 block 대신 inline으로 만들고 싶다면 inline 유틸리티를 사용하면 돼요:

<img class="inline" src="..." alt="..." />

이미지는 크기가 제한됩니다

이미지와 비디오는 고유한 가로세로 비율(aspect ratio)을 유지하면서 부모 너비에 맞춰 제한돼요:

img, video {
  max-width: 100%;
  height: auto;
}

이렇게 하면 컨테이너를 넘치는 것을 막아주고 기본적으로 반응형으로 만들어 줘요. 이 동작을 재정의해야 한다면 max-w-none 유틸리티를 사용하세요:

<img class="max-w-none" src="..." alt="..." />

hidden 속성을 가진 요소는 숨겨진 채 유지됩니다

[hidden]:where(:not([hidden="until-found"])) {
  display: none !important;
}

이 규칙은 hidden 속성을 가진 요소가 hidden="until-found"를 사용하지 않는 한 보이지 않게 유지되도록 강제해요. 요소를 사용자에게 보이게 하고 싶다면 hidden 속성을 제거하면 돼요.

Preflight 확장하기 (Extending Preflight)

Preflight 위에 우리만의 base 스타일을 추가하고 싶다면, CSS에서 @layer base를 사용해 base CSS 레이어에 추가하면 돼요:

@layer base {
  h1 {
    font-size: var(--text-2xl);
  }
  h2 {
    font-size: var(--text-xl);
  }
  h3 {
    font-size: var(--text-lg);
  }
  a {
    color: var(--color-blue-600);
    text-decoration-line: underline;
  }
}

더 알아보려면 adding base styles 문서를 참고하세요.

Preflight 비활성화하기 (Disabling Preflight)

Preflight을 완전히 비활성화하고 싶다면—예를 들어 기존 프로젝트에 Tailwind를 통합하거나, 우리만의 base 스타일을 정의하고 싶다면—필요한 Tailwind 부분만 임포트하면 돼요.

기본적으로 @import "tailwindcss";는 아래와 같은 것을 주입해요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);

Preflight을 비활성화하려면 그 임포트만 빼고 나머지는 모두 유지하면 돼요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);

Tailwind CSS 파일을 개별적으로 임포트할 때는 source(), theme(), prefix() 같은 기능들을 각 임포트에 맞게 넣어야 해요.

예를 들어 source 감지는 생성되는 유틸리티에 영향을 주므로, source(…)는 utilities.css 임포트에 추가해야 해요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);
@import "tailwindcss/utilities.css" layer(utilities) source(none);

important도 마찬가지로 유틸리티에 영향을 주므로 같은 방식으로 적용해요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);
@import "tailwindcss/utilities.css" layer(utilities) important;

마찬가지로 theme(static)와 theme(inline)은 생성되는 테마 변수에 영향을 주므로 theme.css 임포트에 두어야 해요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/theme.css" layer(theme) theme(static);
@import "tailwindcss/utilities.css" layer(utilities);

마지막으로 prefix(tw) 접두사를 사용하면 유틸리티와 변수 모두에 영향을 주므로, 두 임포트 모두에 넣어야 해요:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);
@import "tailwindcss/theme.css" layer(theme) prefix(tw);
@import "tailwindcss/utilities.css" layer(utilities) prefix(tw);

더 알아보기 (Learn more)

  • base 스타일 추가하기 (adding base styles) 문서
  • 테마 변수 (theme variable) 문서