宽高比

还没加载任何东西时,高度就已经由宽度定下来了,所以姗姗来迟的图片或嵌入内容不会把页面其余部分往下挤。子元素会填满盒子并被裁切,而不是留出黑边。

基础宽高比

aspectRatio({ ratio: '16 / 9', style: 'background: var(--su-surface-2)' },
  '<img src="/logo.svg" alt="" style="object-fit: contain; padding: 2rem">',
)

常见比例

16 / 9
4 / 3
1 / 1
3 / 4
grid({ min: '9rem' },
  ...['16 / 9', '4 / 3', '1 / 1', '3 / 4'].map((ratio) =>
    stack({ gap: 'xs' },
      aspectRatio({ ratio, style: 'background: var(--su-surface-2); border-radius: 0.5rem' },
        '<img src="/logo.svg" alt="" style="object-fit: contain; padding: 1rem">'),
      text({ variant: 'caption', tone: 'muted', align: 'center' }, ratio),
    ),
  ),
)

嵌入内容

这个组件存在的理由:<iframe> 没有固有尺寸,不给比例就会塌掉,或者只能写死一个高度。

这里会放一个 <iframe>
aspectRatio({ ratio: '16 / 9', style: 'background: var(--su-surface-2); border-radius: 0.6rem' },
  '<div style="display: grid; place-items: center; color: var(--su-text-subtle)">这里会放一个 &lt;iframe&gt;</div>',
)

在卡片中

卡片顶部已经由 cardMedia() 做了这件事。盒子在别处时,才用 aspectRatio()。

cardMedia——内置

aspectRatio——其他任何地方

grid({ min: '12rem' },
  card(
    cardMedia({ src: '/logo.svg', alt: '', style: 'background: var(--su-surface-2); object-fit: contain; padding: 1rem' }),
    cardBody(text({ variant: 'small' }, 'cardMedia——内置')),
  ),
  card(
    cardBody(
      stack({ gap: 'sm' },
        aspectRatio({ ratio: '1 / 1', style: 'background: var(--su-surface-2); border-radius: 0.5rem' },
          '<img src="/logo.svg" alt="" style="object-fit: contain; padding: 1rem">'),
        text({ variant: 'small' }, 'aspectRatio——其他任何地方'),
      ),
    ),
  ),
)

裁切

子元素会被拉伸填满,并按 object-fit: cover 裁切。对于不能被裁的东西——标志、图示——请在子元素上设置 object-fit: contain,本页每个示例都是这么做的。

属性

属性类型默认值说明
ratiostring'16 / 9'任意 CSS aspect-ratio 值。
asstring'div'渲染成哪个元素。