0Pricing
React Native Academy · レッスン

Flexboxの方向、justifyContent、alignItems

flexDirection、justifyContent、alignItemsを使ってView内の子要素の配置を制御し、要素を中央揃えにしたり、間隔を空けたり、整列させたりします

「Flexboxの方向、justifyContent、alignItems」はCoddyKit上の無料React Native Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Native Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Native Academyコースには全4レッスンが含まれています。

このレッスンの一部はまだ翻訳されておらず、英語で表示されています。

Flexbox Is the Default Layout System

React Native uses Flexbox as its layout algorithm for every View component — there is no block or inline layout like in CSS. Every View is automatically a Flex container, meaning its children are positioned according to Flexbox rules by default. The key difference from web CSS Flexbox is that React Native's default flexDirection is 'column', not 'row' like on the web. This means children stack vertically by default, which matches how most mobile screens are laid out.

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

export default function DefaultFlex() {
  return (
    // No flexDirection needed — 'column' is the default
    <View style={styles.container}>
      <View style={styles.box1} />
      <View style={styles.box2} />
      <View style={styles.box3} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#f5f5f5', padding: 16 },
  box1: { height: 60, backgroundColor: '#ff6b6b', marginBottom: 8 },
  box2: { height: 60, backgroundColor: '#4f86f7', marginBottom: 8 },
  box3: { height: 60, backgroundColor: '#51cf66' },
});

flexDirection: row vs column

flexDirection sets the main axis of the Flex container. With 'column' (default), children stack top to bottom. With 'row', children sit left to right. The values 'column-reverse' and 'row-reverse' reverse the order. Changing flexDirection also changes which axis justifyContent and alignItems affect — justifyContent always works along the main axis, and alignItems along the cross axis. This is the single most impactful Flexbox property to understand.

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

export default function DirectionDemo() {
  return (
    <View style={{ flex: 1, gap: 16, padding: 16 }}>
      {/* Column: children stack vertically (default) */}
      <View style={{ flexDirection: 'column', height: 120, backgroundColor: '#f0f0f0' }}>
        <View style={styles.box} />
        <View style={styles.box} />
      </View>

      {/* Row: children sit side by side */}
      <View style={{ flexDirection: 'row', height: 60, backgroundColor: '#f0f0f0' }}>
        <View style={styles.box} />
        <View style={styles.box} />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  box: { width: 50, height: 50, backgroundColor: '#4f86f7', margin: 4 },
});

justifyContent: Aligning Along the Main Axis

justifyContent controls how children are distributed along the main axis (vertical for column, horizontal for row). The most useful values are: 'flex-start' (pack at start, default), 'flex-end' (pack at end), 'center' (center the group), 'space-between' (first and last touch the edges, equal gaps between others), 'space-around' (equal space around each child), and 'space-evenly' (equal space including edges). 'space-between' is particularly common for navigation bars and action button rows.

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

export default function SpaceBetween() {
  return (
    <View style={styles.row}>
      <Text style={styles.tab}>Home</Text>
      <Text style={styles.tab}>Search</Text>
      <Text style={styles.tab}>Profile</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
    justifyContent: 'space-between', // distribute across full width
    paddingHorizontal: 24,
    paddingVertical: 16,
    backgroundColor: '#fff',
    borderTopWidth: 1,
    borderTopColor: '#eee',
  },
  tab: { fontSize: 14, color: '#666' },
});

alignItems: Aligning Along the Cross Axis

alignItems controls how children are positioned on the cross axis (perpendicular to the main axis). For a column container it aligns children horizontally; for a row container it aligns them vertically. Values: 'flex-start' (default for column on Android, items hug the start), 'flex-end', 'center', and 'stretch' (items expand to fill the cross axis — this is the default on iOS and makes sense for column layouts where you want full-width children). 'baseline' aligns text baselines of children.

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

export default function AlignDemo() {
  return (
    <View style={styles.container}>
      {/* Row: alignItems centers children vertically */}
      <View style={styles.row}>
        <Text style={styles.smallText}>Small</Text>
        <Text style={styles.largeText}>LARGE</Text>
        <Text style={styles.smallText}>Small</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 20 },
  row: {
    flexDirection: 'row',
    alignItems: 'center', // vertically center all items
    backgroundColor: '#e8f0fe',
    padding: 16,
    borderRadius: 8,
  },
  smallText: { fontSize: 12, color: '#666', marginHorizontal: 8 },
  largeText: { fontSize: 28, fontWeight: 'bold', color: '#111', marginHorizontal: 8 },
});

