loading...

React Native - The aspectRatio Style Property

hrastnik profile image Mateo Hrastnik ・2 min read

A lot of React Native developers come from a web background. They're used to working with CSS and since React Native styling is basically a stripped down version of CSS, it means they quickly get used to it. There is however one feature in React Native that I find extremely useful which cannot be found on the web - so a lot of devs don't even realize it exists. I'm talking about the aspectRatio style prop.

So what is it? Why should you use it? Well, imagine this scenario. You want to create a scrollable screen filled with some images. All the images are perfectly square and take up the width of the screen.

So how do you get the height of the image? That's easy - you just import { Dimensions } from "react-native" and you use the window width for both the width and height, right? Like this:

function Card({ item: uri }) {
  const { width } = Dimensions.get("window");
  return (
    <Image
      source={{ uri }}
      style={{
        width: width,
        height: width
      }}
    />
  );
}

You use a FlatList to render the cards like this and even add a fancy separator.

<FlatList
  style={{ flex: 1 }}
  ItemSeparatorComponent={() => <View style={{ height: 16 }} />}
  data={images}
  renderItem={Card}
  keyExtractor={image => image}
/>

Full width image

So, this works fine, but let's say that sometime later, you have to do some tweaks and add some horizontal padding to the FlatList - here's what you'll get.

<FlatList
  style={{ flex: 1 }}
  contentContainerStyle={{ padding: 64 }} /* ADDED THIS */ 
  ItemSeparatorComponent={() => <View style={{ height: 16 }} />}
  data={images}
  renderItem={Card}
  keyExtractor={image => image}
/>

Our UI breaks. That's because the images are as wide as our screen, and with the padding they extend beyond the screen. The issue is we're using Dimensions to set the width - which we obviously don't want as it makes our components fragile.

So what we need to do is make the image take all available width and still keep the aspect ratio 1:1. The aspectRatio style prop does just that.

Simply use it like this:

function Card({ item: uri }) {
  return (
    <Image
      source={{ uri }}
      style={{
        width: "100%",
        aspectRatio: 1
      }}
    />
  );
}

If the parents View has it's alignItems style prop set to stretch (this is the default) you don't even have to specify width: "100%" as all the children will stretch to fill all the available width.

function Card({ item: uri }) {
  return (
    <Image
      source={{ uri }}
      style={{ aspectRatio: 1 }}
    />
  );
}

Here's the result.

Final product

Use aspectRatio wherever you can and avoid grabbing the window width using the Dimensions API. aspectRatio can make your components better adapt to change and in turn make your UI more stable.

There is one caveat - this doesn't (yet) work with react-native-web, so if you're using that, it's best to avoid it.

Discussion

pic
Editor guide
Collapse
uladzislaustuk profile image
Uladzislau

Thank you for article!