Loop

Control how loop items appear in index.php, archive.php, and search.php using four layout options: horizontal cards, grid cards, overlay cards, or custom. All are customizable via context-aware filters.

How it works

Bootscore provides 4 templates for calling the loop in archive.php, index.php, and search.php. These templates can be found in the theme folder: template-parts/loop/.

Note that these templates are also used by the bs Loop, bs Isotope and bs Swiper plugins. If you override these templates in your child theme or use non-specific filters, the templates will be overridden for these plugins as well.

Checking the context parameter allows modifying these templates without affecting the plugin ones. It allows targeting, for example, only the archive loop by using a single parameter:

// Apply only to archive, search, and index templates
if (in_array($context, ['archive', 'search', 'index'])) {
  // Do stuff here
}

Templates

Horizontal cards (default)

The cards-horizontal.php file is the default loop template. It displays items in horizontal cards that switch to vertical cards below md screen sizes:

The items are wrapped in a grid that uses row-cols-1 on all screen sizes:

xssmmdlgxl2xl
row-cols-1row-cols-1row-cols-1row-cols-1row-cols-1row-cols-1

The horizontal grid layout can be customized via a filter, for instance, to create a row-cols-xl-2 g-2 mb-2 grid:

/**
 * Customize horizontal grid columns
 */
add_filter('bootscore/class/loop/horizontal/col', function($classes, $context) {
  
  // Apply only to specific templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'row row-cols-1 row-cols-xl-2 g-2 mb-2';
  }
  
  // Keep default for others (like shortcodes)
  return $classes;
  
}, 10, 2);

Grid

The grid layout displays loop items in vertical grid cards using cards.php. It can be enabled via a filter:

/**
 * Enable grid layout only on archive, search, and index pages
 */
add_filter('bootscore/loop/layout', function($layout, $context) {
  
  // Apply only to archive, search, and index templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'grid'; // Override default 'horizontal'
  }
  
  return $layout; // Keep original for other contexts
}, 10, 2);

The default grid template uses the following column classes:

xssmmdlgxl2xl
row-cols-1row-cols-sm-1row-cols-md-2row-cols-lg-3row-cols-xl-4row-cols-2xl-4

The grid layout can be customized via a filter, for instance, to create a row-cols-2 row-cols-md-2 row-cols-lg-2 row-cols-xl-3 g-3 mb-3 grid:

/**
 * Enable grid layout only on archive, search, and index pages
 */
add_filter('bootscore/loop/layout', function($layout, $context) {
  
  // Apply only to archive, search, and index templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'grid'; // Override default 'horizontal'
  }
  
  return $layout; // Keep original for other contexts
}, 10, 2);

/**
 * Customize grid columns
 */
add_filter('bootscore/class/loop/grid/col', function($classes, $context) {
  
  // Apply only to specific templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'row row-cols-2 row-cols-md-2 row-cols-lg-2 row-cols-xl-3 g-3 mb-3';
  }
  
  // Keep default for others (like shortcodes)
  return $classes;
  
}, 10, 2);

Cards overlay

The overlay layout displays loop items as image overlay cards using cards-overlay.php. It can be enabled via a filter.

The overlay template requires featured images and uses the card-img-overlay class. Note that content should not be larger than the height of the image. If content exceeds the image height, it will be displayed outside the image. This example may broken on mobile.

/**
 * Enable overlay layout only on archive, search, and index pages
 */
add_filter('bootscore/loop/layout', function($layout, $context) {
  
  // Apply only to archive, search, and index templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'overlay'; // Override default 'horizontal'
  }
  
  return $layout; // Keep original for other contexts
}, 10, 2);

The items are wrapped in a grid that uses row-cols-1 on all screen sizes:

xssmmdlgxl2xl
row-cols-1row-cols-1row-cols-1row-cols-1row-cols-1row-cols-1

The overlay grid layout can be customized via a filter – for instance, to create a row-cols-1 row-cols-md-2 g-3 mb-3 grid. To avoid content displaying outside the card, certain elements can be hidden:

/**
 * Enable overlay layout only on archive, search, and index pages
 */
