Componente de Paginación con Scroll Infinito (2026) - Bsale-IO/template-docs GitHub Wiki

📄 Componente de Paginación

Componente reutilizable para colecciones de productos y blog, que permite definir el tipo de paginación desde la configuración general de la tienda.

La opción de paginación se encuentra disponible en el panel de configuración y aplica de forma global tanto para productos como para el blog, sin requerir cambios adicionales en el código una vez habilitada.

Important

Actualización importante: el componente de Paginación ahora es 100% genérico: un único código funciona para todas las plantillas (detecta automáticamente el grid y los items vía JavaScript, sin necesidad de assign wrapper_id / grid_selector por plantilla). Por lo tanto, ya no se debe duplicar el código de Paginación en cada plantilla. Se implementa una sola vez (ver sección Código unificado de Paginación) y se reutiliza en Blog y en Colección – Buscador – Marca mediante {{ 'paginacion' | get_component }}.

Además, para que el scroll infinito funcione correctamente (que los nuevos productos cargados por AJAX queden disponibles para el JS de carrito/checkout vía window.Bsale.collections), es obligatorio actualizar el componente Coleccion (load collection) con el nuevo script (ver sección Actualización del componente Coleccion).


⚙️ Configuración

La activación y selección del modo de paginación se realiza directamente desde la configuración de la tienda, en la sección “Tipo de paginación para productos y blog”.

Desde esta opción es posible seleccionar el comportamiento deseado (paginación tradicional, carga automática o carga con botón), siempre que la configuración esté previamente habilitada para el cliente.

Configuración del tipo de paginación para productos y blog

🔐 Habilitación de la opción de paginación

Antes de que la opción “Tipo de paginación para productos y blog” aparezca en la configuración de la tienda, es necesario habilitar previamente la configuración correspondiente a nivel de sistema.

Warning

Importante: Para que las opciones de configuración de paginación aparezcan en la configuración de la tienda y se active el scroll automático, es obligatorio crear y habilitar previamente la configuración scroll_mode en la base de datos del cliente.

Si esta configuración no existe, las opciones no se mostrarán y el comportamiento de paginación no funcionará, aunque el componente esté correctamente implementado en la plantilla.

CREA scroll_mode config

INSERT INTO db_bsale_29213.mk_markets_config
(mk_id, mkc_variable, mkc_valor, mkc_es_editable, mkc_es_empresa, mkc_control_html, mkc_orden, mc_id)
VALUES
(1, 'scroll_mode', 'auto', 1, 0, NULL, NULL, NULL);

Important

Atención: El nombre de base de datos db_bsale_29213 es solo un ejemplo.

Al implementar en un cliente real, se debe reemplazar por la base de datos correspondiente al cliente, de lo contrario la configuración no se aplicará correctamente.

El mk_id es el número del market.


Configuración del componente de paginación

🧩 Modos disponibles

Modo Descripción
Carga automática al hacer scroll Carga nuevos resultados automáticamente al llegar al final de la página
Carga con botón Muestra un botón “Ver más” para cargar más resultados
Paginación numérica tradicional Navegación clásica mediante páginas numeradas

Modo por defecto: Carga automática al hacer scroll


🔄 Código unificado de Paginación

Este es el único código de Paginación necesario. Reemplaza completamente los bloques de "Paginación" que antes se repetían en cada plantilla (Matías, Facundo, Catalina, Sofía, Trinidad, Ricardo, Nicolás, Rosario, Joaquín, etc).

A diferencia de la versión anterior, ya no requiere que la plantilla calcule wrapper_id / grid_selector vía Liquid ({% assign %} / data-grid): el propio script detecta automáticamente el grid (.bs-collection.grid, .bs-blog-articles, .grid.bs-blog, .grid) y los items (.grid__item, .bs-collection__product, .bs-blog-item, .item) dentro del wrapper correspondiente (products-wrapper para colecciones, content-wrapper para blog).

Componente: paginacion

{% case site.scroll_mode %}
{% when "auto" or "button" %}
    {% if collection %}
        {% assign wrapper_id = "products-wrapper" %}
    {% else %}
        {% assign wrapper_id = "content-wrapper" %}
    {% endif %}
    {% comment %} === SCROLL INFINITO (auto o button) === {% endcomment %}
    {% if pagination.next %}
    <div id="infinite-scroll-loader"></div>

    <!-- Indicador de más contenido (solo modo auto) -->
    <div id="scroll-indicator">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <polyline points="6 9 12 15 18 9"></polyline>
        </svg>
        <span>Desliza para ver más</span>
    </div>

    <button id="load-more-btn" type="button">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <polyline points="7 13 12 18 17 13"></polyline>
            <polyline points="7 6 12 11 17 6"></polyline>
        </svg>
        <span>Ver más</span>
    </button>

    <div id="scroll-sentinel" 
         data-next-page="{{ pagination.next }}" 
         data-mode="{{ site.scroll_mode }}"
         data-wrapper="{{ wrapper_id }}">
    </div>
    {% endif %}
