왜 Safari에서 aspect-ratio가 안되죠?

badahertz52·2025년 12월 29일

web

목록 보기
5/5
post-thumbnail

Issue

뷰 상단 고정 요소에 aspect-ratio를 썼더니 Safari에서 깨져요

뷰포트에 따라 반응형으로 크기를 유지하기 위해 aspect-ratio를 사용했습니다.

Chrome 개발자 도구에서는 잘 보였는데, Safari를 사용하는 iOS 웹뷰에서는 요소가 보이지 않거나 레이아웃이 깨지는 현상이 발생했습니다.

aspect-ratio는 표준 CSS 속성이고, 최신 iOS에서도 지원하는데…
왜 Safari에서는 문제가 생길까요?

왜 Chrome은 괜찮은데, Safari에서 이런 오류가 나는 걸까요?

저는 브라우저 엔진에서 그 원인을 찾았습니다.

Trobleshooting

CSS aspect-ratio란?

aspect-ratio는 “이 요소는 이 비율을 선호해요”라고 브라우저에게 힌트를 주는 속성입니다.

레이아웃 단계에서 계산되며, width/height 중 하나만 있을 때 의미가 있습니다. 둘 다 고정되어 있으면 이 속성은 무시됩니다.

CSS 사양은 aspect-ratio 값을 “preferred aspect ratio”로 정의하고 있고, 계산 순서에 대한 구체적인 지침은 주지 않습니다.

즉, aspect-ratio는 “비율”을 지정해 주는 힌트이지, 항상 무조건 적용되는 절대 값이 아닙니다.

브라우저는 이 힌트를 어떻게 처리할까요?
브라우저 엔진에 따라 다릅니다.

브라우저 엔진에 따른, 레이아웃 관점의 차이

Chrome의 Blink엔진은 웬만하면 개발자 의도를 반영합니다.

이와 달리, Safari의 WebKit 엔진은 명세와 계산 순서를 엄격하게 지킵니다. (UX를 우선하는 WebKit의 기본철학때문인 것 같습니다.)

이런 관점의 차이로 인해, 각 브라우저의 aspect-ratio 처리 방식이 다르게 됩니다.

CASE1. height: 0 + aspect-ratio

.element {
	width:100px; 
	height: 0;
	aspect-ratio: 16/9;
}
  • Chrome: aspect-ratio를 우선 적용하여 재계산
  • Safari: 명시된 height: 0을 우선 적용해 aspect-ratio를 무시

CASE2. position: sticky와의 조합

.element { 
	position: sticky;
	aspect-ratio: 800/132;
}
  • Safari
    • sticky를 스크롤 처리와 위치 고정과 연결된 레이아웃으로 처리
    • WebKit 철학:“스크롤 중 절대 레이아웃을 다시 계산하지 말자”
      → sticky 관련 위치/범위를 먼저 “고정” 시키고 aspect-ratio는 이후에 판단
      → 레이아웃 단계에서 aspect-ratio가 계산되지 않아 적용되지 않음
  • Chrome
    • sticky를 레이아웃 파생 결과로 취급
    • aspect-ratio를 1급 sizing 규칙으로 규정해, sticky 여부와 무관하게 size 먼저 확정

💡 1급 sizing 규칙이란?
레이아웃 단계에서 반드시 먼저 고려되어야하는, 다른 레이아웃 결정의 기준이 되는 크기 결정 규칙

CASE3. Flex Container

<div class="parent" style="aspect-ratio: 800/132">
  <div class="child" style="display: flex; height: 100%">
    <!-- 자식 요소 -->
  </div>
</div>

Safari은 부모의 높이를 먼저 확정하지 않고,자식의 계산을 먼저 시도하면서 순환 참조 상황이 생겨 aspect-ratio 적용이 무시되는 경우가 있습니다.

Chrome은 이런 계산 순서를 좀 더 유연하게 처리합니다.

Solution

.element {
  width: 100%;
  height: 0;
  padding-bottom: 56.25%; /* (height / width) × 100% */
  position: relative;
}

sticky, flex를 사용한다면 padding-bottom이나 padding-top을 사용하는것이 안전합니다.
aspect-ratio는 ‘믿을 수 있는 힌트’이지만, padding은 ‘확정된 계산식’이기 때문입니다. 또한 aspect-ratio를 지원하지 않는 오래된 브라우저에서도 안정적으로 동작합니다.

마무리

iOS의 Selection 객체 초기화 문제, Chrome의 AutoFill 처리 방식, 그리고 이번 aspect-ratio 이슈까지 — 이러한 문제들의 공통 분모는 결국 브라우저 엔진과 그 엔진 기반 브라우저의 설계 철학의 차이였습니다.

물론 실무에서는 버그를 빨리 해결해서 제품이 제대로 동작하게 만드는 것이 가장 중요합니다. 하지만 저는 여기에 한 걸음 더 들어가서 왜 이런 문제가 발생했을까를 들여다보는 것이 정말 도움이 된다고 느꼈습니다.

문제의 근본 원인을 이해하면 비슷한 이슈가 생겼을 때 단순히 코드를 고치는 것이 아니라, 어떤 브라우저가 어떤 철학을 가지고 동작하는지 판단할 수 있게 됩니다.

그리고 이런 경험이 쌓이면, CS 자체가 더 재미있어지고 — 위에서 다룬 것처럼 과거의 트러블 슈팅이 새로운 문제를 예측하는 데 도움이 되고 기억에 더 남는 경우가 많았습니다.

무튼!! 이 글이 올해 2025년의 마지막 블로그 글이 될 것 같습니다.
(산타 할아버지가 어른이된 개발자에게 배포할 거리는 선물로 주시네요. 🫠 )

내년은 더 좋은 글로 찾아뵙겠습니다!!!

참고 자료

profile
세상과 사람을 잇는 개발을 꿈꾸는 프론트엔드 개발자

0개의 댓글