24. Align Items en React Native Flexbox
Objetivo:
Comprender y aplicar la propiedad alignItems en React Native para controlar la alineación de elementos en el eje cruzado (perpendicular al eje principal) dentro de contenedores flex.
Contenido del tutorial:
1. ¿Qué es alignItems?
Definición: Propiedad que alinea elementos en el eje cruzado del contenedor flex.
Relación con flexDirection:
Si flexDirection: 'row' → Eje cruzado es vertical → alignItems controla alineación vertical.
Si flexDirection: 'column' → Eje cruzado es horizontal → alignItems controla alineación horizontal.
Valor por defecto: stretch
2. Configuración inicial del ejemplo
Código base:
jsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const App = () => {
return (
<View style={styles.container}>
<View style={styles.boxSize}>
<Text style={styles.text}>1</Text>
</View>
<View style={styles.boxSize}>
<Text style={styles.text}>2</Text>
</View>
<View style={styles.boxSize}>
<Text style={styles.text}>3</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row', // ← Eje principal: horizontal
justifyContent: 'space-around',
alignItems: 'center', // ← Controla alineación VERTICAL (eje cruzado)
},
boxSize: {
width: 100,
height: 100,
margin: 5,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'gray',
},
text: {
fontSize: 30,
fontWeight: 'bold',
color: 'white',
},
});
export default App;
3. Valores de alignItems con flexDirection: 'row' (eje cruzado: VERTICAL)
1. flex-start
jsx
alignItems: 'flex-start'
Comportamiento: Alinea elementos al inicio del eje cruzado (arriba).
Visual:
text
[1] [2] [3]
Uso: Para elementos que deben estar pegados arriba.
2. center (el más común)
jsx
alignItems: 'center'
Comportamiento: Centra elementos en el eje cruzado.
Visual:
text
[1] [2] [3]
Uso: Centrado vertical cuando los elementos tienen altura fija.
3. flex-end
jsx
alignItems: 'flex-end'
Comportamiento: Alinea elementos al final del eje cruzado (abajo).
Visual:
text
[1] [2] [3]
Uso: Para elementos que deben estar abajo.
4. stretch (VALOR POR DEFECTO)
jsx
alignItems: 'stretch'
Comportamiento: Estira elementos para llenar el contenedor en el eje cruzado.
Condición: Solo funciona si NO hay dimensiones fijas (width/height) en el elemento hijo.
Ejemplo práctico:
jsx
// En el hijo (boxSize), QUITAMOS la altura:
boxSize: {
width: 100,
// height: 100, ← QUITADO para que stretch funcione
margin: 5,
backgroundColor: 'gray',
}
Resultado: Las cajas se estiran verticalmente al 100% del contenedor padre.
5. baseline (menos común)
jsx
alignItems: 'baseline'
Comportamiento: Alinea elementos según la línea base del texto.
Uso: Para alinear textos de diferentes tamaños.
4. Valores de alignItems con flexDirection: 'column' (eje cruzado: HORIZONTAL)
Cambia el eje cruzado:
jsx
container: {
flex: 1,
flexDirection: 'column', // ← Eje principal: vertical
justifyContent: 'space-around',
alignItems: 'center', // ← Ahora controla alineación HORIZONTAL
}
flex-start → Alinea a la izquierda
center → Centra horizontalmente
flex-end → Alinea a la derecha
stretch → Estira horizontalmente (si no hay width fijo en hijos)
5. Demostración práctica: stretch en acción
Ejemplo 1: stretch con flexDirection: 'row'
jsx
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'stretch', // ← Estirará verticalmente
},
boxSize: {
width: 100, // ← Ancho fijo
// height: 100, ← SIN altura para que stretch funcione
margin: 5,
backgroundColor: 'gray',
},
});
Resultado: Cajas ocuparán todo el alto disponible.
Ejemplo 2: stretch con flexDirection: 'column'
jsx
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'stretch', // ← Estirará horizontalmente
},
boxSize: {
// width: 100, ← SIN ancho para que stretch funcione
height: 100, // ← Alto fijo
margin: 5,
backgroundColor: 'gray',
},
});
Resultado: Cajas ocuparán todo el ancho disponible.
6. Caso especial: stretch con contenido interno
Problema: Si un elemento hijo tiene contenido (como texto), stretch puede comportarse inesperadamente.
Solución: El hijo se estirará, pero su contenido puede mantener dimensiones propias.
Ejemplo:
jsx
<View style={styles.boxSize}>
<Text style={styles.text}>3</Text>
</View>
La caja se estira, pero el texto mantiene su tamaño.
7. Código interactivo para probar todas las opciones
jsx
import React, { useState } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
const alignItemsOptions = [
'flex-start',
'center',
'flex-end',
'stretch',
'baseline',
];
const App = () => {
const [currentAlign, setCurrentAlign] = useState('center');
const [direction, setDirection] = useState('row');
const [hasFixedDimensions, setHasFixedDimensions] = useState(true);
return (
<View style={styles.main}>
{/* Controles */}
<View style={styles.controls}>
<Text style={styles.title}>Flex Direction:</Text>
<View style={styles.directionButtons}>
{['row', 'column'].map((dir) => (
<TouchableOpacity
key={dir}
style={[styles.controlButton, direction === dir && styles.selectedControl]}
onPress={() => setDirection(dir)}
>
<Text style={styles.controlText}>{dir}</Text>
</TouchableOpacity>
))}
</View>
<Text style={styles.title}>alignItems:</Text>
<ScrollView horizontal style={styles.options}>
{alignItemsOptions.map((option) => (
<TouchableOpacity
key={option}
style={[
styles.controlButton,
currentAlign === option && styles.selectedControl,
]}
onPress={() => setCurrentAlign(option)}
>
<Text style={styles.controlText}>{option}</Text>
</TouchableOpacity>
))}
</ScrollView>
<Text style={styles.title}>Dimensiones en hijos:</Text>
<TouchableOpacity
style={[
styles.controlButton,
!hasFixedDimensions && styles.selectedControl,
]}
onPress={() => setHasFixedDimensions(!hasFixedDimensions)}
>
<Text style={styles.controlText}>
{hasFixedDimensions ? 'Con dimensiones fijas' : 'Sin dimensiones fijas (stretch funciona)'}
</Text>
</TouchableOpacity>
</View>
{/* Información */}
<Text style={styles.info}>
{`flexDirection: '${direction}'`} | {`alignItems: '${currentAlign}'`}
{'\n'}
Eje cruzado: {direction === 'row' ? 'VERTICAL' : 'HORIZONTAL'}
</Text>
{/* Contenedor principal */}
<View style={[styles.container, {
flexDirection: direction,
alignItems: currentAlign,
}]}>
<View style={[
styles.box,
hasFixedDimensions && direction === 'row' && styles.boxFixedHeight,
hasFixedDimensions && direction === 'column' && styles.boxFixedWidth,
]}>
<Text style={styles.boxText}>1</Text>
</View>
<View style={[
styles.box,
hasFixedDimensions && direction === 'row' && styles.boxFixedHeight,
hasFixedDimensions && direction === 'column' && styles.boxFixedWidth,
]}>
<Text style={[styles.boxText, { fontSize: 20 }]}>Texto más pequeño</Text>
</View>
<View style={[
styles.box,
hasFixedDimensions && direction === 'row' && styles.boxFixedHeight,
hasFixedDimensions && direction === 'column' && styles.boxFixedWidth,
]}>
<Text style={styles.boxText}>3</Text>
</View>
</View>
{/* Leyenda */}
<View style={styles.legend}>
<Text style={styles.legendText}>
💡 <Text style={{ fontWeight: 'bold' }}>Nota:</Text>
{'\n'}
• 'stretch' solo funciona si los hijos NO tienen dimensiones fijas en el eje cruzado.
{'\n'}
• Con 'row': quita 'height' para ver stretch vertical.
{'\n'}
• Con 'column': quita 'width' para ver stretch horizontal.
</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
main: {
flex: 1,
paddingTop: 50,
backgroundColor: '#fff',
},
controls: {
padding: 15,
backgroundColor: '#f5f5f5',
borderBottomWidth: 1,
borderBottomColor: '#ddd',
},
title: {
fontSize: 14,
fontWeight: 'bold',
marginTop: 10,
marginBottom: 5,
color: '#333',
},
directionButtons: {
flexDirection: 'row',
marginBottom: 15,
},
options: {
marginBottom: 15,
},
controlButton: {
padding: 10,
marginRight: 10,
backgroundColor: '#e0e0e0',
borderRadius: 5,
minWidth: 100,
alignItems: 'center',
},
selectedControl: {
backgroundColor: '#2196F3',
},
controlText: {
color: '#333',
fontWeight: 'bold',
fontSize: 12,
},
info: {
textAlign: 'center',
fontSize: 14,
fontWeight: 'bold',
marginVertical: 15,
color: '#555',
backgroundColor: '#f9f9f9',
padding: 10,
},
container: {
flex: 1,
backgroundColor: '#f0f0f0',
marginHorizontal: 20,
marginBottom: 20,
padding: 20,
borderWidth: 2,
borderColor: '#ccc',
borderRadius: 10,
},
box: {
margin: 10,
backgroundColor: '#4CAF50',
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
padding: 10,
},
boxFixedHeight: {
height: 80, // Fijo para row (altura en eje cruzado)
},
boxFixedWidth: {
width: 120, // Fijo para column (ancho en eje cruzado)
},
boxText: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
},
legend: {
backgroundColor: '#FFF3CD',
marginHorizontal: 20,
marginBottom: 20,
padding: 15,
borderRadius: 8,
borderWidth: 1,
borderColor: '#FFEAA7',
},
legendText: {
color: '#856404',
fontSize: 12,
},
});
export default App;
8. Combinaciones útiles en la práctica
Formulario centrado:
jsx
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center', // ← Centra horizontalmente
}
Barra de navegación:
jsx
container: {
flexDirection: 'row',
alignItems: 'center', // ← Centra verticalmente los íconos/texto
height: 60,
backgroundColor: '#fff',
}
Tarjetas de ancho completo:
jsx
container: {
flexDirection: 'column',
alignItems: 'stretch', // ← Las tarjetas ocupan todo el ancho
},
card: {
// Sin width definido para que stretch funcione
height: 100,
marginVertical: 5,
}
9. Errores comunes y soluciones
Conclusión:
alignItems es esencial para controlar la alineación perpendicular al flujo principal de elementos. Recuerda:
✅ Eje cruzado depende de flexDirection
✅ stretch es el valor por defecto
✅ stretch requiere hijos sin dimensiones fijas en ese eje
✅ center es el más común para centrar
✅ Combinado con justifyContent controlas ambos ejes
Próximo paso: Aprenderemos sobre alignSelf para alinear elementos individualmente dentro de un contenedor flex.
💡 Tip para depuración: Coloca bordes de colores en tus contenedores para visualizar claramente cómo alignItems afecta la disposición de los elementos
Comentarios
Publicar un comentario