<script>
// Forzar recarga limpia cuando se vuelve desde caché del navegador (bfcache)
window.addEventListener("pageshow", function(event) {
    if (event.persisted) location.reload();
});
document.addEventListener("DOMContentLoaded", function() {
    
    // === OBTENER ELEMENTOS DEL DOM ===
    const sentinel = document.getElementById("scroll-sentinel");
    if (!sentinel) return; // Si no hay sentinel, no hay paginación
    
    // Obtener configuración desde data attributes del sentinel
    const wrapperID = sentinel.dataset.wrapper;          // ID del contenedor principal
    const scrollMode = sentinel.dataset.mode || "auto"; // Modo: auto, button o numbers
    
    // Elementos de la UI
    const contentWrapper = document.getElementById(wrapperID);
    const loader = document.getElementById("infinite-scroll-loader");
    const loadMoreBtn = document.getElementById("load-more-btn");
    const scrollIndicator = document.getElementById("scroll-indicator");
    const productsShown = document.getElementById("products-shown");
    const sortSelect = document.querySelector("[data-bs=\"collection.sort\"]");
    
    // Recargar página al cambiar orden (evita problemas de caché)
    if (sortSelect) {
        sortSelect.addEventListener("change", function() {
            window.location.href = this.value;
        });
    }
    
    if (!contentWrapper) return;
    
    // === DETECCIÓN AUTOMÁTICA DE GRID ===
    // Lista de selectores de grid soportados (en orden de prioridad)
    const gridSelectors = [".bs-collection.grid", ".bs-blog-articles", ".grid.bs-blog", ".grid"];
    let gridContainer = null;
    let gridSelector = null;
    
    // Buscar cuál selector de grid existe en el wrapper
    for (const selector of gridSelectors) {
        gridContainer = contentWrapper.querySelector(selector);
        if (gridContainer) {
            gridSelector = selector; // Guardar el selector encontrado
            break;
        }
    }
    
    if (!gridContainer) return; // Si no hay grid, salir
    
    // === DETECCIÓN AUTOMÁTICA DE ITEMS ===
    // Lista de selectores de items soportados (en orden de prioridad)
    const itemSelectors = [".grid__item", ".bs-collection__product", ".bs-blog-item", ".item"];
    let itemSelector = null;
    
    // Buscar cuál selector de items existe en el grid
    for (const selector of itemSelectors) {
        if (gridContainer.querySelector(":scope > " + selector)) {
            itemSelector = selector;
            break;
        }
    }
    
    // Si no encuentra ninguno, usar todos los hijos directos
    if (!itemSelector) {
        itemSelector = ":scope > *";
    }
    
    // === VARIABLES DE ESTADO ===
    let isLoading = false;                        // Indica si está cargando
    let nextPageUrl = sentinel.dataset.nextPage;  // URL de la siguiente página
    
    // === INICIALIZACIÓN SEGÚN MODO ===
    if (scrollMode === "button") {
        // Modo botón: mostrar botón y agregar evento click
        loadMoreBtn.classList.add("active");
        loadMoreBtn.addEventListener("click", loadMoreContent);
    } else {
        // Modo auto: mostrar indicador y configurar scroll
        if (scrollIndicator) scrollIndicator.classList.add("active");
        setupAutoScroll();
    }
    
    // === FUNCIÓN: Actualizar contador "Mostrando X de Y" ===
    function updateCount() {
        if (productsShown) {
            const items = itemSelector === ":scope > *" 
                ? gridContainer.children.length 
                : gridContainer.querySelectorAll(":scope > " + itemSelector).length;
            productsShown.textContent = items;
        }
    }
    
    // === FUNCIÓN: Configurar scroll infinito automático ===
    function setupAutoScroll() {
        // Observer: detecta cuando el sentinel entra en el viewport
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting && !isLoading && nextPageUrl) loadMoreContent();
            });
        }, { rootMargin: "500px", threshold: 0 }); // 500px antes de llegar
        
        observer.observe(sentinel);
        
        // Fallback: también detectar scroll manual
        window.addEventListener("scroll", function() {
            if (isLoading || !nextPageUrl) return;
            if (window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 500) {
                loadMoreContent();
            }
        });
        
        // Verificar si necesita cargar más contenido inicial
        checkIfNeedsMoreContent();
    }
    
    // === FUNCIÓN PRINCIPAL: Cargar más contenido ===
    async function loadMoreContent() {
        // Evitar cargas duplicadas
        if (isLoading || !nextPageUrl) return;
        
        isLoading = true;
        
        // Ocultar indicador de scroll mientras carga
        if (scrollIndicator) scrollIndicator.classList.add("hidden");
        
        // Mostrar loader según el modo
        scrollMode === "button" ? loadMoreBtn.classList.add("loading") : loader.classList.add("active");
        
        try {
            // Fetch de la siguiente página
            const response = await fetch(nextPageUrl);
            const doc = new DOMParser().parseFromString(await response.text(), "text/html");

            //Se busca el JSON del listado de productos
            
            const collDataBase = doc.getElementById("coll_data_base");
            if (collDataBase?.textContent){
              const newData = JSON.parse(collDataBase.textContent);
              //Se busca el objeto de la coleccion y se añaden los nuevos productos.
              const foundColl = window.Bsale.collections.find(coll => coll.name == newData.name);
              if (foundColl){foundColl.addItems(newData.items)}
            }
            
            // Buscar el grid en la nueva página usando el selector detectado
            const newGrid = doc.querySelector("#" + wrapperID + " " + gridSelector);
            
            if (newGrid) {
                //Clonar el grid completo.
                const clonedGrid = newGrid.cloneNode(true);

                //Inicializar eventos de agregar al carro
                window.addToCartCollection(clonedGrid);

                // Construir selector para los items
                const newItemSelector = itemSelector === ":scope > *" ? ":scope > *" : ":scope > " + itemSelector;
                const newItems = clonedGrid.querySelectorAll(newItemSelector);

                                
                // Agregar cada item al grid actual
                gridContainer.append(...newItems);
                
                // Actualizar contador
                updateCount();
                
                // Re-inicializar eventos (carrito, etc.)
                if (typeof window.BS !== "undefined" && window.BS.init) window.BS.init();
            }
            
            // Buscar si hay más páginas
            const newSentinel = doc.querySelector("#scroll-sentinel");
            if (newSentinel?.dataset.nextPage) {
                // Hay más páginas: actualizar URL y mostrar indicador
                nextPageUrl = newSentinel.dataset.nextPage;
                if (scrollIndicator) scrollIndicator.classList.remove("hidden");
                if (scrollMode === "auto") checkIfNeedsMoreContent();
            } else {
                // No hay más páginas: limpiar elementos
                nextPageUrl = null;
                loader.remove();
                loadMoreBtn.remove();
                sentinel.remove();
                if (scrollIndicator) scrollIndicator.remove();
            }
        } catch (error) {
            console.error("Error:", error);
        } finally {
            // Siempre ejecutar: ocultar loaders
            isLoading = false;
            loader.classList.remove("active");
            loadMoreBtn?.classList.remove("loading");
        }
    }
    
    // === FUNCIÓN: Verificar si la página necesita más contenido ===
    // Si la página no tiene scroll, carga más contenido automáticamente
    function checkIfNeedsMoreContent() {
        setTimeout(() => {
            const pageHeight = document.documentElement.scrollHeight;
            const viewportHeight = window.innerHeight;
            
            // Si la página es más corta que la ventana y hay más contenido
            if (pageHeight <= viewportHeight && nextPageUrl && !isLoading) {
                loadMoreContent();
            }
        }, 300); // Delay para evitar loops
    }
});
</script>
{% else %}
    {% comment %} === PAGINACIÓN NUMÉRICA (numbers) === {% endcomment %}
    {% if pagination.pages %}
    <nav>
        <ul class="pagination justify-content-center mt-3">
            {% if pagination.prev %}
                <li class="page-item">
                    <a class="page-link" tabindex="-1" href="{{ pagination.prev }}"><i class="fas fa-angle-left"></i></a>
                </li>
            {% endif %}
            {% for page in pagination.pages %}
                {% if page %}
                    {% if page.current %}
                        <li class="page-item active">
                            <span class="page-link cursor-default">{{ page.number }}</span>
                        </li>
                    {% else %}
                        <li class="page-item">
                            <a class="page-link" href="{{ page.url }}">{{ page.number }}</a>  
                        </li>
                    {% endif %}
                {% else %}
                    <li class="page-item disabled">
                        <span class="page-link cursor-default">..</span>
                    </li>
                {% endif %}
            {% endfor %}
            {% if pagination.next %}
                <li class="page-item">
                    <a class="page-link" href="{{ pagination.next }}"><i class="fas fa-angle-right"></i></a>
                </li>
            {% endif %}
        </ul>
    </nav>
    {% endif %}
{% endcase %}