Centering Content with flex, justify, and align

A very common pattern is centering content both vertically and horizontally — for splash screens, empty states, or loading indicators. Set the container to flex: 1 so it fills available space, then apply justifyContent: 'center' and alignItems: 'center'. Since the default flexDirection is column, this centers children in the middle of the screen both vertically and horizontally. This three-property combination is probably the most-used layout recipe in React Native.

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

export default function CenteredScreen() {
  return (
    <View style={styles.container}>
      <Text style={styles.emoji}>🎯</Text>
      <Text style={styles.title}>Nothing here yet</Text>
      <Text style={styles.subtitle}>Add your first item to get started</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center', // vertical center (column main axis)
    alignItems: 'center',     // horizontal center (column cross axis)
    backgroundColor: '#f8f9fa',
  },
  emoji: { fontSize: 56, marginBottom: 16 },
  title: { fontSize: 22, fontWeight: 'bold', color: '#333' },
  subtitle: { fontSize: 14, color: '#999', marginTop: 8, textAlign: 'center' },
});

alignSelf: Overriding Cross-Axis Alignment

alignSelf overrides the parent's alignItems for a specific child. It accepts the same values as alignItems: 'auto' (use parent's setting), 'flex-start', 'flex-end', 'center', and 'stretch'. This is useful when most siblings share one alignment but one child needs different treatment — for example, a row of icons where one is larger and should align to the top while the others center. Use alignSelf sparingly; it's more maintainable to adjust the parent's alignItems and use wrapper Views when needed.

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

export default function AlignSelfExample() {
  return (
    <View style={styles.row}>
      <View style={styles.boxSmall} />
      {/* This box aligns to flex-end independently */}
      <View style={[styles.boxSmall, { alignSelf: 'flex-end', backgroundColor: 'red' }]} />
      <View style={styles.boxSmall} />
    </View>
  );
}

const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
    alignItems: 'center', // default for siblings
    height: 100,
    backgroundColor: '#e8f0fe',
    padding: 8,
    gap: 8,
  },
  boxSmall: { width: 50, height: 50, backgroundColor: '#4f86f7', borderRadius: 6 },
});

gap, rowGap, and columnGap

Instead of adding margin to each child, use gap on the container to set uniform spacing between flex children. gap sets both row and column gaps, while rowGap and columnGap control them independently. This eliminates the need for marginBottom on all but the last child, or the hack of adding negative margin to the container. Gap support was added in React Native 0.71 (available in Expo SDK 48+), so check your RN version before using it in older projects.

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

export default function GapExample() {
  return (
    <View style={styles.container}>
      {[1, 2, 3, 4].map(n => (
        <View key={n} style={styles.card} />
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 12,           // equal gap between all children
    padding: 16,
    backgroundColor: '#f5f5f5',
  },
  card: {
    width: '47%',      // two columns
    height: 100,
    backgroundColor: '#4f86f7',
    borderRadius: 10,
  },
});

flexWrap: Wrapping Children to Next Lines

By default, flex children shrink to fit in a single line and never wrap. Set flexWrap: 'wrap' on the container to let children wrap to the next row (for row direction) or next column (for column direction) when they run out of space. This is the foundation for tag clouds, grid-like layouts with percentage widths, and any UI where items should flow onto the next line naturally. 'nowrap' is the default; 'wrap-reverse' wraps in the opposite direction.

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

const tags = ['React Native', 'Mobile', 'iOS', 'Android', 'JavaScript', 'Flexbox', 'Expo'];

export default function TagCloud() {
  return (
    <View style={styles.container}>
      {tags.map(tag => (
        <View key={tag} style={styles.tag}>
          <Text style={styles.tagText}>{tag}</Text>
        </View>
      ))}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, padding: 16 },
  tag: { backgroundColor: '#e8f0fe', paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16 },
  tagText: { color: '#4f86f7', fontSize: 13, fontWeight: '500' },
});

A Practical Header Layout

Apply your Flexbox knowledge to build a common mobile app pattern: a navigation header with a back button on the left, a centered title, and a menu icon on the right. Use flexDirection: 'row' and alignItems: 'center' on the header container. Give the title flex: 1 so it expands to fill the remaining space and centers itself between the fixed-width side icons. This is cleaner than using position: 'absolute' for centering and handles varying title lengths correctly.

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';

export default function Header({ title, onBack, onMenu }) {
  return (
    <View style={styles.header}>
      <TouchableOpacity style={styles.sideBtn} onPress={onBack}>
        <Text style={styles.icon}>←</Text>
      </TouchableOpacity>

      <Text style={styles.title} numberOfLines={1}>{title}</Text>

      <TouchableOpacity style={styles.sideBtn} onPress={onMenu}>
        <Text style={styles.icon}>⋯</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 16,
    paddingVertical: 12,
    backgroundColor: '#fff',
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderBottomColor: '#ddd',
  },
  sideBtn: { width: 40, alignItems: 'center' },
  title: { flex: 1, fontSize: 18, fontWeight: '600', color: '#111', textAlign: 'center' },
  icon: { fontSize: 22, color: '#333' },
});

Debugging Flexbox Layouts

Flexbox bugs are common during layout development. Useful debugging techniques: add a temporary backgroundColor to each View to make its boundaries visible, use React DevTools to inspect the computed layout in the component tree, check whether flex: 1 is missing from ancestor containers (a container without flex: 1 collapses to zero height, making its children invisible), and verify that flexDirection is the value you intend (remember, React Native defaults to column, not row). Removing all styles and adding them back one by one is a reliable way to isolate layout bugs.

// Debug technique: color-code your Views temporarily
const debugStyles = StyleSheet.create({
  container: { flex: 1, backgroundColor: 'rgba(255,0,0,0.1)' }, // red tint
  inner: { backgroundColor: 'rgba(0,0,255,0.1)' },              // blue tint
  text: { backgroundColor: 'rgba(0,255,0,0.1)' },               // green tint
});

// Then you can see exactly where each View starts and ends
// Remove these debug colors before shipping!

Row with Icon, Text, and Action

One of the most common mobile UI patterns is a list row with an icon on the left, text in the middle, and an action button on the right. Implement it with flexDirection: 'row' on the container, alignItems: 'center' to vertically align all children, a fixed-size icon View on the left, a flex: 1 text area in the middle (so it expands to fill available space), and a fixed-size action button on the right. This pattern appears in settings screens, contact lists, and any data-dense table view in mobile apps.

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';

export default function SettingsRow({ icon, label, subtitle, onPress }) {
  return (
    <TouchableOpacity style={styles.row} onPress={onPress}>
      {/* Left: icon */}
      <View style={styles.iconContainer}>
        <Text style={{ fontSize: 22 }}>{icon}</Text>
      </View>

      {/* Middle: text content — flex: 1 fills space */}
      <View style={{ flex: 1 }}>
        <Text style={styles.label} numberOfLines={1}>{label}</Text>
        {subtitle && <Text style={styles.subtitle} numberOfLines={1}>{subtitle}</Text>}
      </View>

      {/* Right: chevron */}
      <Text style={styles.chevron}>›</Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  row: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#fff', gap: 12 },
  iconContainer: { width: 36, height: 36, borderRadius: 8, backgroundColor: '#f0f4ff', alignItems: 'center', justifyContent: 'center' },
  label: { fontSize: 16, color: '#222' },
  subtitle: { fontSize: 13, color: '#999', marginTop: 2 },
  chevron: { fontSize: 22, color: '#ccc', fontWeight: '300' },
});

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: flexDirection sets the main axis (column by default in React Native, not row), justifyContent distributes children along the main axis, and alignItems aligns children on the cross axis. Next up we explore the flex property and responsive sizing across screen dimensions.

よくある質問

「Flexboxの方向、justifyContent、alignItems」レッスンは無料ですか?

はい。「Flexboxの方向、justifyContent、alignItems」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Native Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Native Academyコースには全4レッスンが含まれています。

「Flexboxの方向、justifyContent、alignItems」で何を学びますか?

flexDirection、justifyContent、alignItemsを使ってView内の子要素の配置を制御し、要素を中央揃えにしたり、間隔を空けたり、整列させたりします ブラウザで直接実行するハンズオンコードでReact Native Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

React Native Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのReact Native Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「Flexboxの方向、justifyContent、alignItems」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このReact Native Academyレッスンでコードを書いて実行できますか?

はい。すべてのReact Native Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. StyleSheet.createとインラインスタイル
  2. Flexboxの方向、justifyContent、alignItems
  3. flex、flexGrow、レスポンシブなサイズ設定
  4. レスポンシブなカードグリッドの構築
← React Native Academyに戻る