Урок 04

Стили и Flexbox

Flexbox в React Native работает всегда — нет display: block или display: inline. Все контейнеры — flex по умолчанию.

Отличия от CSS

  • Flexbox всегда включён — не нужно display: flex
  • flexDirection по умолчанию column, а не row
  • Нет % в большинстве случаев — используются числа или flex
  • Нет px — только числа

flexDirection

<View style={{ flexDirection: 'column' }}>  {/* по умолчанию */}
    <View style={styles.box} />
    <View style={styles.box} />
</View>

<View style={{ flexDirection: 'row' }}>
    <View style={styles.box} />
    <View style={styles.box} />
</View>

justifyContent

Распределение по главной оси:

justifyContent: 'flex-start'    // в начало
justifyContent: 'flex-end'      // в конец
justifyContent: 'center'        // по центру
justifyContent: 'space-between' // равные промежутки, крайние у краёв
justifyContent: 'space-around'  // равные промежутки вокруг
justifyContent: 'space-evenly'  // равные промежутки

alignItems

По поперечной оси:

alignItems: 'flex-start'  // в начало
alignItems: 'flex-end'    // в конец
alignItems: 'center'      // по центру
alignItems: 'stretch'     // растянуть (по умолчанию)
alignItems: 'baseline'    // по базовой линии текста

flex

<View style={{ flex: 1 }}>  {/* займёт всё доступное пространство */}

Два блока с flex: 1 поделят пространство поровну:

<View style={{ flex: 1, flexDirection: 'row' }}>
    <View style={{ flex: 1, backgroundColor: 'red' }} />
    <View style={{ flex: 1, backgroundColor: 'blue' }} />
</View>

Отступы

padding: 16
paddingTop: 20
paddingHorizontal: 16  // слева и справа
paddingVertical: 8     // сверху и снизу

margin: 16
marginTop: 20
marginHorizontal: 16
marginVertical: 8

paddingHorizontal и paddingVertical — уникальны для React Native.

Размеры

width: 100
height: 200
minWidth: 50
maxWidth: 300
minHeight: 50
maxHeight: 500

В процентах:

width: '100%'
height: '50%'

Позиционирование

position: 'relative'  // по умолчанию
position: 'absolute'

top: 10
right: 10
bottom: 10
left: 10

Absolute позиционируется относительно родителя.

Тени

iOS:

shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,

Android:

elevation: 4,

Универсально:

const styles = StyleSheet.create({
    card: {
        ...Platform.select({
            ios: {
                shadowColor: '#000',
                shadowOffset: { width: 0, height: 2 },
                shadowOpacity: 0.1,
                shadowRadius: 4,
            },
            android: {
                elevation: 4,
            },
        }),
    },
});

Границы

borderWidth: 1
borderColor: '#ccc'
borderRadius: 8
borderTopWidth: 1
borderBottomColor: '#000'

Комбинирование стилей

<View style={[styles.base, styles.primary, { marginTop: 16 }]} />

Массив — стили применяются по порядку. Последний выигрывает.

Условно:

<View style={[styles.base, isActive && styles.active]} />

Если isActive = false — false игнорируется.

Итоги

  • Flexbox всегда включён
  • flexDirection: 'column' по умолчанию
  • paddingHorizontal, paddingVertical
  • Тени — разные на iOS и Android
  • Стили комбинируются массивом