🆕 Actualización del componente Coleccion (load collection)

Para que el scroll infinito / botón "Ver más" pueda sincronizar los productos recién cargados por AJAX con window.Bsale.collections (usado por el carrito y otros scripts del sitio), el componente Coleccion debe incluir el siguiente bloque, que expone el JSON de la colección en un <script id="coll_data_base"> que el JS de Paginación busca y parsea en cada carga:

Componente: Coleccion (load collection)

<!--- load collection ----------------------------------------->
<script>
    window.INIT.collections.push({
        "name": "{{title}}",
        "items":{{collection | json_encode }}
    });
</script>
<script id="coll_data_base" type="application/json">
    {
        "name": "{{title}}",
        "items":{{collection | json_encode }}
    }
</script>
<!----------------------------------------------------------->

Warning

Esta actualización es obligatoria en todas las plantillas para que el scroll infinito funcione correctamente. Sin este bloque, el JS de Paginación no podrá encontrar #coll_data_base y window.Bsale.collections no se actualizará con los nuevos productos, lo que puede afectar funcionalidades como agregar al carro sobre los ítems cargados dinámicamente.


📋 Implementación en plantillas

Para implementar el componente correctamente, se debe identificar la versión de la plantilla y reemplazar el código correspondiente en los siguientes componentes:

  1. Componente Blog
  2. Componente Colección – Buscador – Marca (orden)
  3. Componente Colección – Buscador – Marca
  4. Componente Coleccion (load collection) → aplicar la actualización de la sección anterior
  5. Componente Paginación → usar una sola vez el código unificado de la sección Código unificado de Paginación (no se repite por plantilla)

