http___localhost_ejer2-clinica_

 

📚 EXPLICACIÓN DE CÓMO FUNCIONA

La arquitectura Flexbox en 3 niveles

text
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í:

text
┌─────────┐     ┌─────────┐
│ 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:

text
┌─────────┐     ┌─────────┐
│ 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ónPropiedades claveFrase para recordar
Contenedor padredisplay: flex"Papá se vuelve flexible"
Alinear hijos horizontaljustify-content: center"Justificar = centrar en horizontal"
Alinear hijos verticalalign-items: center (o stretch)"Alinear = vertical"
Espacio entre hijosgap: 20px"Gap = hueco"
Dirección verticalflex-direction: column"Columna = apilar"
Expandir un hijoflex: 1 en ese hijo"Flex 1 = se come el espacio"

Técnica 2: Asociaciones visuales (mnemotecnia)

text
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):

text
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-shadow

Té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:

  1. ¿Qué pasa si elimino flex: 1 del .card-body?

    • Los footers quedan a diferentes alturas

  2. ¿Qué pasa si elimino flex-shrink: 0 del header?

    • El header podría encogerse si hay mucho contenido en el body

  3. ¿Qué hace align-items: stretch en el contenedor?

    • Obliga a todas las tarjetas a tener la misma altura

  4. Diferencia entre justify-content y align-items?

    • justify-content → eje PRINCIPAL (horizontal en row)

    • align-items → eje CRUZADO (vertical en row)

  5. ¿Por qué el body tiene display: flex también?

    • Para poder centrar su contenido verticalmente con justify-content: center

Técnica 6: El "esqueleto mental" que debes memorizar

css
/* 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:

text
┌─────────────────────────────────────────┐
│  .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

css
/* 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. 🚀

html
<!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

Entradas más populares de este blog

Tutorial de CSS: De Cero a Estilizar tu Primera Página Web

layouts

Proyecto Práctico: Tarjeta de Perfil