Flexbox в React Native: руководство по гибким макетам
Flexbox — это модель раскладки в CSS (и в React Native), которая позволяет управлять расположением дочерних элементов внутри контейнера. В React Native Flexbox включён по умолчанию, поэтому его удобно использовать для адаптивных и предсказуемых интерфейсов на мобильных устройствах.
Зачем это читать
- Узнаете, чем отличается поведение Flexbox в React Native от web-версии.
- Получите рабочие примеры кода с корректными JSX-структурами.
- Возьмёте на вооружение чек-листы, тесты и шпаргалку для быстрого применения в проекте.
Ключевые отличия Flexbox в React Native и в вебе
Если вы привыкли к Flexbox в браузере, обратите внимание на важные отличия при переносе знаний в React Native:
- flexDirection по умолчанию — column в React Native (в вебе — row).
- alignContent по умолчанию — flex-start в React Native (в вебе — stretch).
- flexShrink по умолчанию — 0 в React Native (в вебе — 1).
Эти отличия влияют на расположение элементов и на то, как они занимают доступное пространство. Помните: в React Native контейнеры уже «flex» по умолчанию — указывать display: ‘flex’ не нужно.
1. Свойство flex — как распределяется пространство
Свойство flex принимает целое неотрицательное значение и указывает относительную долю доступного пространства, которую займёт элемент.
Пример: один компонент занимает весь экран
import React from "react";
import { View } from "react-native";
export default function App() {
return (
);
}Два элемента с flex:1 и flex:3
import React from "react";
import { View } from "react-native";
export default function App() {
return (
);
}Пояснение: значения суммируются (1 + 3 = 4), и каждый элемент получает свою долю от доступного пространства.
2. flexDirection — основной и вспомогательный оси
flexDirection определяет, вдоль какой оси располагаются дочерние элементы:
- column — вертикальная (по умолчанию в RN), элементы идут сверху вниз;
- row — горизонтальная, элементы идут слева направо (в LTR);
- column-reverse и row-reverse — те же оси, но в обратном порядке.
Пример: три квадрата в ряд
import React from "react";
import { StyleSheet, View } from "react-native";
const styles = StyleSheet.create({
container: {
backgroundColor: "#00FF00",
flex: 1,
alignItems: "center",
flexDirection: "row",
},
square: {
backgroundColor: "#FF0000",
width: 98,
height: 98,
margin: 4,
},
});
export default function App() {
return (
);
}Примечание: при переходе между column и row помните, что главная ось меняется — это напрямую влияет на поведение justifyContent.
3. justifyContent — выравнивание по главной оси
justifyContent управляет распределением пространства вдоль главной оси (той, что задана flexDirection). Варианты:
- flex-start — с начала оси;
- flex-end — в конец;
- center — по центру;
- space-between — ровные промежутки между элементами;
- space-around — промежутки вокруг элементов;
- space-evenly — равномерное распределение (равные пробелы между и вокруг).
Пример: три квадрата, выровненные в начале по горизонтали
import React from "react";
import { StyleSheet, View } from "react-native";
const styles = StyleSheet.create({
container: {
backgroundColor: "#00FF00",
flex: 1,
justifyContent: "flex-start",
flexDirection: "row",
},
square: {
backgroundColor: "#FF0000",
width: 98,
height: 98,
margin: 6,
},
});
export default function App() {
return (
);
}Если flexDirection = ‘column’, то justifyContent будет управлять вертикальным распределением.
Пример центрирования по вертикали (flexDirection: ‘column’)
4. alignItems — выравнивание по вторичной оси
alignItems управляет выравниванием вдоль вторичной оси (перпендикулярной главной). Возможные значения:
- flex-start
- flex-end
- center
- baseline
- stretch (поведение stretch в RN может отличаться от веба в зависимости от контента)
Пример: выравнивание по началу вторичной оси при row
import React from "react";
import { StyleSheet, View } from "react-native";
const styles = StyleSheet.create({
container: {
backgroundColor: "#00FF00",
flex: 1,
alignItems: "flex-start",
flexDirection: "row",
},
square: {
backgroundColor: "#FF0000",
width: 98,
height: 98,
margin: 6,
},
});
export default function App() {
return (
);
}Если flexDirection = ‘column’ и alignItems = ‘center’, элементы будут вертикально расположены и центрированы по горизонтали.
5. alignSelf — переопределение выравнивания для одного элемента
alignSelf позволяет задать выравнивание конкретного дочернего элемента, переопределив alignItems контейнера. Значения совпадают с alignItems.
Пример: один элемент с alignSelf, остальным задано alignItems
import React from "react";
import { StyleSheet, View } from "react-native";
const styles = StyleSheet.create({
container: {
backgroundColor: "#00FF00",
flex: 1,
alignItems: "center",
justifyContent: "center",
flexDirection: "row",
},
square: {
backgroundColor: "#FF0000",
width: 98,
height: 98,
margin: 6,
},
});
export default function App() {
return (
);
}Дополнительные свойства
- flexWrap: управляет переносом элементов при переполнении контейнера. Значения: nowrap (по умолчанию) и wrap.
- gap: добавляет промежутки между элементами. В RN поддержка gap может зависеть от версии; можно заменить margin в дочерних элементах.
Шпаргалка: быстрый обзор свойств Flexbox
| Свойство | Возможные значения | Что делает |
|---|---|---|
| flex | число >= 0 | Относительная доля доступного пространства |
| flexDirection | row, column, row-reverse, column-reverse | Главная ось контейнера |
| justifyContent | flex-start, flex-end, center, space-between, space-around, space-evenly | Выравнивание по главной оси |
| alignItems | flex-start, flex-end, center, baseline, stretch | Выравнивание по вторичной оси |
| alignSelf | flex-start, flex-end, center, baseline | Переопределяет alignItems для одного элемента |
| flexWrap | nowrap, wrap | Перенос строк/столбцов при переполнении |
| gap | любое числовое значение (px, dp) | Расстояние между элементами (поддержка зависит от окружения) |
Ментальные модели и эвристики
- Представьте контейнер как «основную ось» (main axis) и «вторичную ось» (cross axis). flexDirection определяет, какая ось главная.
- Всегда спрашивайте: «По какой оси я хочу распределять пространство?» — ответ выбирает между justifyContent и alignItems.
- Для быстрого макета используйте flex для распределения пустого пространства, размеры (width/height) — для фиксированных блоков.
Когда Flexbox может не подойти (контрпримеры)
- Сложные двумерные сетки (rows × columns) с пересекающимися ячейками лучше строить с помощью grid-подхода на вебе. В React Native CSS Grid не поддерживается, и для подобных сеток придётся писать собственный layout или использовать композицию вложенных контейнеров.
- Если нужен pixel-perfect макет с абсолютным наложением элементов (например, SVG-слои или точное позиционирование), удобнее использовать position: ‘absolute’ и координаты.
- Если нужно управлять макетом в зависимости от текста и сложных типографических правил, иногда проще использовать измерения (onLayout) и управлять размерами программно.
Альтернативные подходы и движки
- Подложка React Native — это движок Yoga, реализующий Flexbox. Он оптимизирован под мобильные устройства и отличается от браузерной реализации.
- Для специфичных случаев используйте абсолютное позиционирование (position: ‘absolute’) или сторонние библиотеки для layout’а; но помните: это добавляет сложность и может ухудшить адаптивность.
Чек-листы (роль-по-роли)
Для разработчика:
- Проверил, что flexDirection задан корректно (row vs column).
- Использую flex только для того, чтобы распределить оставшееся пространство.
- Не полагаюсь на gap если целевая версия RN его не поддерживает; применяю margin в дочерних элементах.
- Протестировал на разных экранах (портрет/ландшафт).
Для дизайнера:
- Указал, какие элементы должны быть фиксированного размера, а какие гибкими.
- Предоставил макеты для разных размеров экрана.
Для QA:
- Проверил расположение элементов на телефонах с узким экраном.
- Проверил, как ведёт себя контейнер при изменении текста (длинные строки, локализация).
- Проверил переносы при flexWrap: wrap и nowrap.
Критерии приёмки (основные тесты)
- Два компонента с flex:1 и flex:3 корректно занимают 25% и 75% высоты (при column) или ширины (при row).
- При justifyContent: ‘center’ элементы центрируются по главной оси на всех целевых экранах.
- alignSelf переопределяет alignItems только для элемента с указанным alignSelf.
- При flexWrap: ‘wrap’ дочерние элементы переходят на новую строку; при nowrap — остаются на одной линии и могут выйти за пределы контейнера.
Примеры «быстро и практично»: шаблоны макетов
Шапка + контент + футер (вертикальная компоновка)
import React from "react";
import { View, Text, StyleSheet } from "react-native";
const styles = StyleSheet.create({
page: { flex: 1, flexDirection: "column" },
header: { height: 60, backgroundColor: "#222" },
content: { flex: 1, backgroundColor: "#fff" },
footer: { height: 50, backgroundColor: "#333" },
});
export default function Page() {
return (
Header
Content
Footer
);
}Ряд иконок с равными промежутками
Советы по локализации и адаптивности
- Тексты на других языках могут быть длиннее; не полагайтесь на фиксированные ширины для элементов с текстом.
- Проверяйте макет на самых «проблемных» языках (например, немецкий или русский) и учитывайте переносы.
- Для RTL (справа налево) используйте support для I18nManager и тестируйте flexDirection и порядок элементов.
Миграция и совместимость
- Flexbox в RN основан на Yoga — это означает консистентность между версиями RN, но синтаксис и поддержка некоторых свойств (например, gap) могут меняться. Проверяйте changelog целевой версии React Native.
Краткий глоссарий (1 строка)
- Главная ось — ось, вдоль которой размещаются элементы (определяется flexDirection).
- Вторичная ось — перпендикулярная главной оси.
- flex — относительная доля пространства элемента.
- justifyContent — выравнивание по главной оси.
- alignItems — выравнивание по вторичной оси.
FAQ
Нужно ли указывать display: ‘flex’ в React Native?
Нет. В React Native контейнеры уже используют модель Flexbox по умолчанию.
Почему мои элементы не переносятся на новую строку?
Убедитесь, что у контейнера задано flexWrap: ‘wrap’, иначе поведение по умолчанию — nowrap.
Как добиться равных отступов между элементами на старых версиях RN?
Если gap не поддерживается, используйте margin у дочерних элементов и корректируйте отрицательные внешние отступы у контейнера при необходимости.
Итог: Flexbox — это мощный и гибкий инструмент для построения макетов в React Native. Понимание главной и вторичной осей, а также свойств flex, justifyContent, alignItems и alignSelf позволяет создавать адаптивные интерфейсы, простые в поддержке. Используйте приведённые шаблоны, шпаргалку и чек-листы, чтобы ускорить разработку и тестирование.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone