이 글에서 정리하는 내용
Tailwind CSS v4 기준으로 임의 값 문법에서 공백이 들어갈 때 클래스가 깨지는 이유를 정리합니다.처럼 기존 CSS에서는 자연스럽게 쓰던 값을 Tailwind 클래스 안으로 옮길 때 어떤 방식으로 바꿔야 하는지, 그리고 가 언제 공백으로 변환되고 언제 그대로 남는지까지 함께 다룹니다.
- Tailwind 임의 값은 CSS 값을 넣는 통로에 가깝다
- 공백이 들어가면 클래스명이 왜 끊어질까
_로 공백을 표현하는 방식- 항상
_가 공백으로 바뀌는 것은 아니다 - 임의 값을 계속 쓸지, CSS 변수로 뺄지 판단하는 기준
- 정리
Tailwind 임의 값은 CSS 값을 넣는 통로에 가깝다

Tailwind를 쓰다 보면 정해진 유틸리티만으로는 딱 맞지 않는 순간이 생깁니다. 예를 들어 카드 폭을 정확히 로 맞춰야 하거나, 디자인 시안에 있는 배경색 를 그대로 반영해야 할 때가 있습니다. 이럴 때 대괄호 문법을 사용하면 기존 CSS 값을 Tailwind 클래스 안에서 바로 표현할 수 있습니다.
<div className="w-[320px] bg-[#f5f5f5]"> 내용
</div> 이 정도 값은 크게 흔들릴 부분이 없습니다. 대괄호 안에 들어간 값이 하나의 덩어리이고, 공백도 없기 때문입니다. 는 너비를 로 만들고는 배경색을 직접 지정합니다. 기존 CSS로 쓰면에 해당합니다.
문제는 기존 CSS 값이 항상 이렇게 단순하지 않다는 데 있습니다. 퍼블리싱 작업에서는 처럼 공백을 포함한 값을 자주 씁니다. 이 값을 Tailwind 안으로 그대로 옮기면 겉보기에는 CSS 값을 복사한 것 같지만, 실제로는 클래스 문자열 자체가 쪼개질 수 있습니다.
임의 값 문법의 큰 개념을 먼저 잡고 싶다면 Tailwind Arbitrary Value Variant 차이: 대괄호 문법 사용 기준과 함께 보면 흐름이 이어집니다. 이번 글은 그중에서도 공백 처리 문제만 따로 떼어, 실제로 레이아웃이 적용되지 않는 상황을 기준으로 좁혀서 정리합니다.
공백이 들어가면 클래스명이 왜 끊어질까
HTML에서 속성은 공백으로 여러 클래스를 구분합니다. React의 도 결국 HTML class 문자열로 렌더링되기 때문에 같은 기준을 따릅니다. 개발자가 보기에는 대괄호 안에 있는 값이라도, 문자열 안에 공백이 들어간 순간 하나의 클래스명으로 유지되지 않을 수 있습니다.
<div className="grid grid-cols-[1fr 500px 2fr]"> ...
</div> 위 코드는 CSS에 익숙한 사람에게는 자연스럽게 보입니다. 값으로 을 넣으려는 의도가 분명하기 때문입니다. 하지만 문자열 기준으로 보면처럼 나뉘어 읽힐 수 있습니다. 이 상태에서는 Tailwind가 온전한 클래스를 찾기 어렵습니다.
이 지점이 퍼블리셔 입장에서 특히 자주 걸립니다. CSS 파일에서는 공백이 값의 일부입니다. 반면 class 속성에서는 공백이 클래스와 클래스를 나누는 기준입니다. 같은 공백이지만 문맥이 다르기 때문에, 기존 CSS 값을 Tailwind로 옮길 때 한 번 변환하는 과정이 필요합니다.
Grid 레이아웃을 Tailwind로 자주 옮긴다면 Tailwind CSS Grid 실무 레이아웃 정리에서, 흐름을 먼저 잡아둘 수 있습니다. 지금 다루는 공백 문제는 그중에서도 임의 값으로 열 구조를 직접 지정할 때 가장 쉽게 드러납니다.
기존 CSS와 Tailwind 의 차이
.layout { display: grid; grid-template-columns: 1fr 500px 2fr;
} CSS 파일 안에서는 이 값이 정상입니다., 사이의 공백은 grid column track을 나누는 역할을 합니다. 하지만 Tailwind 클래스 안에서는 이 공백을 그대로 둘 수 없습니다. 같은 값을 표현하더라도 안에서는 다른 방식으로 적어야 합니다.
로 공백을 표현하는 방식
Tailwind 임의 값 안에서 공백이 필요할 때는 공백 대신 를 사용합니다. Tailwind는 빌드 과정에서 이 언더스코어를 공백으로 변환합니다. 그래서 는 최종적으로 처럼 해석됩니다.
<div className="grid grid-cols-[1fr_500px_2fr]"> ...
</div> 처음에는 가 오히려 낯설 수 있습니다. CSS 값으로 보면 은 이상한 값처럼 보입니다. 하지만 이 코드는 CSS 파일에 직접 쓰는 값이 아니라, Tailwind가 빌드 전에 읽어야 하는 클래스 이름입니다. 여기서 는 최종 CSS 값 자체라기보다 “여기에 공백이 들어가야 한다”는 표시입니다.
calc()에서도 같은 기준을 적용한다
는 기존 CSS에서 자주 쓰는 값입니다. 예를 들어 전체 너비에서 여백이나 사이드바 폭을 빼고 싶을 때 같은 계산식을 씁니다. 이 값을 Tailwind 임의 값으로 넣을 때도 공백을 그대로 두면 안 됩니다.
<div className="w-[calc(100%_-_24px)]"> ...
</div> 여기서 는 사이의 공백을 대신합니다. 최종 의도는 입니다. 연산자 주변 공백을 유지해 두면 계산식의 구조가 바로 보이지만, Tailwind 클래스 안에서는 그 공백을 로 표현해야 하나의 클래스명으로 유지됩니다.
box-shadow처럼 공백이 많은 값
그림자 값도 같은 문제를 만납니다. 시안에서 받은 shadow가 Tailwind 기본 shadow scale과 맞지 않으면 임의 값으로 넣고 싶어집니다. 이때 숫자 사이의 공백은 전부 로 바꿔야 합니다.
<div className="rounded-xl bg-white shadow-[0_8px_24px_rgba(0,0,0,0.12)]"> 카드 내용
</div> 이 코드는 에 가까운 의도로 작성한 예입니다. Tailwind 기본값으로 충분하면같은 클래스를 쓰면 됩니다. 디자인 시안의 특정 수치를 그대로 맞춰야 하는 경우에는 임의 값이 현실적인 선택지가 됩니다.
항상 가 공백으로 바뀌는 것은 아니다
공백이 필요할 때 를 쓴다는 규칙만 외우면 또 다른 오해가 생깁니다. 모든 언더스코어가 무조건 공백으로 바뀌는 것은 아닙니다. Tailwind는 URL처럼 언더스코어가 일반적으로 쓰이고, 공백이 유효하지 않은 위치에서는 언더스코어를 그대로 유지합니다.
<div className="bg-[url('/images/main_banner.png')]"> ...
</div> 위 예시에서 의 는 파일명 일부입니다. 이 경우에는 공백으로 바뀌면 오히려 URL이 깨집니다. 그래서 규칙은 “대괄호 안에서는 항상 공백으로 바뀐다”가 아니라, “공백이 필요한 값에서는 로 표현한다”로 기억하는 편이 덜 헷갈립니다.
content 값에서는 실제 언더스코어와 공백이 헷갈릴 수 있다
조금 더 애매한 경우는 값입니다. 처럼 작성했을 때, 의도한 값이 인지 인지 상황에 따라 헷갈릴 수 있습니다. 실제 언더스코어를 남겨야 한다면 escape 처리를 고려해야 합니다.
<div className="before:content-['hello_world']"> ...
</div> React JSX에서는 escape 문자가 렌더링 과정에서 다르게 처리될 수 있습니다. 이럴 때는 문자열을 그대로 보존하기 위해 를 사용하는 방식이 필요할 수 있습니다.
<div className={String.raw`before:content-['hello_world']`}> ...
</div> 이 예시는 자주 쓰는 패턴이라기보다, 실제 언더스코어를 콘텐츠로 출력해야 하는 상황에서 확인할 예외입니다. 대부분의 레이아웃 작업에서는 처럼 값 내부 공백을 로 바꾸는 경우가 더 많습니다.
임의 값을 계속 쓸지, CSS 변수로 뺄지 판단하는 기준

