Implementación de Diseño de Cascada con JavaScript Puro y Carga Dinámica al Desplazarse

El diseño de cascada, o disposición en casccada, es una técnica de maquetación web que organiza los elemetnos en múltiples columnas con alturas variables, creando un efecto visual irregular. A medida que el usuario se despalza verticalmente, se insertan nuevos elementos en la posición de menor altura acumulada, optimizando el espacio y ofreciendo una experiencia continua.

La implementación se basa en cálculos dinámicos con JavaScript puro. Se determina el número de columnas según el ancho del contenedor y la ventana del navegador. Luego, se almacenan las alturas de cada columna y se asigna cada nuevo elemento a la columna con la altura mínima, actualizando el registro tras cada inserción.

Estructura HTML de ejemplo:

<div id="contenedor-galeria">
    <div class="tarjeta">
        <div class="contenido">
            <img src="imagenes/1.jpg" alt="Ejemplo">
            <p>Texto descriptivo</p>
        </div>
    </div>
    <!-- Elementos adicionales omitidos por brevedad -->
</div>

Estilos CSS correspondientes:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    background-color: #eaeaea;
    font-family: sans-serif;
}
#contenedor-galeria {
    position: relative;
    margin: 20px;
}
#contenedor-galeria .tarjeta {
    padding: 10px;
    position: absolute;
}
#contenedor-galeria .contenido {
    border: 1px solid #ccc;
    background-color: #fff;
    padding: 10px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#contenedor-galeria .contenido img {
    max-width: 100%;
    display: block;
}
#contenedor-galeria .contenido p {
    text-align: center;
    margin-top: 8px;
    font-weight: bold;
    color: #333;
}

Lógica JavaScript para el posicionamiento y carga:

document.addEventListener('DOMContentLoaded', () => {
    const datosSimulados = [
        { ruta: '1.jpg' },
        { ruta: '2.jpg' },
        { ruta: '3.jpg' },
        { ruta: '4.jpg' }
    ];

    inicializarDiseñoCascada('contenedor-galeria', 'tarjeta');

    window.addEventListener('scroll', () => {
        if (verificarCondicionCarga()) {
            insertarNuevosElementos(datosSimulados);
            inicializarDiseñoCascada('contenedor-galeria', 'tarjeta');
        }
    });
});

function inicializarDiseñoCascada(idContenedor, claseElemento) {
    const contenedor = document.getElementById(idContenedor);
    const elementos = contenedor.querySelectorAll(`.${claseElemento}`);
    const anchoElemento = elementos[0] ? elementos[0].offsetWidth : 200;
    const anchoViewport = window.innerWidth;
    const numColumnas = Math.max(1, Math.floor(anchoViewport / anchoElemento));
    const alturasColumnas = Array(numColumnas).fill(0);

    elementos.forEach((elemento, indice) => {
        const alturaActual = elemento.offsetHeight;
        if (indice < numColumnas) {
            elemento.style.top = '0';
            elemento.style.left = `${anchoElemento * indice}px`;
            alturasColumnas[indice] = alturaActual;
        } else {
            const alturaMinima = Math.min(...alturasColumnas);
            const indiceMin = alturasColumnas.indexOf(alturaMinima);
            elemento.style.top = `${alturaMinima}px`;
            elemento.style.left = `${anchoElemento * indiceMin}px`;
            alturasColumnas[indiceMin] += alturaActual;
        }
    });
}

function verificarCondicionCarga() {
    const contenedor = document.getElementById('contenedor-galeria');
    const ultimoElemento = contenedor.querySelector('.tarjeta:last-child');
    if (!ultimoElemento) return false;
    const limiteInferior = ultimoElemento.offsetTop + ultimoElemento.offsetHeight;
    const desplazamientoVertical = window.pageYOffset || document.documentElement.scrollTop;
    const alturaVisible = window.innerHeight;
    return limiteInferior < desplazamientoVertical + alturaVisible;
}

function insertarNuevosElementos(datos) {
    const contenedor = document.getElementById('contenedor-galeria');
    datos.forEach(dato => {
        const nuevaTarjeta = document.createElement('div');
        nuevaTarjeta.className = 'tarjeta';
        const nuevoContenido = document.createElement('div');
        nuevoContenido.className = 'contenido';
        const imagen = document.createElement('img');
        imagen.src = `imagenes/${dato.ruta}`;
        nuevoContenido.appendChild(imagen);
        const parrafo = document.createElement('p');
        parrafo.textContent = 'Contenido dinámico';
        nuevoContenido.appendChild(parrafo);
        nuevaTarjeta.appendChild(nuevoContenido);
        contenedor.appendChild(nuevaTarjeta);
    });
}

El código anterior calcula dinámicamente la disposición y activa la carga de nuevos elementos cuando el usuario se acerca al final de la página visible.

Etiquetas: JavaScript css HTML diseño-cascada carga-lazy

Publicado el 6-2 16:03