Skip to main content

Load More v1.0.0

Allow user to reveal additional content by pressing a button to load more items dynamically.

Default Setup Anchor (Default Setup)

Experimental: Experimental examples or components may require additional work, further testing, and may not be fully supported or accessible. They should be carefully evaluated before being used in a production environment.

<div class="load-more">

    <div class="load-more__msg" aria-live="polite"></div>
  
    <ul class="load-more__container" role="list">
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 1</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 2</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 3</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 4</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 5</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 6</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 7</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 8</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 9</span>
  
        </a>
  
      </li>
  
      <li class="load-more__item">
  
        <a href="#!">
  
          <img src="https://radancy.dev/placeholder.png" alt="">
  
          <span>Item 10</span>
  
        </a>
  
      </li>
  
    </ul>
  
  </div>
/*!

  Radancy Component Library: Load More

  Contributor(s): 
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

$base-color: #6F00EF;

.load-more {

  // Assistive Tech Message - Do not remove!

  &__msg {
  clip-path: inset(100%);
  clip: rect(0 0 0 0);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
  }

  &__container {
  list-style: none;
  margin: 0;
  padding: 0;

    @media(min-width: 48.625em) {

      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;

    }

  }

  &__item {
  margin-bottom: 1em;

    @media(min-width: 48.625em) {

      width: 33.3%;

    }

    a {
    display: block;
    margin: .5em;
    padding: .5em;
    }

    img {
    display: block;
    width: 100%;
    }

  }

  &__btn {
  background-color: $base-color;
  border: 0;
  color: #fff;
  display: block;
  line-height: normal;
  margin: 0 auto;
  max-width: calc(200rem / 16);
  padding: 1.5em;
  text-align: center;
  text-transform: uppercase;

    &[disabled] {
    opacity: .5;
    }

  }

}
/*!

  Radancy Component Library: Load More

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: jQuery

*/

(function() {

  // Display which component in use via console:

  console.log("%cLoad More%cv1.0.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var $loadMore = $(".load-more");
  var $loadMoreItem = $(".load-more__item");
  var $loadMoreMsg = $(".load-more__msg");
  var loadMoreBtnTxt = "Load More";
  var loadMoreBtnFin = "All Done!";
  var loadMoreNewItemTxt =  " new items have been loaded.";
  var loadMoreNewItemSingleTxt =  " new item has been loaded.";
  var loadMoreComplete = "All content has been loaded.";
  var loadMoreDelay = 500;
  var loadMoreDefault = 3;

  // Hide all items after nth item

  $loadMore.each(function(e) {

    if ($(this).data("load-more-show")) {

      var loadMoreShow = $(this).data("load-more-show");

    } else {

      var loadMoreShow = loadMoreDefault;

    }

    $(this).find($loadMoreItem).slice(loadMoreShow).prop("hidden", "true");

  });

  // Add Button

  $loadMore.append("<button class='load-more__btn'>" + loadMoreBtnTxt + "</button>");

  // Apply button class to variable

  var $loadMoreBtn = $(".load-more__btn");

  // Button Action: Message

  $($loadMoreBtn).on("itemsDisplayed", function(e, totalCount){

    var $loadMoreItemsHidden = $(this).parent().find(".load-more__item[hidden]");

    if(!$loadMoreItemsHidden.length) {

      // Change button text when done

      $(this).prop("disabled", "true").text(loadMoreBtnFin);

      if (totalCount === 1) {

        $(this).parent().find($loadMoreMsg).html(totalCount + loadMoreNewItemSingleTxt + " " + loadMoreComplete);

      } else {

        $(this).parent().find($loadMoreMsg).html(totalCount + loadMoreNewItemTxt + " " + loadMoreComplete);

      }

    }

  });

  $loadMoreBtn.on("click", function() {

    // Get Hidden Item(s)

    var $loadMoreItemsHidden = $(this).parent().find(".load-more__item[hidden]");

    // Remove hidden attr on every group of nth item(s)

    if ($(this).parent().data("load-more-show")) {

      var itemsToLoad =  $(this).parent().data("load-more-show");

    } else {

      var itemsToLoad = loadMoreDefault;

    }

    var itemsToRemove = $loadMoreItemsHidden.slice(0, itemsToLoad);

    itemsToRemove.slice(0, itemsToLoad).removeAttr("hidden");

    var totalItems = itemsToRemove.length;

    var loadMoreTxt = totalItems + loadMoreNewItemTxt;

    $(this).parent().find($loadMoreMsg).html(loadMoreTxt);

    // In not knowing what kind of content may exist in item, we are applying temporary focus to item itself.
    // Question: Is it better to apply focus here or keep focus on the 'Load More' button itself, allowing
    // keyboard user to navigate through newly revealed items?
    // Also, is it better to put focus on item or first focusable element within item?
    // TODO: More research will be required.

    //  $loadMoreItemsHidden.first().attr("tabindex", "-1").focus();

    var $focusElms = "a, audio, button, input, select, video";

    $loadMoreItemsHidden.find($focusElms).first().focus();

    $(this).trigger("itemsDisplayed", [totalItems]);

    // Remove message
    // Note: Message needs to be removed so we can add it again
    // when loading next selection of items.

    setTimeout(function(){

      $loadMoreMsg.empty();

    }, loadMoreDelay);

  });

})();

Properties Anchor (Properties)

Use the following properties to configure this component.

Attribute Applies To Note Description
data-load-more-max .load-more Number, Optional
Used to set the maximum number of items first shown on page load and items shown when the "Load More" button is pressed. The default is 3.

Class Applies To Note Description
.load-more div, section Mandatory
Used on the parent element that wraps your list.
.load-more__btn button Component
Used on the button that loads more content.
.load-more__container ul, ol Mandatory
Used on the list element that wraps your list items.
.load-more__item li Mandatory
Used on the list items that wrap your content.
.load-more__msg div Mandatory
Used to alert assistive technology users that a change has occured on the page after clicking .load-more__btn.

Report Issues

Find a bug? Want a new feature? Report it on JIRA. You're so awesome!