Image is the workhorse of Pinterest. If you define Pinterest to be all about collecting ideas, then images are how we choose to represent those ideas. In response, we've added a few extra superpowers to the regular img tag to make it even more awesome.

also known as <img>, Picture, Photo

Figma:

Responsive:

Adaptive:

A11y:

Props

Component props
Name
Type
Default
alt
Required
string
-

Alt text read by screen readers. See MDN for more details.

naturalHeight
Required
number
-

Exact height of source image. See the Dimensions example for more details.

naturalWidth
Required
number
-

Exact width of source image. See the Dimensions example for more details.

src
Required
string
-

The URL for the image.

children
React.Node
-

Children content will be overlaid on the image. See the Overlay example for more details.

color
string
"transparent"

Used as a visual placeholder while the image is loading. See the Placeholders example for more details.

crossOrigin
"anonymous" | "use-credentials"
-

Specifies the CORS setting to use when retrieving the image. See MDN for more details.

decoding
"sync" | "async" | "auto"
-

Sends a hint to the browser specifying whether or not it is allowed to try to parallelize loading your image. See MDN for more details.

elementTiming
string
-

HTML attribute for performance profiling (see https://developer.mozilla.org/en-US/docs/Web/API/Element_timing_API). Note that it only works if the `fit` prop is not set to `"cover"` or `"contain"`.

fetchPriority
"high" | "low" | "auto"
"auto"

Priority hints provide developers a way to indicate a resource's relative importance to the browser, allowing more control over the order resources are loaded (only available via Chrome Origin Trial). `"high"`: the developer considers the resource to be high priority. `"low"`: the developer considers the resource to be low priority. `auto` the developer does not indicate a preference.
Note that this feature is currently experimental; please see the attribute spec for more details.

fit
"cover" | "contain" | "none"
"none"

Sets how the image is resized to fit its container. See the Fit example for more details.
Note: this doesn't work with srcSet or sizes.

loading
"eager" | "lazy" | "auto"
"auto"

Controls if loading the image should be deferred when it's off-screen. `"lazy"` defers the load until the image or iframe reaches a distance threshold from the viewport. `"eager"` loads the resource immediately. `"auto"` uses the default behavior, which is to eagerly load the resource. See the Lazy example for more details.

onError
({ event: SyntheticEvent<HTMLImageElement> }) => void
-

Callback fired when the image loading has an error.

onLoad
({ event: SyntheticEvent<HTMLImageElement> }) => void
-

Callback fired when the image successfully loads.

role
"img" | "presentation"
-

When Image is used purely as a presentational or decorative addition, the `role` should be set to "presentation" for better accessibility. See the Presentational Images with Role example for more details.

sizes
string
-

A comma-separated list of one or more strings indicating a set of source sizes.

srcSet
string
-

A comma-separated list of one or more strings indicating a set of possible image sources for the user agent to use.

Accessibility

Presentational Images with Role

Sometimes Images are purely presentational. For example, an Image used above an article title may be used to draw people's attention visually, but doesn't add any additional information or context about the article. In this case, the role should be set to "presentation" in order to inform screen readers and other assistive technology that this image does not need alternative text or any additional label.

import { Box, Heading, Image } from 'gestalt';

export default function Example() {
  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Box
        alignContent="center"
        borderStyle="sm"
        direction="column"
        display="flex"
        height={300}
        justifyContent="between"
        width={300}
      >
        <Box height={200} width="100%">
          <Image
            alt=""
            color="#000"
            fit="cover"
            naturalHeight={1}
            naturalWidth={1}
            role="presentation"
            src="https://i.ibb.co/FY2MKr5/stock6.jpg"
          />
        </Box>
        <Heading align="center" size="600">
          Article Title
        </Heading>
      </Box>
    </Box>
  );
}

Variants

Dimensions

One thing that might be unusual is that the width and the height of the component are required, yet the image will scale to the size of its container.

This is so that the placeholder's size can be calculated before the image has rendered.

While the exact dimensions supplied aren't used (only the ratio between them is considered), you should always try to supply the exact dimensions of the source image requested.

Placeholders

The color you pass into Image will be used to fill the placeholder that shows up as an image loads. The example shown contains an image with a transparent background which allows you to visualize the placeholder color. When Mask is used to create rounded corners on Image, the placeholder color may leak through on the corners. To prevent this, remove the placeholder color."

import { Box, Column, Image } from 'gestalt';
import { TOKEN_COLOR_BACKGROUND_SHOPPING } from 'gestalt-design-tokens';

export default function Example() {
  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      {['rgb(111, 91, 77)', 'black', TOKEN_COLOR_BACKGROUND_SHOPPING].map(
        (color) => (
          <Column key={color} span={3}>
            <Image
              alt="example.com"
              color={color}
              naturalHeight={1}
              naturalWidth={1}
              src="https://d3cy9zhslanhfa.cloudfront.net/media/BBEEEEC7-E954-4223-B5A061E37D0C03E2/CE43CF95-DE36-465B-956EFB21C9CC9C04/webimage-0311D236-89DC-4404-9D9B1452C865159C.png"
            />
          </Column>
        )
      )}
    </Box>
  );
}

Overlay

You can overlay content on an Image by passing it children.