Nota: los bloques Blog, Orden y Colección – Buscador – Marca de cada plantilla se mantienen igual que antes (no cambian entre plantillas en su lógica de paginación, ya que ambos simplemente llaman a {{ 'paginacion' | get_component }}), por lo que a continuación solo se listan por referencia.

Códigos de cada plantilla

TEMPLATE MATIAS
Blog
<main class="bs-blog">
  <div class="container">
    {{ 'migas de pan' | get_component }}

    {% if articles.size > 0 %}
      <div class="bs-blog-grid">
        <h1>Blog</h1>
        <div id="content-wrapper">
          <div class="bs-blog-articles">
            {% for art in articles %}
              <article class="bs-blog-item"> 
                <a href="{{ art.link }}" title="{{ art.title }}" class="bs-blog-image-link">
                  {% if art.imagen.size > 0 %}
                    <div class="bs-img-square blog bg-secondary cover">
                      <picture>
                        <source {{ art.imagen | source_tag_attributes: 'X' }}>
                        <source {{ art.imagen | source_tag_attributes: 'L' }}>
                        <source {{ art.imagen | source_tag_attributes: 'M' }}>
                        <source {{ art.imagen | source_tag_attributes: 'S' }}>
                        <img {{ art.imagen | img_tag_attributes: 'S' }}
                            onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                            alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                      </picture>
                    </div>
                  {% else %}
                    <div class="bs-img-square blog bg-secondary"></div>
                  {% endif %}
                </a>

                <div class="bs-blog-article">
                  <a href="{{ art.link }}" title="{{ art.title }}">
                    <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                  </a>
                  <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 100, '...' }}</p>

                  <div class="bs-blog-article-more">
                    <a href="{{ art.link }}" class="bs-blog-article__btn btn btn-link">Ver más</a>
                  </div>
                </div>

              </article>
            {% endfor %}
          </div>
        </div>

        {{ 'paginacion' | get_component }}
      </div>
    {% endif %}
  </div>
</main>
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE FACUNDO
Blog
<main class="bs-blog">
  <div class="container">
    {{ 'migas de pan' | get_component }}

    {% if articles.size > 0 %}
      <div class="bs-blog-grid">
        <h1>Blog</h1>
        <div id="content-wrapper">
          <div class="bs-blog-articles">
            {% for art in articles %}
              <article class="bs-blog-item"> 
                <a href="{{ art.link }}" title="{{ art.title }}" class="bs-blog-image-link">
                  {% if art.imagen.size > 0 %}
                    <div class="bs-img-square blog bg-secondary cover">
                      <picture>
                        <source {{ art.imagen | source_tag_attributes: 'X' }}>
                        <source {{ art.imagen | source_tag_attributes: 'L' }}>
                        <source {{ art.imagen | source_tag_attributes: 'M' }}>
                        <source {{ art.imagen | source_tag_attributes: 'S' }}>
                        <img {{ art.imagen | img_tag_attributes: 'S' }}
                            onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                            alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                      </picture>
                    </div>
                  {% else %}
                    <div class="bs-img-square blog bg-secondary"></div>
                  {% endif %}
                </a>

                <div class="bs-blog-article">
                  <a href="{{ art.link }}" title="{{ art.title }}">
                    <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                  </a>
                  <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 100, '...' }}</p>

                  <div class="bs-blog-article-more">
                    <a href="{{ art.link }}" class="bs-blog-article__btn btn btn-link">Ver más</a>
                  </div>
                </div>

              </article>
            {% endfor %}
          </div>
        </div>

        {{ 'paginacion' | get_component }}
      </div>
    {% endif %}
  </div>
</main>
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE CATALINA
Blog
<main class="bs-blog">
  <div class="container">
    {{ 'migas de pan' | get_component }}

    {% if articles.size > 0 %}
      <div class="bs-blog-grid">
        <h1>Blog</h1>
        <div id="content-wrapper">
          <div class="bs-blog-articles">
            {% for art in articles %}
              <article class="bs-blog-item"> 
                <a href="{{ art.link }}" title="{{ art.title }}" class="bs-blog-image-link">
                  {% if art.imagen.size > 0 %}
                    <div class="bs-img-square blog bg-secondary cover">
                      <picture>
                        <source {{ art.imagen | source_tag_attributes: 'X' }}>
                        <source {{ art.imagen | source_tag_attributes: 'L' }}>
                        <source {{ art.imagen | source_tag_attributes: 'M' }}>
                        <source {{ art.imagen | source_tag_attributes: 'S' }}>
                        <img {{ art.imagen | img_tag_attributes: 'S' }}
                            onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                            alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                      </picture>
                    </div>
                  {% else %}
                    <div class="bs-img-square blog bg-secondary"></div>
                  {% endif %}
                </a>

                <div class="bs-blog-article">
                  <a href="{{ art.link }}" title="{{ art.title }}">
                    <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                  </a>
                  <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 100, '...' }}</p>

                  <div class="bs-blog-article-more">
                    <a href="{{ art.link }}" class="bs-blog-article__btn btn btn-link">Ver más</a>
                  </div>
                </div>

              </article>
            {% endfor %}
          </div>
        </div>

        {{ 'paginacion' | get_component }}
      </div>
    {% endif %}
  </div>
