AspectRatioBox
child 를 고정 width:height 비율 박스로 제약하는 컨테이너
목차
child 를 고정 width:height 비율(ratio)로 제약하는 컨테이너입니다. Flutter AspectRatio
위젯과 동일하며, Web 에서는 padding-top 퍼센트 트릭 + position: relative + 절대 배치 콘텐츠 레이어로 같은 의미를 재현합니다. 이미지·미디어 임베드를 반응형으로 유지할 때 씁니다.
Live Preview#
코드 보기
class AspectRatioBoxDefaultExample extends StatelessComponent {
const AspectRatioBoxDefaultExample({super.key});
@override
Component build(BuildContext context) {
return div(
styles: Styles(raw: {'width': '280px', 'max-width': '100%'}),
[
AspectRatioBox(
ratio: 16 / 9,
child: Card(
child: div(
classes: 'flex items-center justify-center w-full h-full',
[Text('16 : 9').titleMedium],
),
),
),
],
);
}
}
class AspectRatioBoxDefaultExample extends StatelessWidget {
const AspectRatioBoxDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
width: 280,
child: AspectRatioBox(
ratio: 16 / 9,
child: Card(
child: Center(child: Text('16 : 9').titleMedium),
),
),
);
}
}
사용법#
// Flutter / Web 동일
AspectRatioBox(
ratio: 16 / 9,
child: Card(child: Center(child: Text('16 : 9').titleMedium)),
)
Props / Parameters#
W 는 Flutter의 Widget, Web의 Jaspr Component 입니다.
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
child | W | 필수 | 비율-제약 박스 안에 배치되는 콘텐츠 |
ratio |
double |
필수 | width / height 비율. 비정상 값은 테마의 defaultRatio → CoreAspectRatioBoxStyle.defaultDefaultRatio(1.0)로 폴백 |
너비는 부모가 정합니다 —
AspectRatioBox는 그 너비에서ratio에 맞는 높이를 산출합니다(또는 그 반대). 위 프리뷰는 280px 너비 안에서 16:9 박스를 보여줍니다.
스타일 시스템 (Style System)#
CoreAspectRatioBoxStyle 필드#
| 필드 | 타입 | 설명 |
|---|---|---|
defaultRatio |
double? |
Project-level fallback ratio (
width / height
) when the widget caller supplies a value that is not strictly positive.
null
defers to [defaultDefaultRatio] (square).
|
동작 스펙 (Behavior)#
-
ratio는 단위 없는 너비 / 높이 비율입니다. 유한 양수이면 그대로 쓰고, 그 외에는CoreComponentTheme.aspectRatioBox.style.defaultRatio→CoreAspectRatioBoxStyle.defaultDefaultRatio(1.0) 순으로 폴백합니다. -
부모 제약 안에서 비율에 맞는 박스를 만들고
child를 그 안에 채웁니다. 이미지 자르기 · 로딩 · 재생 · 클릭은 자식의 책임이며 이 컴포넌트에는 콜백이나 비활성 상태가 없습니다. - 너비와 높이의 비율 고정이 필요하면 이 컴포넌트, 비율 없이 콘텐츠 슬롯을 묶는 표면이면 Card 를 씁니다. 둘은 함께 조합할 수 있습니다.
사용 가이드라인 (Usage Guidelines)#
✅ Do#
유한하고 양수인 ratio 를 명시적으로 전달
AspectRatioBox(
ratio: 16 / 9,
child: Image.network(url),
)
ratio 는 > 0 인 유한 값이어야 하며, 16 / 9 같은 리터럴 나눗셈으로 넘기면 의도한 비율이 그대로 유지됩니다.
❌ Don't#
계산된 값을 검증 없이 ratio 로 넘기지 않기
// ❌ height 가 0이면 무한대, width 가 0이면 0이 되는 값을 그대로 사용
AspectRatioBox(
ratio: width / height,
child: media,
)
비정상 값(0, 음수, NaN, 무한대)은 테마의 defaultRatio, 없으면 기본 1.0 로 폴백됩니다. 테마 폴백 값 자체의 유효성은 resolver가 다시 검증하지 않으므로 그 값도 유한 양수로 제공하세요.
접근성 (Accessibility)#
역할#
양쪽 플랫폼 모두 아무 역할도 내보내지 않습니다. Flutter 는 AspectRatio 를 그대로 반환하며 Semantics
를 붙이지 않고, Web 은 비율을 지탱하는 spacer <div> 와 콘텐츠 <div> 를 감싼 <div>
를 그릴 뿐 role 이나 aria-* 를 설정하지 않습니다. 보조기술 입장에서 이 컴포넌트는 통과 지점이며, child
가 알리는 내용이 곧 전부입니다.
키보드#
없습니다. 양쪽 모두 키 핸들러가 없습니다.
포커스 관리#
없습니다. 포커스를 받지 않고(Flutter FocusNode 없음 / Web tabindex 없음), 포커스 링을 그리지 않으며, 포커스를 가두거나 되돌리지 않습니다.
스크린 리더#
child 의 announcement 가 전부입니다. Web 의 spacer <div> 는 자식이 없어 읽을 텍스트를 만들지 않습니다 —
aria-hidden 이 붙어 있지는 않지만 비어 있어 결과적으로 조용합니다.
알려진 제약#
-
이름이나 역할이 필요하면 소비자가 직접 붙여야 합니다. Web 은
attributespassthrough 로role/aria-label을 넣을 수 있습니다. -
Flutter 생성자에는
attributes도semanticsLabel도 없어, 같은 일을 하려면 호출부에서AspectRatioBox를 자신의Semantics로 감싸야 합니다. 이 비대칭은 현재 코드 그대로입니다.
모든 컴포넌트에 공통으로 적용되는 축은 전역 접근성 축에 있습니다.
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 비율 제약 | AspectRatio 의 부모 constraint 기반 레이아웃 |
너비 기준 padding-top: 100 / ratio % spacer와 절대 배치 콘텐츠 |
| 콘텐츠 채움 | 자식에게 tight constraint 전달 | coui-aspect-fill 자식 선택자로 너비 · 높이 100% 적용 |
| 프레임워크 인프라 | key |
key
,
id
,
classes
,
css
,
attributes
,
eventHandlers
를 루트로 전달
|