import { Box, Button, Flex, Image, Text } from 'gestalt';

export default function Example() {
  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Box height={266} width={200}>
        <Image
          alt="Tropic greens: The taste of Petrol and Porcelain | Interior design, Vintage Sets and Unique Pieces agave"
          color="rgb(231, 186, 176)"
          naturalHeight={751}
          naturalWidth={564}
          src="https://i.ibb.co/7bQQYkX/stock2.jpg"
        >
          <Box height="100%" padding={3}>
            <Flex direction="column" height="100%" justifyContent="between">
              <Text color="dark" weight="bold">
                Tropic greens: The taste of Petrol and Porcelain
              </Text>

              <Button
                color="red"
                onClick={
                  () => alert('Click!') /* eslint-disable-line no-alert */
                }
                text="Save this Pin"
              />
            </Flex>
          </Box>
        </Image>
      </Box>
    </Box>
  );
}

Fit

In some cases, you may want to scale an image to fit into its container. To achieve that, you can set fit to either "cover" or "contain", depending on the effect you wish to achieve.

"contain": This makes it so that the image is "contained" within its container. This means that the image is resized appropriately such that the entire image can fit in the container, while maintaining its aspect ratio (think letterbox);

<Image alt="..." color="#000" fit="contain" src="..." />

"cover": This does the opposite of "contain" and tries to scale the image as large as possible so that the entire container is occupied, while maintaining the aspect ratio of the image.

<Image alt="..." color="#000" fit="cover" src="..." />

Notes:

  • When using "cover"/"contain", naturalHeight and naturalWidth are ignored since the aspect ratio is handled by the browser.
  • In order for "cover"/"contain" to work properly, the container must have some sort of implicit height.
import { Box, Flex, Image, Text } from 'gestalt';

export default function Example() {
  return (
    <Box padding={8}>
      <Flex
        alignItems="start"
        direction="column"
        gap={{ column: 6, row: 0 }}
        wrap
      >
        <Flex direction="column" gap={2}>
          <Text size="300" weight="bold">
            Square content: contain vs cover
          </Text>
          <Flex gap={8} justifyContent="around" wrap>
            <Box color="dark" height={200} width={200}>
              <Image
                alt="square"
                color="#000"
                fit="contain"
                naturalHeight={1}
                naturalWidth={1}
                src="https://i.ibb.co/d0pQsJz/stock3.jpg"
              />
            </Box>
            <Box color="dark" height={200} width={200}>
              <Image
                alt="square"
                color="#000"
                fit="cover"
                naturalHeight={1}
                naturalWidth={1}
                src="https://i.ibb.co/d0pQsJz/stock3.jpg"
              />
            </Box>
          </Flex>
        </Flex>

        <Flex direction="column" gap={{ column: 2, row: 0 }}>
          <Text size="300" weight="bold">
            Wide content: contain vs cover
          </Text>
          <Flex gap={8} justifyContent="around" wrap>
            <Box color="dark" height={200} width={200}>
              <Image
                alt="wide"
                color="#000"
                fit="contain"
                naturalHeight={1}
                naturalWidth={1}
                src="https://i.ibb.co/SB0pXgS/stock4.jpg"
              />
            </Box>
            <Box color="dark" height={200} width={200}>
              <Image
                alt="wide"
                color="#000"
                fit="cover"
                naturalHeight={1}
                naturalWidth={1}
                src="https://i.ibb.co/SB0pXgS/stock4.jpg"
              />
            </Box>
          </Flex>
        </Flex>

        <Flex direction="column" gap={{ column: 2, row: 0 }}>
          <Text size="300" weight="bold">
            Tall content: contain vs cover
          </Text>
          <Flex gap={8} justifyContent="around" wrap>
            <Box color="dark" height={200} width={200}>
              <Image
                alt="tall"
                color="#000"
                fit="contain"
                naturalHeight={1}
                naturalWidth={1}
                src="https://i.ibb.co/jVR29XV/stock5.jpg"
              />
            </Box>
            <Box color="dark" height={200} width={200}>
              <Image
                alt="tall"
                color="#000"
                fit="cover"
                naturalHeight={1}
                naturalWidth={1}
                src="https://i.ibb.co/jVR29XV/stock5.jpg"
              />
            </Box>
          </Flex>
        </Flex>
      </Flex>
    </Box>
  );
}

Lazy

You can delay loading images that are off-screen with the loading attribute. See MDN for more details.

import { Box, Image } from 'gestalt';

export default function Example() {
  return (
    <Box
      alignItems="center"
      display="flex"
      height="100%"
      justifyContent="center"
      padding={8}
    >
      <Box column={6} paddingX={2}>
        <Image
          alt="Tropic greens: The taste of Petrol and Porcelain | Interior design, Vintage Sets and Unique Pieces agave"
          color="rgb(231, 186, 176)"
          loading="lazy"
          naturalHeight={496}
          naturalWidth={496}
          src="https://i.ibb.co/FY2MKr5/stock6.jpg"
        />
      </Box>
    </Box>
  );
}

Component quality checklist

Component quality checklist
Quality item
Status
Status description
Figma Library
Component is not currently available in Figma.
Responsive Web
Ready
Component responds to changing viewport sizes in web and mobile web.