</main>
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE SOFÍA
Blog
{{ 'migas de pan' | get_component }}
<main class="bs-blog">
  <div class="container-xxl">
    {% if articles.size > 0 %}
      <div class="bs-blog-grid">
        <h1>Blog</h1>
        
        <!-- Wrapper para scroll infinito -->
        <div id="content-wrapper">
          <div class="bs-blog-articles">
            {% for art in articles %}
              <article class="bs-blog-item"> 
                <a href="{{ art.link }}" title="{{ art.title }}" class="bs-blog-image-link">
                  {% if art.imagen.size > 0 %}
                    <div class="bs-img-square blog bg-secondary cover">
                      <picture>
                        <source {{ art.imagen | source_tag_attributes: 'X' }}>
                        <source {{ art.imagen | source_tag_attributes: 'L' }}>
                        <source {{ art.imagen | source_tag_attributes: 'M' }}>
                        <source {{ art.imagen | source_tag_attributes: 'S' }}>
                        <img {{ art.imagen | img_tag_attributes: 'S' }}
                            onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                            alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                      </picture>
                    </div>
                  {% else %}
                    <div class="bs-img-square blog bg-secondary"></div>
                  {% endif %}
                </a>

                <div class="bs-blog-article">
                  <a href="{{ art.link }}" title="{{ art.title }}">
                    <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                  </a>
                  <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 100, '...' }}</p>

                  <div class="bs-blog-article-more">
                    <a href="{{ art.link }}" class="bs-blog-article__btn btn btn-link">Ver más</a>
                  </div>
                </div>

              </article>
            {% endfor %}
          </div>
        </div>

        {{ 'paginacion' | get_component }}
      </div>
    {% endif %}
  </div>
</main>
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container-xxl container-fluid">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE TRINIDAD
Blog
<main class="bs-blog">
  <div class="container">
    {{ 'migas de pan' | get_component }}
    {% if articles.size > 0 %}
      <div class="bs-blog-grid">
        <h1>Blog</h1>
        
        <!-- Wrapper para scroll infinito -->
        <div id="content-wrapper">
          <div class="bs-blog-articles">
            {% for art in articles %}
              <article class="bs-blog-item"> 
                <a href="{{ art.link }}" title="{{ art.title }}" class="bs-blog-image-link">
                  {% if art.imagen.size > 0 %}
                    <div class="bs-img-square blog bg-secondary cover">
                      <picture>
                        <source {{ art.imagen | source_tag_attributes: 'X' }}>
                        <source {{ art.imagen | source_tag_attributes: 'L' }}>
                        <source {{ art.imagen | source_tag_attributes: 'M' }}>
                        <source {{ art.imagen | source_tag_attributes: 'S' }}>
                        <img {{ art.imagen | img_tag_attributes: 'S' }}
                            onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                            alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                      </picture>
                    </div>
                  {% else %}
                    <div class="bs-img-square blog bg-secondary"></div>
                  {% endif %}
                </a>

                <div class="bs-blog-article">
                  <a href="{{ art.link }}" title="{{ art.title }}">
                    <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                  </a>
                  <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 100, '...' }}</p>

                  <div class="bs-blog-article-more">
                    <a href="{{ art.link }}" class="bs-blog-article__btn btn btn-link">Ver más</a>
                  </div>
                </div>

              </article>
            {% endfor %}
          </div>
        </div>

        {{ 'paginacion' | get_component }}
      </div>
    {% endif %}
  </div>
</main>
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE RICARDO
Blog
<main class="bs-blog">
  <div class="container-xxl container-fluid">
    {{ 'migas de pan' | get_component }}
    {% if articles.size > 0 %}
      <div class="bs-blog-grid">
        <h1>Blog</h1>
        
        <!-- Wrapper para scroll infinito -->
        <div id="content-wrapper">
          <div class="bs-blog-articles">
            {% for art in articles %}
              <article class="bs-blog-item"> 
                <a href="{{ art.link }}" title="{{ art.title }}" class="bs-blog-image-link">
                  {% if art.imagen.size > 0 %}
                    <div class="bs-img-square blog bg-secondary cover">
                      <picture>
                        <source {{ art.imagen | source_tag_attributes: 'X' }}>
                        <source {{ art.imagen | source_tag_attributes: 'L' }}>
                        <source {{ art.imagen | source_tag_attributes: 'M' }}>
                        <source {{ art.imagen | source_tag_attributes: 'S' }}>
                        <img {{ art.imagen | img_tag_attributes: 'S' }}
                            onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                            alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                      </picture>
                    </div>
                  {% else %}
                    <div class="bs-img-square blog bg-secondary"></div>
                  {% endif %}
                </a>

                <div class="bs-blog-article">
                  <a href="{{ art.link }}" title="{{ art.title }}">
                    <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                  </a>
                  <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 100, '...' }}</p>

                  <div class="bs-blog-article-more">
                    <a href="{{ art.link }}" class="bs-blog-article__btn btn btn-link">Ver más</a>
                  </div>
                </div>

              </article>
            {% endfor %}
          </div>
        </div>

        {{ 'paginacion' | get_component }}
      </div>
    {% endif %}
  </div>
