The ResponsiveItem component can be used to make images, videos, iframes, or
other media elements responsive within a relative container with built-in
support for forcing specific aspect ratios when the item's size is unknown.
See the objectFit class name utility function for a simpler implementation.
This example will show how to create responsive images by wrapping the
<img> element in the ResponsiveItem. The default behavior
will be to respect the <img> dimensions but scale them down into the
container's width.
Try resizing the browser or updating the columns constant in the next
demo to see how it works.
import { Box } from "@react-md/core/box/Box";
import { type BoxOptions } from "@react-md/core/box/styles";
import { Card } from "@react-md/core/card/Card";
import { ResponsiveItem } from "@react-md/core/responsive-item/ResponsiveItem";
import { type ReactElement } from "react";
export default function SimpleExample(): ReactElement {
return (
<Box align="stretch" grid fullWidth gridColumns={columns}>
<Card align="center" justify="center">
<ResponsiveItem>
<img src="https://picsum.photos/200/300?image=30" alt="" />
</ResponsiveItem>
</Card>
<Card align="center" justify="center">
<ResponsiveItem>
<img src="https://picsum.photos/300/200?image=3" alt="" />
</ResponsiveItem>
</Card>
<Card align="center" justify="center">
<ResponsiveItem>
<img src="https://picsum.photos/300?image=1008" alt="" />
</ResponsiveItem>
</Card>
<Card align="center" justify="center">
<ResponsiveItem>
<img src="https://picsum.photos/100/110?image=233" alt="" />
</ResponsiveItem>
</Card>
</Box>
);
}
let columns: BoxOptions["gridColumns"];
// columns = "fit";
// columns = "fill";
// columns = 2;
When dealing with unknown content, the aspect ratio can be forced using
the aspectRatio prop. The default aspect ratios are:
16-9, 4-3, and 1-1.
import { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { ResponsiveItem } from "@react-md/core/responsive-item/ResponsiveItem";
import { type ReactElement } from "react";
export default function ForceAspectRatio(): ReactElement {
return (
<Box grid fullWidth>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/400/300?image=3" alt="" />
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="4-3">
<img src="https://picsum.photos/400/300?image=3" alt="" />
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="1-1">
<img src="https://picsum.photos/300/400?image=3" alt="" />
</ResponsiveItem>
</Card>
</Box>
);
}
When a YouTube video should be rendered in an iframe, either the height and
width need to be provided to the iframe or an aspect ratio must be set on
the ResponsiveItem to work correctly.
import { Card } from "@react-md/core/card/Card";
import { ResponsiveItem } from "@react-md/core/responsive-item/ResponsiveItem";
import { type ReactElement } from "react";
export default function YouTubeIFrame(): ReactElement {
return (
<Card fullWidth>
<ResponsiveItem aspectRatio="16-9">
<iframe
src="https://www.youtube.com/embed/kyAn3fSs8_A"
allowFullScreen
title="Archer - Highway To The Dangerzone"
style={{ border: 0 }}
/>
</ResponsiveItem>
</Card>
);
}
The generated aspect ratios are configured by the
core.$responsive-item-aspect-ratios Sass variable which is a map of
x-y: x y.
It can sometimes be useful to add an overlay above the responsive item to cover
it with a title, description, or other information. Use the ResponsiveItemOverlay
component to add this overlayh within a ResponsiveItem.
import { Box } from "@react-md/core/box/Box";
import { box } from "@react-md/core/box/styles";
import { button } from "@react-md/core/button/styles";
import { Card } from "@react-md/core/card/Card";
import { ResponsiveItem } from "@react-md/core/responsive-item/ResponsiveItem";
import { ResponsiveItemOverlay } from "@react-md/core/responsive-item/ResponsiveItemOverlay";
import { Typography } from "@react-md/core/typography/Typography";
import InfoOutlineIcon from "@react-md/material-icons/InfoOutlineIcon";
import { type ReactElement } from "react";
export default function ResponsiveItemOverlayExample(): ReactElement {
return (
<Box grid fullWidth>
<Card>
<ResponsiveItem>
<img
src="https://picsum.photos/800/800?image=432"
alt="green trees, grass, and lake at sunrise"
/>
<ResponsiveItemOverlay
className={box({ justify: "space-between", disablePadding: true })}
>
<Typography type="headline-5" margin="none">
Photo by: Michael Hull
</Typography>
<a
aria-label="Unsplash photo source"
rel="noreferrer"
href="https://unsplash.com/photos/photo-of-green-trees-grass-and-lake-at-sunrise-vuWB5mGu5wE"
target="_blank"
className={button({ buttonType: "icon" })}
>
<InfoOutlineIcon />
</a>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
</Box>
);
}
The ResponsiveItemOverlay supports the following positions:
toprightbottom (default)leftmiddle - vertically centeredcenter - horizontally centeredabsolute-center - horizontally and vertically centeredimport { Box } from "@react-md/core/box/Box";
import { Card } from "@react-md/core/card/Card";
import { ResponsiveItem } from "@react-md/core/responsive-item/ResponsiveItem";
import { ResponsiveItemOverlay } from "@react-md/core/responsive-item/ResponsiveItemOverlay";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
export default function OverlayPositions(): ReactElement {
return (
<Box grid fullWidth gridColumns={1}>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="top">
<Typography type="headline-5" margin="none">
Top
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="right">
<Typography type="headline-5" margin="none">
Right
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="bottom">
<Typography type="headline-5" margin="none">
Bottom (default)
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="left">
<Typography type="headline-5" margin="none">
Left
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="middle">
<Typography type="headline-5" margin="none" textAlign="center">
Middle
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="center">
<Typography type="headline-5" margin="none" textAlign="center">
Center
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
<Card>
<ResponsiveItem aspectRatio="16-9">
<img src="https://picsum.photos/600/600?image=404" alt="" />
<ResponsiveItemOverlay position="absolute-center">
<Typography type="headline-5" margin="none" textAlign="center">
Absolute Center
</Typography>
</ResponsiveItemOverlay>
</ResponsiveItem>
</Card>
</Box>
);
}
The global overlay styles can be configured by changing the following sass variables:
Otherwise, custom styles can be provided using the className prop like normal.