add_filter('bootscore/loop/layout', function($layout, $context) {
  
  // Apply only to archive, search, and index templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'overlay'; // Override default 'horizontal'
  }
  
  return $layout; // Keep original for other contexts
}, 10, 2);

/**
 * Customize overlay grid columns
 */
add_filter('bootscore/class/loop/horizontal/col', function($classes, $context) {
  
  // Apply only to specific templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'row row-cols-1 row-cols-md-2 g-3 mb-3';
  }
  
  // Keep default for others (like shortcodes)
  return $classes;
  
}, 10, 2);

/**
 * Hide category badge on archive, search, and index pages
 */
add_filter('bootscore/loop/category', function($show, $context) {
  // Check the template context
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    return false; // Hide meta on these templates
  }
  
  return $show; // Keep original for others
}, 10, 2);

/**
 * Hide meta on archive, search, and index pages
 */
add_filter('bootscore/loop/meta', function($show, $context) {
  // Check the template context
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    return false; // Hide meta on these templates
  }
  
  return $show; // Keep original for others
}, 10, 2);



/**
 * Hide read-more on archive, search, and index pages
 */
add_filter('bootscore/loop/read-more', function($show, $context) {
  // Check the template context
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    return false; // Hide meta on these templates
  }
  
  return $show; // Keep original for others
}, 10, 2);


/**
 * Hide tags badge on archive, search, and index pages
 */
add_filter('bootscore/loop/tags', function($show, $context) {
  // Check the template context
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    return false; // Hide meta on these templates
  }
  
  return $show; // Keep original for others
}, 10, 2);

Custom

Draw freely your own custom loop using the custom.php template. This is an empty template that contains three action hooks: bootscore_before_loop_itembootscore_custom_loop_item, and bootscore_after_loop_item. Hook into these actions to build your custom loop:

/**
 * Enable custom layout only on archive, search, and index pages
 */
add_filter('bootscore/loop/layout', function($layout, $context) {
  
  // Apply only to archive, search, and index templates
  if (in_array($context, ['archive', 'search', 'index'])) {
    return 'custom'; // Override default 'horizontal'
  }
  
  return $layout; // Keep original for other contexts
}, 10, 2);


/**
 * Draw freely a custom loop items grid
 * Only runs on archive, search, and index templates
 */

// Before loop, open row
add_action('bootscore_before_loop', function($context) {
  if (in_array($context, ['archive', 'search', 'index'])) {
    echo '<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 mb-4">';
  }
});

// Before loop item, open col - check global template context
add_action('bootscore_before_loop_item', function($context) {
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    echo '<div class="col">';
  }
});

// Custom loop item
add_action('bootscore_custom_loop_item', function($context) {
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    ?>
    <article class="card shadow h-100 rounded-5">
      
      <?php if ( has_post_thumbnail() ) : ?>
        <a class="pt-2 px-2" href="<?php the_permalink(); ?>" aria-hidden="true" tabindex="-1">
          <?php the_post_thumbnail('medium', array(
            'class' => 'card-img',
            'style' => 'border-radius: calc(var(--bs-border-radius-xxl) - 0.5rem);' // border-radius-xxl - inner-padding p-2
          )); ?>
        </a>
      <?php endif; ?>
      
      <div class="card-body p-4 d-flex flex-column">
        
        <?php the_title('<h2 class="h5">', '</h2>'); ?>

        <p class="card-text small fw-lighter">
          <?= esc_html(wp_strip_all_tags(get_the_excerpt())); ?>
        </p>

        <p class="card-text mt-auto">
          <a class="btn btn-dark btn-sm rounded-pill shadow px-3 d-block" href="<?php the_permalink(); ?>">
            Learn more <i class="fa-solid fa-arrow-right"></i>
          </a>
        </p>

      </div>
      
    </article>
    <?php
  }
});

// After loop item, close col - check global template context
add_action('bootscore_after_loop_item', function($context) {
  $template_context = $GLOBALS['bootscore_template_context'] ?? '';
  if (in_array($template_context, ['archive', 'search', 'index'])) {
    echo '</div>';
  }
});

// After loop, close row
add_action('bootscore_after_loop', function($context) {
  if (in_array($context, ['archive', 'search', 'index'])) {
    echo '</div>';
  }
});