</main>
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container-xxl container-fluid">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE NICOLAS
Blog
{{'migas de pan' | get_component }}
<div class="container-xxl">
    <h2><a class="bs-home-title" href="/blog">Blog</a></h2>
    {% if articles.size > 0 %}
        <!-- Wrapper para scroll infinito -->
        <div id="content-wrapper">
            <div class="grid bs-blog">
                {% for art in articles %}
                    <div class="item"> 
                        <div class="bs-blog-article">
                   
                            {% if art.imagen.size > 0 %}
                                <a class="bs-img-square bs-blog-article__img" href="{{art.link}}" title="{{art.title}}">
                                    <picture>
                                        <source srcset="{{art.imagen | image_url: 'L'}}" media="(min-width:800px)">
                                        <source srcset="{{art.imagen | image_url: 'M'}}" media="(min-width:400px)">
                                        <source srcset="{{art.imagen | image_url: 'S'}}" media="(min-width:240px)">
                                        <source srcset="{{art.imagen | image_url: 'T'}}" media="(min-width:0px)">
                                        <img loading="lazy" src="{{art.imagen | image_url: 'S'}}" 
                                             onerror="this.onerror=null;this.src='{{art.imagen}}';"
                                             alt="{{art.title}}">
                                     </picture>  
                                </a>
                            {% else %}
                            <div class="bs-img-square bs-blog-article__img">
                            </div>
                            {% endif %}
             
                        <div class="bs-blog-article__info">
                            <h4 class="bs-blog-article__title"> {{art.title}}</h4>
                            <p class="bs-blog-article__content"> {{art.content | strip_html | truncate: 120, '...'}}</p>
                            <a class="bs-blog-article__btn btn btn-link"  href="{{art.link}}" title="{{art.title}}">ver más</a>
                        </div>
                        
                        </div>
                    </div>
                {% endfor %}
            </div>
        </div>
    {% endif %}
    {{'paginacion' | get_component }}
</div><!-- container-->
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE ROSARIO
Blog
<!-- Preload de la primera imagen Crítica-->
{% if articles.size > 0 and articles[0].imagen.size > 0 %}
  <link rel="preload" as="image" href="{{ articles[0].imagen | image_url: 'M' }}">
{% endif %}

{{ 'migas de pan' | get_component }}
<div class="container-xxl">
    <h2><a class="bs-home-title" href="/blog">Blog</a></h2>
    {% if articles.size > 0 %}
        <!-- Wrapper para scroll infinito -->
        <div id="content-wrapper">
            <div class="grid bs-blog">
                {% for art in articles %}
                    <div class="item"> 
                        <div class="bs-blog-article">
                            {% if art.imagen.size > 0 %}
                                <a class="bs-img-square bs-blog-article__img" href="{{ art.link }}" title="{{ art.title }}">
                                    <picture>
                                        <!-- Pantallas grandes (escritorio) -->
                                        <source srcset="{{ art.imagen | image_url: 'L' }} 1x, {{ art.imagen | image_url: 'X' }} 2x" media="(min-width: 1200px)">
                                        <!-- Pantallas medianas (tablets) -->
                                        <source srcset="{{ art.imagen | image_url: 'M' }} 1x, {{ art.imagen | image_url: 'L' }} 2x" media="(min-width: 800px)">
                                        <!-- Pantallas pequeñas (smartphones grandes) -->
                                        <source srcset="{{ art.imagen | image_url: 'S' }} 1x, {{ art.imagen | image_url: 'M' }} 2x" media="(min-width: 400px)">
                                        <!-- Pantallas móviles (smartphones pequeños) -->
                                        <source srcset="{{ art.imagen | image_url: 'M' }} 1x, {{ art.imagen | image_url: 'M' }} 2x" media="(min-width: 0px)">
                                        <img src="{{ art.imagen | image_url: 'M' }}" 
                                             onerror="this.onerror=null;this.src='{{ art.imagen }}';"
                                             alt="{{ art.title }}" loading="{% if forloop.last %}lazy{% endif %}">
                                    </picture>  
                                </a>
                            {% else %}
                                <div class="bs-img-square bs-blog-article__img"></div>
                            {% endif %}
                            
                            <div class="bs-blog-article__info">
                                <h4 class="bs-blog-article__title">{{ art.title }}</h4>
                                <p class="bs-blog-article__content">{{ art.content | strip_html | truncate: 120, '...' }}</p>
                                <a class="bs-blog-article__btn btn btn-link" href="{{ art.link }}" title="{{ art.title }}">ver más</a>
                            </div>
                        </div>
                    </div>
                {% endfor %}
            </div>
        </div>
        
        <!-- Paginación dentro del if -->
        {{ 'paginacion' | get_component }}
    {% endif %}