임의 값은 예외적인 수치를 빠르게 넣을 때 편합니다. 하지만 클래스가 너무 길어지면 수정 기준이 흐려집니다. 특히 처럼 값이 복잡해지거나같은 계산식이 여러 컴포넌트에 반복된다면 Tailwind 클래스 안에 계속 두는 것이 관리 부담으로 돌아올 수 있습니다.
한 화면에서 한 번만 쓰는 예외라면 임의 값으로 충분합니다. 관리자 화면의 특정 패널 폭, 임시 배너의 고정 높이, 한 번만 등장하는 특수한 shadow 정도는 대괄호 문법으로 처리해도 읽는 데 큰 무리가 없습니다. 반대로 여러 페이지에서 반복되는 레이아웃 기준이라면 이름을 붙여 분리하는 쪽이 낫습니다.
<section className="grid grid-cols-[220px_1fr] gap-6"> <aside>필터</aside> <div>목록</div>
</section> 위처럼 단순한 관리자 목록 레이아웃은 임의 값으로도 읽을 만합니다. 짜리 필터 영역과 남은 영역을 나누는 구조가 바로 보입니다. 하지만 같은 기준이 검색 페이지, 상품 관리 페이지, 주문 관리 페이지에 반복된다면 별도 레이아웃 컴포넌트나 CSS 변수로 기준을 고정하는 것이 낫습니다.
Tailwind v4에서 디자인 토큰이나 테마 변수를 정리하는 흐름까지 같이 봐야 한다면 Tailwind @theme 사용법: 변수와 디자인 토큰 차이와 연결해서 보면 됩니다. 임의 값은 빠른 예외 처리에 강하고, 토큰은 반복되는 기준을 관리하는 데 더 적합합니다.
작업 중 확인할 기준
| 상황 | 처리 기준 |
|---|---|
| 한 번만 쓰는 특수한 값 | 임의 값 문법으로 처리 |
| 공백이 들어가는 CSS 값 | 공백 대신 사용 |
| 여러 컴포넌트에서 반복되는 값 | CSS 변수, 테마 토큰, 공통 컴포넌트로 분리 |
| 실제 언더스코어를 출력해야 하는 값 | escape 처리 여부 확인 |
Tailwind 기본 유틸리티와 임의 값 사이의 경계가 헷갈린다면 Tailwind CSS 기본 클래스: text font bg spacing 사용 기준처럼 기본 클래스의 역할을 먼저 정리해두는 것도 방법입니다. 기본 scale로 해결되는 값까지 전부 대괄호로 넣기 시작하면 Tailwind를 쓰는 장점이 줄어듭니다.
정리
Tailwind 임의 값 문법은 기존 CSS 값을 빠르게 가져올 수 있는 통로입니다. 다만 그 값은 CSS 파일이 아니라 HTML 안에 들어갑니다. 그래서 값 안의 공백이 CSS 값의 일부인지, class 문자열을 나누는 구분자인지부터 구분해야 합니다.
처럼 공백이 필요한 값은 로 바꿔 적습니다. 반면 URL의 파일명처럼 언더스코어가 원래 값의 일부인 경우에는 그대로 유지될 수 있습니다. 처럼 애매한 상황에서는 escape 처리를 확인해야 합니다.
다음에 Tailwind 임의 값이 적용되지 않는다면 대괄호 안의 공백부터 확인하면 됩니다. 기존 CSS에서 자연스럽게 쓰던 값을 그대로 복사했는지, 안에서 하나의 클래스명으로 유지되는지, 반복되는 값인데 임의 값으로 너무 길게 남겨둔 것은 아닌지 순서대로 보면 원인을 빠르게 좁힐 수 있습니다.
참고 자료로는 Tailwind CSS 공식 문서의 arbitrary values, handling whitespace 항목을 기준으로 공백 처리와 언더스코어 예외를 확인했습니다.