CSS calc로 화면 너비를 숫자로 바꾸는 법: 길이끼리 나누기

창 너비에 맞춰 배지를 키우려는데 calc로 구한 값이 scale에 먹히지 않는다. 같은 나눗셈인데 어떻게 써야 scale이 받는 숫자가 나올까?

CSS calc로 화면 너비를 숫자로 바꾸는 법: 길이끼리 나누기
세 줄 요약
  • 길이를 숫자로 나누면 길이가 남고, 길이끼리 나누면 단위 없는 숫자가 된다.
  • 그 숫자는 배율에 쓰거나 각도 단위를 곱해 회전에 쓸 수 있다.
  • 구형 브라우저에는 기본 스타일을 남기고 실제 계산식을 @supports로 검사한다.

100vw를 숫자로 쓰려면 나누는 쪽에도 길이가 필요하다

창이 넓어질수록 장식 요소를 키우려면 현재 너비와 기준 너비의 비율이 필요하다. 이때 calc(100vw / 1000)를 배율로 넣으면 문제가 생긴다. 숫자 1000으로 나눠도 결과에 길이 단위가 남기 때문이다. 기준 너비를 1000px로 쓰면 길이끼리 나눠 단위 없는 비율을 얻는다.

10월 13일 나온 Firefox 158도 이런 타입 산술을 지원한다. MDN의 설명처럼 길이끼리 나누면 단위가 상쇄된다. 단위의 글자가 꼭 같을 필요는 없다. vw와 px는 모두 길이이므로 계산에 함께 쓸 수 있다.

계산식결과남는 타입
calc(1000px / 2)500px길이
calc(1000px / 2px)500숫자
calc(100vw / 1px)뷰포트가 1000 CSS px이면 1000숫자

여기서 얻는 것은 CSS 픽셀 기준의 값이다. 물리적인 디스플레이 해상도를 읽는 코드로 해석하면 안 된다. 1px 대신 다른 길이를 넣으면 그 길이에 대한 비율이 된다.

너비 비율 하나로 배율과 회전각을 만들 수 있다

다음은 1000px를 기준 너비로 삼은 작은 장식 배지 예제다. 기본 상태에서는 크기와 각도를 그대로 두고, 길이 나눗셈을 지원할 때만 계산을 적용한다.

.badge {
  scale: 1;
  rotate: 0deg;
}

@supports (scale: calc(1px / 1px)) {
  .badge {
    --ratio: calc(100vw / 1000px);
    scale: var(--ratio);
    rotate: calc(var(--ratio) * 10deg);
  }
}

scale에는 숫자로 된 배율을 넣을 수 있다. rotate에는 각도가 필요하므로 같은 비율에 10deg를 곱했다. 두 효과를 연결하기 위해 자바스크립트로 창 너비를 읽을 필요가 없는 구성이다.

가정한 뷰포트 너비배율회전각
500px0.55deg
1000px110deg
1500px1.515deg

표는 위 식의 산술 결과다. 창 너비에 따라 장식 요소가 얼마나 변해야 하는지에 맞춰 기준 너비와 회전각을 정하면 된다.

계산이 맞아도 width가 받을 수 있는 값이어야 한다

width: calc(1000px / 2px)는 숫자 500을 만들지만, 그 숫자를 500px로 바꿔 주지는 않는다. CSS Values의 타입 검사 규칙은 계산 결과가 해당 속성이 받는 타입이어야 한다고 설명한다. 길이를 만들 목적이라면 width: calc((1000px / 2px) * 1px)처럼 최종 결과를 길이로 만들어야 한다.

반대로 너비를 절반으로 줄이기만 할 때는 width: calc(1000px / 2)면 충분하다. 길이 나눗셈의 이점은 모든 식을 복잡하게 바꾸는 데 있지 않다. 길이에서 얻은 비율을 배율이나 각도처럼 다른 종류의 값으로 이어 쓸 때 유용하다.

calc 지원 여부보다 실제로 넣을 선언을 검사한다

오래전부터 calc()를 지원한 브라우저라도 길이끼리의 나눗셈까지 지원한다는 뜻은 아니다. 위 예제는 @supports의 선언 검사로 scale: calc(1px / 1px)를 받아들이는지 확인한다. 조건을 통과하지 못하면 앞에서 지정한 기본 배율과 각도를 유지한다.

프로젝트에 적용할 때도 먼저 필요한 결과의 타입을 정하면 식이 단순해진다. 길이가 필요하면 길이를 남기고, 비율이 필요하면 같은 타입끼리 나눈다. 화면 너비를 다른 효과에 연결하려던 코드라면 이 차이부터 확인할 만하다.