</div><!-- container -->
Colección – Buscador – Marca > Orden
{% assign item_in_page = item_per_page %}
{% for i in collection %}
   {%if forloop.last %} 
      {% if forloop.index < item_per_page %} 
         {% assign item_in_page = forloop.index %}
      {%endif%}
   {%endif%}
{% endfor %}
{%if total_item == 0%}
   {% assign item_in_page = 0 %}
{% endif %}
{% unless current_url contains 'search' %}
    <div class="row pb-3">
        <div class="col">
            Mostrando <span id="products-shown">{{item_in_page}}</span> de {{total_item}}
        </div>
        <div class="col-md-3 col-sm-6 ">
            <select class="custom-select" data-bs="collection.sort">
                <option value="">Ordenar por</option>
                {% for sort in collection.sorting %} 
                    <option value="{{sort[1].url}}"{% if current_url contains sort[1].url %} selected{% endif %}>{{sort[1].title}}</option>
                {% endfor %}
            </select>
        </div>
    </div>
{% endunless %}
Colección – Buscador – Marca
<section class="bs-collection">
    {{ 'migas de pan' | get_component }}
    <div class="container">
        <!-- Imagen de la colección -->
        {% if collection.image %}
        <div class="d-flex justify-content-center mb-2">
            <img class="image-collection img-fluid rounded" src="{{ collection.image }}" alt="{{ title }}">
        </div>
        {% endif %}

        <div class="row">
            <!-- Título y descripción de la colección -->
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>

            <!-- Filtros sticky -->
            <aside class="col-lg-3 mb-4 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{ 'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>

            <article class="col-lg-9">
                {% if collection.size > 0 %}
                <!-- Orden de la colección -->
                <section class="mb-3">
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                </section>

                <!-- Lista de productos de la colección -->
                <section class="mb-4">
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                </section>

                <!-- Paginación -->
                <nav class="d-flex justify-content-center">
                    {{ 'paginacion' | get_component }}
                </nav>
                {% else %}
                <!-- Mensaje de error si no hay productos -->
                    {{ 'error > coleccion' | get_component }}
                {% endif %}
            </article>
        </div>
    </div>
</section>
TEMPLATE JOAQUIN
Blog
{{'migas de pan' | get_component }}
<div class="container-xxl">
    <h2><a class="bs-title" href="/blog">Blog</a></h2>
    {% if articles.size > 0 %}
        <!-- Wrapper para scroll infinito -->
        <div id="content-wrapper">
            <div class="grid bs-blog">
                {% for art in articles %}
                    <div class="item">
                        <div class="bs-blog-article"> 
                            {% if art.imagen.size > 0 %}
                                <a class="bs-img-square bs-blog-article__img" 
                                    href="{{art.link}}" title="{{art.title}}">
                                    <picture class='img-bg-blur' 
                                            style="--img-bg-blur: url('{{art.imagen | image_url: 'S'}}')">
                                        <source srcset="{{art.imagen | image_url: 'X'}}" media="(min-width:800px)">
                                        <source srcset="{{art.imagen | image_url: 'L'}}" media="(min-width:400px)">
                                        <source srcset="{{art.imagen | image_url: 'M'}}" media="(min-width:240px)">
                                        <source srcset="{{art.imagen | image_url: 'S'}}" media="(min-width:0px)">
                                        <img loading="lazy" src="{{art.imagen | image_url: 'L'}}" 
                                                onerror="this.onerror=null;this.src='{{art.imagen}}';"
                                                alt="{{art.title}}">
                                    </picture>  
                                </a>
                            {% else %}
                                <div class="bs-img-square bs-blog-article__img"></div>
                            {% endif %}
                            <div class="bs-blog-article__info">
                                <h4 class="bs-blog-article__title"> {{art.title}}</h4>
                                <p class="bs-blog-article__content"> {{art.content | strip_html | truncate: 120, '...'}}</p>
                                <a class="bs-blog-article__btn btn"  href="{{art.link}}" title="{{art.title}}">ver más</a>
                            </div>
                        </div>
                    </div>
                {% endfor %}
            </div>
        </div>
        
        {{'paginacion' | get_component }}
    {% endif %}
</div><!-- container-->
Colección – Buscador – Marca > Orden
<div class="row bs-collection-order align-items-center">
    <div class="col">Mostrando <span id="products-shown">{{ collection.products.size }}</span> de {{collection.size}}</div>
    <div class="col-lg-4 col-md-5 col-sm-6 ">
        <select class="custom-select" data-bs="collection.sort">
            {% for sort in collection.sorting %}
            <option value="{{sort[1].url}}" {% if sort[1].selected %}selected{% endif %}>{{sort[1].title}}</option>
            {% endfor %}
        </select>
    </div>
