compatibility
compatibility (호환성)
Tailwind CSS v4가 지원하는 브라우저와, Sass·Less·Stylus 같은 CSS 전처리기와의 관계를 설명하는 문서예요. 옆에서 함께 짚어 드릴게요.
출처: 문서
본문
Browser support
Tailwind CSS v4.0은 현대 브라우저를 위해 설계되었고 그 환경에서 테스트되었어요. 프레임워크의 핵심 기능은 구체적으로 다음 브라우저 버전에 의존해요.
- Chrome 111 (2023년 3월 출시)
- Safari 16.4 (2023년 3월 출시)
- Firefox 128 (2024년 7월 출시)
또한 Tailwind는 field-sizing: content, @starting-style, text-wrap: balance 같은 지원이 제한적인 최첨단 플랫폼 기능도 지원해요. 이런 현대 기능을 프로젝트에서 쓸지 말지는 여러분의 몫이에요 — 타깃 브라우저가 지원하지 않는다면 그냥 해당 유틸리티와 변형을 사용하지 않으면 돼요.
현대 플랫폼 기능의 지원 여부가 확실하지 않다면, Can I use 데이터베이스가 훌륭한 자료예요.
Sass, Less, and Stylus
Tailwind CSS v4.0은 특정 워크플로우를 위해 설계된 완전한 기능의 CSS 빌드 도구예요. Sass, Less, Stylus 같은 CSS 전처리기와 함께 쓰도록 설계되지는 않았어요.
Tailwind CSS 자체를 여러분의 전처리기라고 생각해 보세요 — Sass와 Stylus를 같이 안 쓰는 것과 같은 이유로 Tailwind를 Sass와 함께 쓰지 않아야 해요.
Tailwind는 현대 브라우저를 위해 설계되었기 때문에, 중첩(nesting)이나 변수(variables) 같은 기능을 위해 전처리기가 실제로 필요하지 않아요. Tailwind 자체가 import 번들링이나 벤더 프리픽스 추가 같은 일을 처리해 줘요.
Build-time imports
Tailwind는 별도의 전처리 도구 없이도 @import 로 포함한 다른 CSS 파일을 자동으로 번들해 줘요.
/* app.css */
@import "tailwindcss";
@import "./typography.css";
이 예시에서 typography.css 파일은 Sass나 postcss-import 같은 별도 도구 없이 Tailwind가 컴파일 과정에서 CSS에 번들해 줘요.
Variables
모든 현대 브라우저는 전처리기 없이도 네이티브 CSS 변수를 지원해요.
/* typography.css */
.typography {
font-size: var(--text-base);
color: var(--color-gray-700);
}
Tailwind는 내부적으로 CSS 변수를 많이 사용해요. 그래서 프로젝트에서 Tailwind를 쓸 수 있다면 네이티브 CSS 변수도 쓸 수 있다고 보면 돼요.
Nesting
내부적으로 Tailwind는 Lightning CSS를 사용해서 이런 중첩 CSS를 처리해요.
/* typography.css */
.typography {
p {
font-size: var(--text-base);
}
img {
border-radius: var(--radius-lg);
}
}
Tailwind는 이 중첩 CSS를 펼처서(flatten) 모든 현대 브라우저가 이해할 수 있게 해 줘요.
/* output.css */
.typography p {
font-size: var(--text-base);
}
.typography img {
border-radius: var(--radius-lg);
}
요즘은 네이티브 CSS 중첩 지원도 아주 좋아서, Tailwind를 쓰지 않더라도 중첩을 위해 전처리기가 꼭 필요하지 않아요.
Loops
과거에 루프로 만들었을 법한 클래스들(예: col-span-1, col-span-2 등)은 Tailwind에서 미리 정의할 필요 없이, 사용할 때마다 Tailwind가 온디맨드로 생성해 줘요.
게다가 Tailwind CSS로 작업할 때 스타일링의 대부분은 CSS 파일이 아닌 HTML에서 이뤄져요. 처음부터 CSS를 많이 쓰지 않으니, 많은 커스텀 CSS 규칙을 프로그래밍 방식으로 생성하기 위한 루프 같은 기능이 그냥 필요 없어요.
Color and math functions
Sass나 Less 같은 전처리기를 쓸 때 darken 이나 lighten 같은 함수로 색상을 조절하곤 했을 거예요.
Tailwind를 쓸 때 권장하는 워크플로우는 각 색상의 밝은/어두운 음영을 포함한 미리 정의된 컬러 팔레트(프레임워크에 포함된 잘 설계된 기본 팔레트 같은)를 사용하는 거예요.
<button class="bg-indigo-500 hover:bg-indigo-600 ...">
<!-- ... -->
</button>
또한 color-mix() 같은 현대 CSS 기능을 사용해서 런타임에 브라우저에서 직접 색상을 조절할 수도 있어요. 이렇게 하면 CSS 변수나 currentcolor 키워드로 정의된 색상도 조절할 수 있는데, 이는 전처리기로는 불가능해요.
마찬가지로 브라우저는 이제 min(), max(), round() 같은 수학 함수를 지원하므로, 이 기능들도 더 이상 전처리기에 의존할 필요가 없어요.
CSS modules
Tailwind는 CSS 모듈과 호환되며, 이미 CSS 모듈을 사용하는 프로젝트에 Tailwind를 도입할 때 함께 공존할 수 있어요. 하지만 가능하다면 CSS 모듈과 Tailwind를 함께 쓰는 것은 권장하지 않아요.
Scoping concerns
CSS 모듈은 커스텀 CSS를 작성하는 대신 HTML에서 유틸리티 클래스를 조합할 때 존재하지 않는 스코프 문제를 해결하기 위해 설계됐어요.
Tailwind에서는 각 유틸리티 클래스가 어디서 사용되든 항상 동일한 일을 하기 때문에 스타일이 자연스럽게 스코프되요. UI의 한 부분에 유틸리티 클래스를 추가한다고 해서 다른 곳에 예상치 못한 부작용이 생길 위험이 없어요.
Performance
CSS 모듈을 사용하면 Vite, Parcel, Turbopack 같은 빌드 도구가 각 CSS 모듈을 별도로 처리해요. 즉 프로젝트에 CSS 모듈이 50개라면 Tailwind가 50번 별도로 실행되어야 하고, 이는 빌드 시간이 훨씬 느려지고 개발자 경험이 나빠져요.
Explicit context sharing
각 CSS 모듈은 별도로 처리되기 때문에, import하지 않는 한 @theme 를 갖지 않아요.
즉, 전역 스타일을 reference로 명시적으로 import하지 않으면 @apply 같은 기능이 기대대로 동작하지 않아요.
/* Button.module.css */
@reference "../app.css";
button {
@apply bg-blue-500;
}
또는 @apply 대신 CSS 변수를 그냥 사용할 수도 있어요. 이렇게 하면 Tailwind가 해당 파일 처리를 건너뛸 수 있어서 추가로 빌드 성능이 개선되는 장점이 있어요.
/* Button.module.css */
button {
background: var(--color-blue-500);
}
Vue, Svelte, and Astro
Vue, Svelte, Astro는 컴포넌트 파일에서 CSS 모듈과 매우 유사하게 동작하는 <style> 블록을 지원해요. 이는 각각 빌드 도구에 의해 완전히 별도로 처리되고 동일한 단점을 모두 갖는다는 뜻이에요.
이들 도구와 Tailwind를 함께 쓴다면, 컴포넌트에서 <style> 블록을 사용하지 말고 Tailwind가 의도한 방식대로 마크업에서 직접 유틸리티 클래스로 스타일링할 것을 권장해요.
<style> 블록을 쓴다면, @apply 같은 기능이 기대대로 동작하게 하려면 전역 스타일을 reference로 import해야 해요.
<!-- Button.vue -->
<template>
<button><slot /></button>
</template>
<style scoped>
@reference "../app.css";
button {
@apply bg-blue-500;
}
</style>
또는 @apply 같은 기능 대신 전역으로 정의된 CSS 변수를 사용하면, Tailwind가 컴포넌트 CSS를 전혀 처리하지 않아도 돼요.
<!-- Button.vue -->
<template>
<button><slot /></button>
</template>
<style scoped>
button {
background-color: var(--color-blue-500);
}
</style>