http___localhost_ejer2-clinica_
📚 EXPLICACIÓN DE CÓMO FUNCIONA
La arquitectura Flexbox en 3 niveles
NIVEL 1: .cards-container (PADRE)
├── display: flex
├── justify-content: center (centra hijas horizontalmente)
├── gap: 20px (espacio entre tarjetas)
└── align-items: stretch (misma altura en todas)
NIVEL 2: .card-uno (HIJO/PADRE)
├── display: flex
├── flex-direction: column (apila verticalmente)
└── width: 250px
NIVEL 3: header - body - footer (NIETOS)
├── header: flex-shrink:0 (no se encoge)
├── body: flex: 1 → ★ SE EXPANDE ★
└── footer: flex-shrink:0 (no se encoge)¿Qué hace flex: 1 en .card-body?
Es la propiedad MÁS IMPORTANTE. Sin ella, las tarjetas se verían así:
┌─────────┐ ┌─────────┐
│ HEADER │ │ HEADER │
├─────────┤ ├─────────┤
│ body │ │ body │
│ (poco │ │ (mucho │
│ texto) │ │ texto) │
├─────────┤ ├─────────┤ ← Footer queda
│ footer │ │ texto │ a diferente
└─────────┘ │ extra │ altura!
├─────────┤
│ footer │
└─────────┘Con flex: 1, todas tienen footer a la misma altura:
┌─────────┐ ┌─────────┐
│ HEADER │ │ HEADER │
├─────────┤ ├─────────┤
│ │ │ body │
│ body │ │ con │
│ se │ │ mucho │
│ expande │ │ texto │
├─────────┤ ├─────────┤ ← ¡Mismo nivel!
│ footer │ │ footer │
└─────────┘ └─────────┘🧠 MÉTODO PARA APRENDER Y MEMORIZAR
Técnica 1: La "Regla de Oro" de Flexbox
Memoriza este patrón que se repite SIEMPRE:
| Situación | Propiedades clave | Frase para recordar |
|---|---|---|
| Contenedor padre | display: flex | "Papá se vuelve flexible" |
| Alinear hijos horizontal | justify-content: center | "Justificar = centrar en horizontal" |
| Alinear hijos vertical | align-items: center (o stretch) | "Alinear = vertical" |
| Espacio entre hijos | gap: 20px | "Gap = hueco" |
| Dirección vertical | flex-direction: column | "Columna = apilar" |
| Expandir un hijo | flex: 1 en ese hijo | "Flex 1 = se come el espacio" |
Técnica 2: Asociaciones visuales (mnemotecnia)
display: flex → 🦸♂️ "Superpoder que organiza"
flex-direction → 🧱 "Dirección de los ladrillos"
justify-content → 📏 "Regla horizontal" (izquierda, centro, derecha)
align-items → 📐 "Escuadra vertical" (arriba, centro, abajo)
gap → ⬜ "Espacio entre dedos"
flex: 1 → 🍕 "Se come la porción restante"
flex-shrink: 0 → 🪨 "Terco como una roca (no se encoge)"Técnica 3: El método de "construcción por capas"
Memoriza este orden de construcción (es siempre el mismo):
CAPA 1: Reset universal
* { margin:0; padding:0; box-sizing: border-box; }
CAPA 2: Contenedor principal (horizontal)
.display-flex {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
}
CAPA 3: Tarjeta individual (vertical)
.card {
display: flex;
flex-direction: column;
width: 250px;
}
CAPA 4: Distribución interna
.header { flex-shrink: 0; }
.body { flex: 1; } ← CLAVE
.footer { flex-shrink: 0; }
CAPA 5: Estilos visuales
background-color, border-radius, padding, box-shadowTécnica 4: Práctica de "5 minutos diarios"
Día 1: Escribe el RESET de memoria
Día 2: Añade el contenedor principal con display: flex
Día 3: Añade la tarjeta con flex-direction: column
Día 4: Añade flex: 1 en el body (el más importante)
Día 5: Añade header y footer con flex-shrink: 0
Día 6: Añade estilos visuales (colores, bordes, sombras)
Día 7: Construye 3 tarjetas desde cero SIN MIRAR
Técnica 5: Preguntas de autoevaluación
Responder estas preguntas solidifica el aprendizaje:
¿Qué pasa si elimino
flex: 1del.card-body?Los footers quedan a diferentes alturas
¿Qué pasa si elimino
flex-shrink: 0del header?El header podría encogerse si hay mucho contenido en el body
¿Qué hace
align-items: stretchen el contenedor?Obliga a todas las tarjetas a tener la misma altura
Diferencia entre
justify-contentyalign-items?justify-content→ eje PRINCIPAL (horizontal en row)align-items→ eje CRUZADO (vertical en row)
¿Por qué el
bodytienedisplay: flextambién?Para poder centrar su contenido verticalmente con
justify-content: center
Técnica 6: El "esqueleto mental" que debes memorizar
/* Este es el patrón que se repite en TODOS los diseños con cards */
.contenedor {
display: flex; /* 1. Activar flex */
justify-content: center; /* 2. Centrar */
gap: 20px; /* 3. Espaciar */
}
.tarjeta {
display: flex; /* 4. Activar flex interno */
flex-direction: column; /* 5. Dirección vertical */
width: 300px; /* 6. Ancho fijo */
}
.header { flex-shrink: 0; } /* 7. Fijo arriba */
.body { flex: 1; } /* 8. ★ EXPANDE ★ */
.footer { flex-shrink: 0; } /* 9. Fijo abajo */Técnica 7: La prueba del "lápiz y papel"
Cierra los ojos y dibuja este diagrama en un papel:
┌─────────────────────────────────────────┐
│ .cards-container (display: flex; gap) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Tarjeta │ │ Tarjeta │ │ Tarjeta │ │
│ │display: │ │display: │ │display: │ │
│ │ flex; │ │ flex; │ │ flex; │ │
│ │ column │ │ column │ │ column │ │
│ │ │ │ │ │ │ │
│ │ Header │ │ Header │ │ Header │ │
│ │─────────│ │─────────│ │─────────│ │
│ │ BODY │ │ BODY │ │ BODY │ │
│ │ flex:1 │ │ flex:1 │ │ flex:1 │ │
│ │─────────│ │─────────│ │─────────│ │
│ │ Footer │ │ Footer │ │ Footer │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────┘🎯 Resumen final: Lo que DEBES memorizar
/* LAS 5 LÍNEAS MÁS IMPORTANTES */
display: flex; /* Activa el superpoder */
flex-direction: column; /* Apila verticalmente */
flex: 1; /* Expande para llenar espacio */
flex-shrink: 0; /* Evita que se encoja */
gap: 20px; /* Espacio entre elementos */Repite estas 5 líneas en voz alta 10 veces cada mañana durante una semana. No las olvidarás nunca. 🚀
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!-- Define la codificación UTF-8 para soportar caracteres especiales (ñ, tildes) --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Hace la página responsive en dispositivos móviles --> <title>Document</title> <!-- Título que aparece en la pestaña del navegador --> </head> <style> /* ============================================ RESETEO GLOBAL (Normalización de estilos) ============================================ */ * { margin: 0; /* Elimina el margen externo predeterminado de todos los elementos HTML */ padding: 0; /* Elimina el padding interno predeterminado de todos los elementos HTML */ box-sizing: border-box; /* Hace que el ancho/alto TOTAL incluyan padding y border, no solo el contenido */ /* Ejemplo: un div con width:100px + padding:10px tendrá ancho TOTAL = 100px (no 120px) */ } /* ============================================ ESTILOS DEL BODY (Página principal) ============================================ */ body { background-color: #f0f0f0; /* Color gris claro de fondo para toda la página */ border: 5px solid red; /* Borde rojo temporal (ÚTIL PARA DEPURACIÓN: muestra los límites exactos del body) */ padding: 20px; /* Espacio interno de 20px alrededor de TODO el contenido, separa del borde rojo */ } /* ============================================ CONTENEDOR PRINCIPAL DE TARJETAS (PADRE FLEX) ============================================ */ .cards-container { display: flex; /* Activa Flexbox para alinear las tarjetas horizontalmente */ flex-wrap: wrap; /* Permite que las tarjetas se envuelvan a la siguiente línea si no hay espacio horizontal */ justify-content: center; /* Centra horizontalmente TODAS las tarjetas como grupo dentro del contenedor */ gap: 20px; /* Espacio de 20px ENTRE cada tarjeta (no en los bordes externos) */ align-items: stretch; /* Hace que TODAS las tarjetas tengan la MISMA altura (la del más alto) */ /* stretch es el valor por defecto, pero lo escribimos explícitamente para claridad */ } /* ============================================ TARJETA INDIVIDUAL (HIJO FLEX) ============================================ */ .card-uno { background-color: white; /* Fondo blanco para cada tarjeta (contrasta con fondo gris del body) */ width: 250px; /* Ancho fijo de 250px para TODAS las tarjetas (uniformidad) */ display: flex; /* Activa Flexbox DENTRO de la tarjeta para organizar su contenido interno */ flex-direction: column; /* Organiza el contenido VERTICALMENTE (header arriba, body medio, footer abajo) */ border-radius: 12px; /* Bordes redondeados de 12px en las 4 esquinas (aspecto moderno) */ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* Sombra: desplazamiento X=0, Y=2px, difuminado=5px, color negro 10% opaco */ /* NOTA: flex-wrap y justify-content NO son necesarios dentro de la tarjeta porque sus hijos son header/body/footer */ } /* ============================================ HEADER DE LA TARJETA (Parte superior - Título) ============================================ */ .card-header { background-color: #f8f9fa; /* Color gris muy claro (casi blanco) para el fondo del header */ border-bottom: 1px solid #dee2e6; /* Línea divisoria inferior: 1px sólido gris claro (separa header de body) */ padding: 10px; /* Espacio interno de 10px alrededor del contenido del header */ flex-shrink: 0; /* EVITA que el header se ENCOJA cuando falte espacio. Mantiene su altura original */ /* Sin flex-shrink:0, el header podría reducir su altura si el contenido es demasiado grande */ } /* Título H3 dentro del header */ .card-header h3 { text-align: center; /* Centra horizontalmente el texto del título dentro del header */ } /* ============================================ BODY DE LA TARJETA (Parte central - CONTENIDO PRINCIPAL) ============================================ */ .card-body { padding: 10px; /* Espacio interno de 10px alrededor del contenido del body */ flex: 1; /* ¡PROPIEDAD CLAVE! Hace que el body ocupe TODO el espacio disponible */ /* flex:1 equivale a: flex-grow: 1, flex-shrink: 1, flex-basis: 0% */ /* Esto significa: el body se EXPANDE para ocupar el espacio entre header y footer */ display: flex; /* Activa Flexbox DENTRO del body para centrar su contenido */ flex-direction: column; /* Organiza el contenido del body verticalmente */ justify-content: center; /* Centra VERTICALMENTE el contenido dentro del body (arriba/abajo) */ } /* ============================================ FOOTER DE LA TARJETA (Parte inferior - Botones) ============================================ */ .card-footer { background-color: #f8f9fa; /* Color gris muy claro para el fondo del footer (coincide con header) */ padding: 10px; /* Espacio interno de 10px alrededor del contenido del footer */ border-top: 1px solid #dee2e6; /* Línea divisoria superior: 1px sólido gris claro (separa body de footer) */ flex-shrink: 0; /* EVITA que el footer se ENCOJA cuando falte espacio. Mantiene su altura original */ display: flex; /* Activa Flexbox DENTRO del footer para alinear el botón/enlace horizontalmente */ width: 100%; /* Asegura que el footer ocupe TODO el ancho disponible de la tarjeta */ } /* ============================================ BOTÓN / ENLACE DE INGRESO (Estilo uniforme para button y a) ============================================ */ .btn-ingresar { flex: 1; /* Hace que el botón ocupe TODO el espacio disponible dentro del footer */ width: 100%; /* Ancho completo del contenedor padre (por si flex falla en navegadores antiguos) */ padding: 8px; /* Espacio interno: 8px arriba/abajo, 8px izquierda/derecha */ background-color: #007bff; /* Color azul primario (azul Bootstrap) para el fondo del botón */ color: white; /* Texto en color blanco para máximo contraste sobre fondo azul */ border: none; /* Elimina el borde predeterminado que los navegadores ponen a los botones */ border-radius: 6px; /* Bordes ligeramente redondeados de 6px para suavizar el diseño */ cursor: pointer; /* Cambia el cursor a "mano" al pasar por encima (indica elemento clickeable) */ transition: background-color 0.3s; /* Transición suave de 0.3 segundos al cambiar color de fondo */ text-align: center; /* Centra el texto horizontalmente dentro del botón */ } /* Estado HOVER (cuando el mouse pasa por encima del botón) */ .btn-ingresar:hover { background-color: #0056b3; /* Cambia a un azul más oscuro al pasar el mouse (efecto visual de realce) */ } /* ============================================ TEXTO DE SUBTÍTULO (para Secretaria y Doctor) ============================================ */ .rol-subtitulo { text-align: center; /* Centra horizontalmente el texto */ color: #666; /* Color gris oscuro (más suave que el negro puro #000) */ } /* ============================================ CONTENEDOR DE ESTADÍSTICAS (para User Registrations y Unique Visitors) ============================================ */ .stats-container { text-align: center; /* Centra horizontalmente TODO el contenido dentro del contenedor */ } /* Cada ítem de estadística (44 o 65 con su etiqueta) */ .stat-item { margin: 10px 0; /* Margen vertical: 10px arriba y abajo, 0 a los lados (separación entre items) */ } /* Número grande de estadística (44, 65) */ .stat-number { font-size: 24px; /* Tamaño de fuente grande (24px) para destacar el número */ font-weight: bold; /* Negrita para dar más énfasis y peso visual */ color: #007bff; /* Mismo azul que el botón para mantener coherencia de colores en el diseño */ } /* Etiqueta descriptiva (User Registrations, Unique Visitors) */ .stat-label { font-size: 12px; /* Tamaño de fuente pequeño (12px) para la descripción (no compite con el número) */ color: #666; /* Color gris oscuro (color secundario, menos protagonismo) */ } /* ============================================ ESTILOS PARA ENLACES <a> (Hipervínculos) ============================================ */ a { text-decoration: none; /* Elimina el subrayado predeterminado que los navegadores ponen a los enlaces */ width: 100%; /* Asegura que el enlace ocupe todo el ancho disponible de su contenedor (el footer) */ } </style> <body> <section> <?php // Código PHP comentado: controlador MVC para manejar enlaces (no afecta al CSS) // $mvc= new mvcController(); // $mvc->enlacesPaginasController(); ?> </section> <div class="cards-container"> <!-- TARJETA 1: Secretaria (usa enlace <a> en lugar de botón) --> <div class="card-uno"> <div class="card-header"> <h3>Secretaria</h3> <!-- Título de la cabecera --> </div> <div class="card-body"> <div class="rol-subtitulo">Inicie Sesión</div> <!-- Subtítulo con instrucción --> </div> <div class="card-footer"> <a href="login-doctor.php" class="btn-ingresar">Ingresar</a> <!-- Enlace estilizado como botón --> </div> </div> <!-- TARJETA 2: Doctor (usa botón <button> con evento onclick) --> <div class="card-uno"> <div class="card-header"> <h3>Doctor</h3> <!-- Título de la cabecera --> </div> <div class="card-body"> <div class="rol-subtitulo">Inicie Sesión</div> <!-- Mismo subtítulo --> </div> <div class="card-footer"> <button class="btn-ingresar" onclick="alert('Acceso Doctor')">Ingresar</button> <!-- Botón con alerta --> </div> </div> <!-- TARJETA 3: Estadísticas (primera, muestra datos numéricos) --> <div class="card-uno"> <div class="card-header"> <h3>Estadísticas</h3> <!-- Título relativo a datos numéricos --> </div> <div class="card-body"> <div class="stats-container"> <!-- Contenedor flex para estadísticas --> <div class="stat-item"> <!-- Primer ítem de estadística --> <div class="stat-number">44</div> <!-- Número grande (Usuarios registrados) --> <div class="stat-label">User Registrations</div> <!-- Etiqueta descriptiva --> </div> <div class="stat-item"> <!-- Segundo ítem de estadística --> <div class="stat-number">65</div> <!-- Número grande (Visitantes únicos) --> <div class="stat-label">Unique Visitors</div> <!-- Etiqueta descriptiva --> </div> </div> </div> <div class="card-footer"> <button class="btn-ingresar" onclick="alert('Acceso General')">Ingresar</button> <!-- Botón de acceso --> </div> </div> <!-- TARJETA 4: Estadísticas (segunda, réplica de la primera) --> <div class="card-uno"> <div class="card-header"> <h3>Estadísticas</h3> <!-- Mismo título --> </div> <div class="card-body"> <div class="stats-container"> <!-- Mismo contenedor de estadísticas --> <div class="stat-item"> <div class="stat-number">44</div> <div class="stat-label">User Registrations</div> </div> <div class="stat-item"> <div class="stat-number">65</div> <div class="stat-label">Unique Visitors</div> </div> </div> </div> <div class="card-footer"> <button class="btn-ingresar" onclick="alert('Acceso General')">Ingresar</button> <!-- Mismo botón --> </div> </div> </div> </body> </html>

Comentarios
Publicar un comentario