</div>
Colección – Buscador – Marca
<section class="bs-collection mb-3">
    {{'migas de pan'| get_component }}
    
    {% if collection.image and pagination.prev == false %}
        <picture>
            <source srcset="{{ collection.image | image_url: "X" }}" media="(min-width:1200px)">
            <source srcset="{{ collection.image | image_url: "X" }}" media="(min-width:800px)">
            <source srcset="{{ collection.image | image_url: "L" }}" media="(min-width:400px)">
            <source srcset="{{ collection.image | image_url: "M" }}" media="(min-width:240px)">
            <source srcset="{{ collection.image | image_url: "S" }}" media="(min-width:100px)">
            <img 
            class="bs-collection__image" src="{{ collection.image | image_url: "M"}}" alt="{{collection.title}}" onerror="this.onerror=null;this.src='{{collection.image}}';">
        </picture>
    {%endif%}
    <div class="container bs-collection__container" >
        <div class="row">
            <div class="col-12 text-center mb-4">
                <h1 class="bs-collection__title">
                    {% if current_url contains '/search?' %}
                    <div class="bs-collection__subtitle text-muted">Resultado de Búsqueda para:</div>
                    {{ title }}
                    {% else %}
                    {{ title }}
                    {% endif %}
                </h1>
                {% if collection.description.size > 0 %}
                <p class="bs-collection__description text-muted mt-2 mx-auto" style="max-width: 1000px; font-size: 1rem; line-height: 1.5;">
                    {{ collection.description }}
                </p>
                {% endif %}
            </div>
            
            <!-- Filtros sticky -->
            <aside class="col-lg-3 sidebar-filters">
                <div class="sidebar-filters__inner">
                    {{'Coleccion - Buscador - Marca > filtros' | get_component }}
                </div>
            </aside>
            
            {% assign search-error1 = site.url | prepend: "https://" | append: "/search" %}
            {% assign search-error2 = site.url | prepend: "https://" | append: "/search/" %}
            {% assign search-error3 = site.url | prepend: "https://" | append: "/search?" %}
            {% if collection.size < 1 or current_url == search-error1 or current_url == search-error2 or current_url == search-error3  %}
            <div class="col-12 col-lg-9">
                {{'error > coleccion' | get_component }}
            </div>
            {% else %}
                <article class="col-lg-9">
                {% if collection.size > 0 %}
                    {{ 'Coleccion - Buscador - Marca > orden' | get_component }}
                    
                    <!-- Wrapper para scroll infinito -->
                    <div id="products-wrapper">
                        {{ 'Coleccion' | get_component }}
                    </div>
                    
                    {{ 'paginacion' | get_component }}
                {% endif %}
            </article>
            {%endif%}
        </div>
    </div>
</section>

Códigos css

Warning

Incorporar el código al final del style.css o en modificaciones.css

Código CSS
/**********************
 paginación 2.0
***********************/

 /* Sidebar sticky */
    .sidebar-filters {
        position: relative;
    }

    .sidebar-filters__inner {
        position: sticky;
        top: 70px;
        max-height: calc(100vh - 140px);
        overflow-y: auto;
        padding-bottom: 20px;
    }

    .sidebar-filters__inner::-webkit-scrollbar {
        width: 4px;
    }

    .sidebar-filters__inner::-webkit-scrollbar-track {
        background: transparent;
    }

    .sidebar-filters__inner::-webkit-scrollbar-thumb {
        background: #ddd;
        border-radius: 4px;
    }

    @media (max-width: 991.98px) {
        .sidebar-filters__inner {
            position: relative;
            top: 0;
            max-height: none;
            overflow-y: visible;
        }
    }

    /* Loader */
    #infinite-scroll-loader {
        display: none;
        width: 20px;
        height: 20px;
        margin: 2rem auto;
        border: 2px solid #e0e0e0;
        border-top-color: #999;
        border-radius: 50%;
        animation: spin 1.5s linear infinite;
    }

    #infinite-scroll-loader.active {
        display: block;
    }

    @keyframes spin {
        to { transform: rotate(360deg); }
    }

    /* Sentinel */
    #scroll-sentinel {
        height: 1px;
        visibility: hidden;
    }

    /* Indicador de scroll */
    #scroll-indicator {
        display: none;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 8px;
        padding: 1.5rem 0;
        color: #999;
        font-size: 0.85rem;
    }

    #scroll-indicator svg {
        width: 24px;
        height: 24px;
        animation: bounceDown 1.5s ease-in-out infinite;
    }

    #scroll-indicator.active {
        display: flex;
    }

    #scroll-indicator.hidden {
        display: none !important;
    }

    @keyframes bounceDown {
        0%, 100% {
            transform: translateY(0);
            opacity: 0.5;
        }
        50% {
            transform: translateY(8px);
            opacity: 1;
        }
    }

    /* Botón cargar más */
    #load-more-btn {
        display: none;
        align-items: center;
        justify-content: center;
        gap: 8px;
        width: 100%;
        max-width: 200px;
        margin: 2rem auto;
        padding: 12px 24px;
        background: transparent;
        border: 1px solid #ddd;
        border-radius: 30px;
        color: #666;
        font-size: 0.9rem;
        cursor: pointer;
        transition: all 0.2s ease;
    }

    #load-more-btn:hover {
        border-color: #999;
        color: #333;
        transform: translateY(2px);
    }

    #load-more-btn svg {
        width: 18px;
        height: 18px;
        transition: transform 0.2s ease;
    }

    #load-more-btn:hover svg {
        transform: translateY(3px);
    }

    #load-more-btn.active {
        display: flex;
    }

    #load-more-btn.loading {
        pointer-events: none;
        opacity: 0.6;
    }

    #load-more-btn.loading svg {
        animation: bounce 1s infinite;
    }

    @keyframes bounce {
        0%, 100% { transform: translateY(0); }
        50% { transform: translateY(5px); }
    }
⚠️ **GitHub.com Fallback** ⚠️