wuno
wuno

Reputation: 9865

How to center an image in React Native

Background

I have an image meant to be displayed while other content is loading.
I want it to be centered and look the same on all devices.

Problem

Currently, the image shows up at the top left.
I would like it to be centered – horizontally and vertically.

Question

What is the solution to make the image centered and have the right size?


The height of my image is 776 px, and the width is 600 px. I know I need to set the image size in the style sheet. From my understanding, I can use JSX to do this.

import React from 'react';
import { Image, StyleSheet, View } from 'react-native';

const logoImage = require('../assets/images/logo.jpg');

const LoadingScreen = () => (
  <View style={styles.container}>
    <Image style={styles.logo} source={logoImage} />
  </View>
);

const styles = StyleSheet.create({
  container: {
  },
  logo: {
    justifyContent: 'center',
    alignItems: 'center',
    width: 300,
    height: 400,
  },
});

export default LoadingScreen;

Upvotes: 32

Views: 126733

Answers (5)

What is the solution to make the image centered and have the right size?

The documentation for using Flexbox in React Native tells us why your attempt failed.

Justify content

justifyContent describes how to align children within the main axis of their container
(which by default is column-wise for React Native).

Align items

alignItems describes how to align children along the cross axis of their container.

Thus, setting alignItems and justifyContent on the <Image /> element affects the position of the children of the image.
But in your case, <Image /> doesn't have any children, so the effect is nil.

How to make your code work as intended

To style the image, we need to set alignItems and justifyContent for the parent of the image, which in your case is the <View /> element.
Assuming that <View /> is styled by container (and <Image /> by logo), the following style sheet settings will center the image in both directions. 1

import React from 'react';
import { Image, StyleSheet, View } from 'react-native';

const logoImage = { uri: 'https://i.sstatic.net/15jTl.png' };

export default function LoadingScreen() {
  return (
    <View style={styles.container}>
      <Image style={styles.logo} source={logoImage} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  logo: {
    width: 280,
    height: 260,
  },
});

The image is centered horizontally and vertically.

An alternative solution

Align self

alignSelf has the same options and effect as alignItems but instead of affecting the children within a container, you can apply this property to a single element.

Just set alignSelf on the image itself, instead of setting alignItems on its parent.

This method can be handy if the image should be centered, while there is text below the image that should be left-aligned.

Consider the example below.
In portrait mode, all content fits on the screen, and is centered horizontally and vertically.
In landscape mode, the image + text doesn't fit vertically. The whole image should be displayed when scrolling to the top, while all text should be displayed when scrolling to the bottom. 2

import React from 'react';
import { Image, ScrollView, StyleSheet, Text, View } from 'react-native';

const logoImage = { uri: 'https://i.sstatic.net/15jTl.png' };

export default function LoadingScreen() {
  return (
    <View style={styles.container}>
      <ScrollView contentContainerStyle={styles.scrollView}>
        <Image style={styles.logo} source={logoImage} />
        <Text>Here are some</Text>
        <Text>lines of text</Text>
        <Text>below the image.</Text>
        <Text> - - -</Text>
        <Text>I want the image</Text>
        <Text>to be centered,</Text>
        <Text>but this text</Text>
        <Text>to be left-aligned,</Text>
        <Text>not centered.</Text>
      </ScrollView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 8 },
  scrollView: { flexGrow: 1, justifyContent: 'center' },
  logo: { alignSelf: 'center', width: 280, height: 260 },
});

All text should be displayed when scrolling to the bottom.


1 The flex: 1 clause makes container span the whole screen height instead of just the image height.

2 To reproduce: download and unzip to some directory of your choice.
Switch to that directory and run npm install and then npm start.
(You'll also need an emulator or a physical device to run the application.)

Upvotes: 1

Akbar RG
Akbar RG

Reputation: 864

You need to set the style of <View> for justifyContent and alignItems for centering the <Image>.

Should be like this :

const LoadingScreen = () => (
<View style={styles.container}>
    <Image
        style={styles.logo}
        source={logo}
    />
</View>
);

const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  logo: {
    width: 300,
    height: 400,
  },
});

Or you can use alignSelf on the <Image> to make it center, but it will still need to add justifyContent on <View> to make it center vertically.

Upvotes: 73

user13868738
user13868738

Reputation:

Set in parent view:

justifycontent:center

And in child set:

alignself:center

Upvotes: 6

user13504866
user13504866

Reputation:

Set in view:

justifycontent:center

And in child:

alignself:center

And perform in task.

Upvotes: 9

justelouise
justelouise

Reputation: 770

The View container should have styling as

flexDirection: 'column'
justifyContent: 'center'
alignItems: 'center'
height: '100%'

The height makes sure it spans throughout the page, thus making the image become both vertically and horizontally aligned.

For the image size, I think using percentage will do the trick instead of defining definite width/height.

Upvotes: 21

Related Questions