calc()가 하는 일
calc()는 CSS 값 안에서 산술 계산을 하고, 레이아웃 시점에야 크기가 정해지는 단위도 섞을 수 있어요. 고전적인 경우는 "전체 너비에서 고정 사이드바 빼기"예요.
100%는 페이지가 배치된 뒤에야 알 수 있고 180px은 고정이라서, 단위 하나로는 이걸 표현할 수 없어요. calc()가 계산해 줘요. 너비 800px 미리보기에서 행은 784px이고 메인 열은 604px을 받으며, 레이아웃 아래 줄이 실제 숫자를 보여 줘요. 요즘은 flexbox나 grid가 계산 없이 이 레이아웃을 만들지만, 같은 뺄셈은 여전히 어디서나 나와요. 높이에서 헤더 빼기, 너비에서 간격 빼기 같은 거예요.
문법 규칙
width: calc(100% - 2rem); /* + and - need spaces on both sides */
width: calc(100% / 3); /* divide by a plain number */
margin: calc(var(--space) * 2); /* multiply by a plain number */
height: calc(100vh - (64px + 1rem)); /* parentheses group */
| 규칙 | 올바른 예 | 잘못된 예 |
|---|---|---|
+와 - 둘레에 공백 | calc(100% - 20px) | calc(100%-20px) |
*: 최소 한쪽은 그냥 숫자 | calc(2 * 1rem) | calc(2px * 3px) |
/: 길이를 그냥 숫자로 나누기 | calc(100% / 3) | width: calc(300px / 3px) (길이가 아님) |
| 단위가 호환되어야 해요 | calc(1rem + 10px) | calc(1rem + 2s) |
공백 규칙이 있는 이유는 100% -20px가 값 두 개로, 두 번째는 음수로 읽히기 때문이에요. calc()가 잘못되면 선언 전체가 버려지고 요소는 앞선 규칙에서 받은 값을 유지해요.
식 입력해 보기
상자 너비에 아무 식이나 입력해 보세요. 브라우저가 유효한지, 계산된 너비가 얼마인지 알려 줘요.
100%-200px(잘못됨, 공백 없음), 100% / 3, 50% + 4rem, 2 * 120px, 200px * 2px(잘못됨), (100% - 40px) / 2를 입력해 보세요.
CSS 변수와 calc()
변수와 calc()는 잘 어울려요. 기본값을 한 번 저장하고 나머지를 거기서 끌어내요. 단위 없는 변수에 단위 하나를 곱하면 길이가 돼요.
--space를 12px로, --cols를 4로 바꾸면 끌어낸 모든 값이 따라와요. 선언과 범위는 CSS 변수 페이지에서 다뤄요.
흔한 용도
| 필요한 것 | calc() |
|---|---|
| 고정 요소 옆 공간 채우기 | width: calc(100% - 240px) |
| 고정 헤더 아래 섹션 | min-height: calc(100vh - 64px) |
| 너비 절반에서 간격 절반 빼기 | width: calc(50% - 8px) |
| absolute로 배치한 100px 상자 가운데 정렬 | left: calc(50% - 50px) |
| 화면에 따라 조금씩 커지는 글자 크기 | font-size: calc(1rem + 0.5vw) |
| 숫자 변수를 길이로 바꾸기 | calc(var(--n) * 1px) |
| 변수의 음수 | calc(var(--space) * -1) |
한계 사이에 머물러야 하는 값에는 clamp()를 쓰세요. calc()를 쓰지 않아도 인수 안에서 같은 계산을 받아요.
calc()를 쓸 수 있는 곳
길이, 퍼센트, 숫자, 각도, 시간을 받는 곳이면 어디든 돼요. width, margin, padding, top, font-size, line-height, grid 트랙 크기, transition-delay, transform 안의 각도예요. 중첩할 수 있고, 중첩된 calc()는 그냥 괄호와 같아요.
각도가 좋은 예예요. 아래의 각 눈금은 자기 --i(0에서 11)를 가지고, 규칙 하나가 calc(var(--i) * 30deg)로 그걸 각도로 바꿔요.
눈금 3은 rotate(90deg)를 받고, Chrome은 이를 행렬 matrix(0, 1, -1, 0, 0, 0), 즉 4분의 1 회전으로 보고해요. left: calc(50% - 2px)는 자기 4px 너비의 절반을 빼서 각 눈금을 가운데에 놓아요.
자주 하는 실수
-나+둘레에 공백 없음.calc(100%-20px)는 잘못된 코드라서 무시돼요.- 두 길이 곱하기.
calc(10px * 2px)는 CSS에서 의미가 없어요.*의 한쪽은 그냥 숫자여야 해요. - 부모 높이 없이 퍼센트 높이에 calc() 쓰기.
height에 쓴calc(100% - 20px)는height: 100%처럼 부모에 높이가 지정되어 있어야 해요. - flexbox나 grid로 될 일에 calc() 쓰기. 열에
width: calc(33.333% - 10px)를 쓰는 건 깨지기 쉬워요.display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px는 계산이 필요 없어요. - 오류 메시지를 기대하기. 브라우저는 잘못된 calc()에 경고하지 않아요. 개발자 도구에서 요소를 확인하세요. 잘못된 선언은 취소선으로 표시돼요.
자주 묻는 질문
CSS에서 calc()는 무엇을 하나요?
+, -, *, /로 된 식에서 값을 계산하고, 브라우저가 레이아웃 시점에야 아는 단위도 섞을 수 있어요. width: calc(100% - 200px)는 부모 너비가 얼마든 부모 전체 너비에서 200px을 뺀 값이에요.
calc()가 동작하지 않는 이유는 무엇인가요?
가장 흔한 원인은 공백 누락이에요. +와 -는 양쪽에 공백이 있어야 해서 calc(100%-20px)는 잘못된 코드예요. 다른 원인은 두 길이를 곱하거나(10px * 2px) 길이로 나누는 것인데, 길이가 나오지 않아요. 잘못된 calc()는 선언 전체를 잘못되게 만들어서 브라우저가 무시해요.
calc()에서 CSS 변수를 쓸 수 있나요?
네. calc(var(--gap) * 2)는 변수를 두 배로 하고, calc(var(--columns) * 1px)는 단위 없는 숫자를 픽셀로 바꿔요. 변수 값이 먼저 대입된 다음 계산돼요.
calc()에서 *와 / 둘레에도 공백이 필요한가요?
아니요. 공백이 필요한 건 +와 -뿐이에요. 공백이 없으면 -20px이 음수로 읽히기 때문이에요. *와 / 둘레의 공백은 선택이지만, 어디에나 쓰는 게 가장 기억하기 쉬운 규칙이에요.
calc()와 clamp()는 무엇이 다른가요?
calc()는 식에서 값 하나를 계산해요. clamp(MIN, VAL, MAX)는 값을 두 한계 사이에 유지해요. 둘은 함께 쓸 수 있어요. clamp()의 각 인수에는 이미 clamp(1rem, 1rem + 2vw, 3rem)처럼 calc 방식의 계산을 넣을 수 있어요.