Infinite scroll

Bootstrap 5 Infinite scroll

This feature adds a scroll event listener, which is applied to either the window or the component it's attached to (if the component has the overflow property set to scroll in the axis that matches the scroll direction you're using). It calls a callback method each time a user reaches the end of a page or container.

Note: Read the API tab to find all available options and advanced customization

Required ES init: InfiniteScroll *
* UMD autoinits are enabled by default. This means that you don't need to initialize the component manually. However if you are using MDBootstrap ES format then you should pass the required components to the initMDB method.

Basic example

Scroll down the container below to add more items.

Note: Your element should be scrollable, for example, it should have overflow-y: scroll property like in the example below.

  • Angry
  • Dizzy
  • Flushed
  • Frown
  • Grimace
  • Grin
        
            
                <ul
                  class="container list-group infinite-scroll-basic"
                  id="basic-example"
                  data-mdb-infinite-scroll-init
                  style="max-height: 261px; overflow-y: scroll"
                >
                  <li class="list-group-item d-flex align-items-center">
                    <i class="far fa-angry fa-3x me-4"></i> Angry
                  </li>
                  <li class="list-group-item d-flex align-items-center">
                    <i class="far fa-dizzy fa-3x me-4"></i> Dizzy
                  </li>
                  <li class="list-group-item d-flex align-items-center">
                    <i class="far fa-flushed fa-3x me-4"></i> Flushed
                  </li>
                  <li class="list-group-item d-flex align-items-center">
                    <i class="far fa-frown fa-3x me-4"></i> Frown
                  </li>
                  <li class="list-group-item d-flex align-items-center">
                    <i class="far fa-grimace fa-3x me-4"></i> Grimace
                  </li>
                  <li class="list-group-item d-flex align-items-center">
                    <i class="far fa-grin fa-3x me-4"></i> Grin
                  </li>
                </ul>
              
        
    
        
            
                import { InfiniteScroll, initMDB } from "mdb-ui-kit";

                initMDB({ InfiniteScroll });

                // An array of icon names
                const icons = [
                  'Sad-Tear',
                  'Meh-Blank',
                  'Smile-Wink',
                  'Tired',
                  'Surprise',
                  'Kiss-Beam',
                  'Laugh-Squint',
                ];

                // Get a scrollable container using an id attribute
                const basicElement = document.getElementById('basic-example');

                // An index of elements added after scrolling to the end of the container
                let itemIndex = 0;

                // items - an array of the created elements using the loop through icons array
                const items = icons.map((icon) => {
                  // Create a list item element
                  const element = document.createElement('li');

                  // Change HTML code inside created list element using icon we are currently working on
                  element.innerHTML = `
                    <li class="list-group-item d-flex align-items-center">
                      <i class="far fa-${icon.toLowerCase()} fa-3x me-4"></i>${icon}
                    </li>
                  `;

                  // Return ready element
                  return element;
                });

                // Add an event listener to the scrollable container. The event below is triggered when a user scrolls to the end of the container
                basicElement.addEventListener('completed.mdb.infiniteScroll', () => {
                  // Return nothing when user appended all of the generated items
                  if (itemIndex === icons.length - 1) return;

                  // Append next element to the scrollable container
                  basicElement.appendChild(items[itemIndex]);

                  // Increment amount of items that are appended
                  itemIndex++;
                });
              
        
    
        
            
                // An array of icon names
                const icons = [
                  'Sad-Tear',
                  'Meh-Blank',
                  'Smile-Wink',
                  'Tired',
                  'Surprise',
                  'Kiss-Beam',
                  'Laugh-Squint',
                ];

                // Get a scrollable container using an id attribute
                const basicElement = document.getElementById('basic-example');

                // An index of elements added after scrolling to the end of the container
                let itemIndex = 0;

                // items - an array of the created elements using the loop through icons array
                const items = icons.map((icon) => {
                  // Create a list item element
                  const element = document.createElement('li');

                  // Change HTML code inside created list element using icon we are currently working on
                  element.innerHTML = `
                    <li class="list-group-item d-flex align-items-center">
                      <i class="far fa-${icon.toLowerCase()} fa-3x me-4"></i>${icon}
                    </li>
                  `;

                  // Return ready element
                  return element;
                });

                // Add an event listener to the scrollable container. The event below is triggered when a user scrolls to the end of the container
                basicElement.addEventListener('completed.mdb.infiniteScroll', () => {
                  // Return nothing when user appended all of the generated items
                  if (itemIndex === icons.length - 1) return;

                  // Append next element to the scrollable container
                  basicElement.appendChild(items[itemIndex]);

                  // Increment amount of items that are appended
                  itemIndex++;
                });
            
        
    

Direction

Use data-mdb-infinite-direction to define the scrolling direction.

Angry Dizzy Flushed Grimace Grin
        
            
              <div 
                class="py-3 text-center" 
                id="direction-example"
                style="max-width: 1500px; overflow-x: scroll; white-space: nowrap;" 
                data-mdb-infinite-scroll-init
                data-mdb-infinite-direction="x"
              >
                <span class="mx-5"><i class="far fa-angry fa-3x me-4"></i> Angry</span>
                <span class="mx-5"><i class="far fa-dizzy fa-3x me-4"></i> Dizzy</span>
                <span class="mx-5"><i class="far fa-flushed fa-3x me-4"></i> Flushed</span>
                <span class="mx-5"><i class="far fa-grimace fa-3x me-4"></i> Grimace</span>
                <span class="mx-5"><i class="far fa-grin fa-3x me-4"></i> Grin</span>
              </div>
            
        
    
        
            
              import { InfiniteScroll, initMDB } from "mdb-ui-kit";

              initMDB({ InfiniteScroll });

              // Get a scrollable container using an id attribute
              const directionElement = document.getElementById('direction-example');

              // An index of elements added after scrolling to the end of the container
              let itemIndex = 0;

              // An array of icon names
              const icons = [
                'Sad-Tear',
                'Meh-Blank',
                'Smile-Wink',
                'Tired',
                'Surprise',
                'Kiss-Beam',
                'Laugh-Squint',
              ];

              // items - an array of the created elements using the loop through icons array
              const items = icons.map((icon) => {
                // Create a span element
                const element = document.createElement('span');

                // Add class mx-5 to the created element, which defines left and right margin
                element.classList.add('mx-5');

                // Change HTML code inside created span element using icon we are currently working on
                element.innerHTML = `
                  <i class="far fa-${icon.toLowerCase()} fa-3x me-4"></i>
                  ${icon}
                `;

                // Return ready element
                return element;
              });

              // Add an event listener to the scrollable container. The event below is triggered when a user scrolls to the end of the container
              directionElement.addEventListener('completed.mdb.infiniteScroll', () => {
                // Return nothing when user appended all of the generated items
                if (itemIndex === items.length - 1) return;

                // Append next element to the scrollable container
                directionElement.appendChild(items[itemIndex]);

                // Increment amount of items that are appended
                itemIndex++;
              });
            
        
    
        
            
              // Get a scrollable container using an id attribute
              const directionElement = document.getElementById('direction-example');

              // An index of elements added after scrolling to the end of the container
              let itemIndex = 0;

              // An array of icon names
              const icons = [
                'Sad-Tear',
                'Meh-Blank',
                'Smile-Wink',
                'Tired',
                'Surprise',
                'Kiss-Beam',
                'Laugh-Squint',
              ];

              // items - an array of the created elements using the loop through icons array
              const items = icons.map((icon) => {
                // Create a span element
                const element = document.createElement('span');

                // Add class mx-5 to the created element, which defines left and right margin
                element.classList.add('mx-5');

                // Change HTML code inside created span element using icon we are currently working on
                element.innerHTML = `
                  <i class="far fa-${icon.toLowerCase()} fa-3x me-4"></i>
                  ${icon}
                `;

                // Return ready element
                return element;
              });

              // Add an event listener to the scrollable container. The event below is triggered when a user scrolls to the end of the container
              directionElement.addEventListener('completed.mdb.infiniteScroll', () => {
                // Return nothing when user appended all of the generated items
                if (itemIndex === items.length - 1) return;

                // Append next element to the scrollable container
                directionElement.appendChild(items[itemIndex]);

                // Increment amount of items that are appended
                itemIndex++;
              });
            
        
    

Spinners and asynchronous data

        
            
            <div class="py-3 text-center" id="spinners-and-async-example" data-mdb-infinite-scroll-init style="max-height: 500px; overflow-y: scroll">
              <div id="images">
                <img src="https://mdbcdn.b-cdn.net/img/Photos/Slides/img%20(100).webp" class="img-fluid mb-3"/>
                <img src="https://mdbcdn.b-cdn.net/img/Photos/Slides/img%20(105).webp" class="img-fluid mb-3"/>
                <img src="https://mdbcdn.b-cdn.net/img/Photos/Slides/img%20(106).webp" class="img-fluid mb-3"/>
              </div>
              <div class="spinner-border mx-auto" id="spinner" style="display: none"></div>
            </div>
            
        
    
        
            
              import { InfiniteScroll, initMDB } from "mdb-ui-kit";

              initMDB({ InfiniteScroll });

              // Get a spinner, container with images and scrollable container using an id attribute
              const spinner = document.getElementById('spinner');
              const imagesContainer = document.getElementById('images');
              const infiniteContainer = document.getElementById('spinners-and-async-example');

              // Function that generates image with data from API
              const createImg = url => {
                // Create an image element
                let imgElement = document.createElement('img');

                // Add .img-fluid class to the element, it will adjust size of it to the container
                imgElement.classList.add('img-fluid');

                // Set a src attribute using parameter that is passed to the function
                imgElement.setAttribute('src', url);

                // Return ready image element
                return imgElement;
              }

              // Function that loads next image
              const loadImages = () => {
                // Make spinner visible
                spinner.style.display = 'block';

                // Fetch your API
                fetch('YOUR_API/getNextItem')
                  .then(response => response.json)
                  .then(imgUrl => {
                    // Hide spinner after data loads
                    spinner.style.display = 'none';

                    // Append an image element generated by createImg function to the container with images
                    imagesContainer.appendChild(createImg(imgUrl));
                  });
              }

              // Add an event listener to the scrollable container. The event below is triggered when a user scrolls to the end of the container
              infiniteContainer.addEventListener('completed.mdb.infiniteScroll', loadImages);
            
        
    
        
            
              // Get a spinner, container with images and scrollable container using an id attribute
              const spinner = document.getElementById('spinner');
              const imagesContainer = document.getElementById('images');
              const infiniteContainer = document.getElementById('spinners-and-async-example');

              // Function that generates image with data from API
              const createImg = url => {
                // Create an image element
                let imgElement = document.createElement('img');

                // Add .img-fluid class to the element, it will adjust size of it to the container
                imgElement.classList.add('img-fluid');

                // Set a src attribute using parameter that is passed to the function
                imgElement.setAttribute('src', url);

                // Return ready image element
                return imgElement;
              }

              // Function that loads next image
              const loadImages = () => {
                // Make spinner visible
                spinner.style.display = 'block';

                // Fetch your API
                fetch('YOUR_API/getNextItem')
                  .then(response => response.json)
                  .then(imgUrl => {
                    // Hide spinner after data loads
                    spinner.style.display = 'none';

                    // Append an image element generated by createImg function to the container with images
                    imagesContainer.appendChild(createImg(imgUrl));
                  });
              }

              // Add an event listener to the scrollable container. The event below is triggered when a user scrolls to the end of the container
              infiniteContainer.addEventListener('completed.mdb.infiniteScroll', loadImages);
            
        
    

Window

You can apply the mdb.InfiniteScroll instance to a window.

Note: You have to initialize an instance on your own, using JavaScript. If you are using other containers, you have to make a check if your event.target is a window.

        
            
              <!--Main layout-->
              <main class="my-4">
                <div class="container">
                  <!--Section: Posts-->
                  <section class="text-center mb-4" id="posts">
                    <div class="row">
                      <div class="col-md-6 mb-4">
                        <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init>
                          <img
                            data-mdb-lazy-load-init
                            data-mdb-lazy-src="https://mdbcdn.b-cdn.net/img/Photos/Others/images/29.webp"
                            data-mdb-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
                            class="w-100"
                          />
                          <a href="#!">
                            <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);"></div>
                          </a>
                        </div>
                        <h5>This is an title of the article</h5>
                        <p>
                          Lorem ipsum dolor sit amet consectetur adipisicing elit.
                          Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
                          illo. Quos architecto deserunt saepe.
                        </p>
                        <a class="btn btn-info btn-rounded" href="#!" role="button" data-mdb-ripple-init data-mdb-ripple-color="light">Read more</a>
                      </div>

                      <div class="col-md-6 mb-4">
                        <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init>
                          <img
                            data-mdb-lazy-load-init
                            data-mdb-lazy-src="https://mdbcdn.b-cdn.net/img/Photos/Others/images/27.webp"
                            data-mdb-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
                            class="w-100"
                          />
                          <a href="#!">
                            <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);"></div>
                          </a>
                        </div>
                        <h5>This is an title of the article</h5>
                        <p>
                          Lorem ipsum dolor sit amet consectetur adipisicing elit.
                          Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
                          illo. Quos architecto deserunt saepe.
                        </p>
                        <a class="btn btn-info btn-rounded" href="#!" role="button" data-mdb-ripple-init data-mdb-ripple-color="light">Read more</a>
                      </div>
                    </div>

                    <div class="row">
                      <div class="col-md-6 mb-4">
                        <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init>
                          <img
                            data-mdb-lazy-load-init
                            data-mdb-lazy-src="https://mdbcdn.b-cdn.net/img/Photos/Others/images/25.webp"
                            data-mdb-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
                            class="w-100"
                          />
                          <a href="#!">
                            <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);"></div>
                          </a>
                        </div>
                        <h5>This is an title of the article</h5>
                        <p>
                          Lorem ipsum dolor sit amet consectetur adipisicing elit.
                          Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
                          illo. Quos architecto deserunt saepe.
                        </p>
                        <a class="btn btn-info btn-rounded" href="#!" role="button" data-mdb-ripple-init data-mdb-ripple-color="light">Read more</a>
                      </div>

                      <div class="col-md-6 mb-4">
                        <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init>
                          <img
                            data-mdb-lazy-load-init
                            data-mdb-lazy-src="https://mdbcdn.b-cdn.net/img/Photos/Others/images/24.webp"
                            data-mdb-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
                            class="w-100"
                          />
                          <a href="#!">
                            <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);"></div>
                          </a>
                        </div>
                        <h5>This is an title of the article</h5>
                        <p>
                          Lorem ipsum dolor sit amet consectetur adipisicing elit.
                          Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
                          illo. Quos architecto deserunt saepe.
                        </p>
                        <a class="btn btn-info btn-rounded" href="#!" role="button" data-mdb-ripple-init data-mdb-ripple-color="light">Read more</a>
                      </div>
                    </div>

                    <div class="row">
                      <div class="col-md-6 mb-4">
                        <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init>
                          <img
                            data-mdb-lazy-load-init
                            data-mdb-lazy-src="https://mdbcdn.b-cdn.net/img/Photos/Others/images/31.webp"
                            data-mdb-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
                            class="w-100"
                          />
                          <a href="#!">
                            <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);"></div>
                          </a>
                        </div>
                        <h5>This is an title of the article</h5>
                        <p>
                          Lorem ipsum dolor sit amet consectetur adipisicing elit.
                          Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
                          illo. Quos architecto deserunt saepe.
                        </p>
                        <a class="btn btn-info btn-rounded" href="#!" role="button" data-mdb-ripple-init data-mdb-ripple-color="light">Read more</a>
                      </div>

                      <div class="col-md-6 mb-4">
                        <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init>
                          <img
                            data-mdb-lazy-load-init
                            data-mdb-lazy-src="https://mdbcdn.b-cdn.net/img/Photos/Others/images/23.webp"
                            data-mdb-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
                            class="w-100"
                          />
                          <a href="#!">
                            <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);"></div>
                          </a>
                        </div>
                        <h5>This is an title of the article</h5>
                        <p>
                          Lorem ipsum dolor sit amet consectetur adipisicing elit.
                          Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
                          illo. Quos architecto deserunt saepe.
                        </p>
                        <a class="btn btn-info btn-rounded" href="#!" role="button" data-mdb-ripple-init data-mdb-ripple-color="light">Read more</a>
                      </div>
                    </div>

                    <div class="row" id="spinner" style="display: none;">
                      <div class="col-md-12">
                        <div class="spinner-border mx-auto"></div>
                      </div>
                    </div>
                  </section>
                  <!--Section: Posts-->
                </div>
              </main>
              <!--Main layout-->
            
        
    
        
            
              import { InfiniteScroll, Ripple, LazyLoad, initMDB } from "mdb-ui-kit";

              initMDB({ InfiniteScroll, Ripple, LazyLoad });

              const postsContainer = document.getElementById('posts');
              const spinner = document.getElementById('spinner');

              const items = [
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/31.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/23.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/29.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/27.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/25.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/24.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/31.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/32.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
              ];

              const getPostTemplate = (post) => {
                // returns the HTML template with post's title, image & text
                return `
                  <div class="col-md-6 mb-4">
                    <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init data-mdb-ripple-color="light">
                      <img src="${post.img}" class="w-100 lazy"/>
                      <a href="#!">
                        <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);">
                        </div>
                      </a>
                    </div>
                    <h5>${post.title}</h5>
                    <p>${post.text}</p>
                    <a class="btn btn-info btn-rounded" href="#!" role="button">Read more</a>
                  </div>
                `;
              };

              // posts - array of templates
              const posts = items.map((item) => getPostTemplate(item));

              const generateRow = (firstPost, secondPost) => {
                // Returns a div.row element with two columns generated based on arguments
                let el = document.createElement('div');
                el.classList.add('row');

                el.innerHTML = `
                  ${firstPost}
                  ${secondPost}
                `;
                return el;
              };

              // rows - array of rows with two posts each
              const rows = [];

              // iterates over posts and creates a row for every two of them
              for (let i = 0; i < posts.length - 1; i += 2) {
                rows.push(generateRow(posts[i], posts[i + 1]));
              }

              // renderedItems - number of items already rendered
              let renderedItems = 0;

              const renderItems = (index) => {
                // timeout simulates delay in loading items (f.e. API call)
                setTimeout(() => {
                  // hide spinner
                  spinner.style.display = 'none';

                  postsContainer.appendChild(rows[index]);
                }, 1500);
              };

              const loadItems = () => {
                if (renderedItems < rows.length) {
                  // show spinner
                  postsContainer.appendChild(spinner);
                  spinner.style.display = 'flex';

                  renderItems(renderedItems);

                  renderedItems++;

                  // Removes event listener after all items have been loaded
                  if (renderedItems === rows.length) {
                    window.removeEventListener('completed.mdb.infiniteScroll', loadItems);
                  }
                }
              };

              // load items when window is scrolled to the end
              window.addEventListener('completed.mdb.infiniteScroll', loadItems);

              // init infinite scroll
              new InfiniteScroll(window);
            
        
    
        
            
              const postsContainer = document.getElementById('posts');
              const spinner = document.getElementById('spinner');

              const items = [
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/31.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/23.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/29.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/27.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/25.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/24.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/31.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
                {
                  img: 'https://mdbcdn.b-cdn.net/img/Photos/Others/images/32.webp',
                  title: 'This is an title of the article',
                  text: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam cupiditate veniam voluptatibus laudantium cum dolorem illo. Quos architecto deserunt saepe.',
                },
              ];

              const getPostTemplate = (post) => {
                // returns the HTML template with post's title, image & text
                return `
                  <div class="col-md-6 mb-4">
                    <div class="bg-image hover-overlay ripple shadow-1-strong rounded mb-4" data-mdb-ripple-init data-mdb-ripple-color="light">
                      <img src="${post.img}" class="w-100 lazy"/>
                      <a href="#!">
                        <div class="mask" style="background-color: rgba(251, 251, 251, 0.2);">
                        </div>
                      </a>
                    </div>
                    <h5>${post.title}</h5>
                    <p>${post.text}</p>
                    <a class="btn btn-info btn-rounded" href="#!" role="button">Read more</a>
                  </div>
                `;
              };

              // posts - array of templates
              const posts = items.map((item) => getPostTemplate(item));

              const generateRow = (firstPost, secondPost) => {
                // Returns a div.row element with two columns generated based on arguments
                let el = document.createElement('div');
                el.classList.add('row');

                el.innerHTML = `
                  ${firstPost}
                  ${secondPost}
                `;
                return el;
              };

              // rows - array of rows with two posts each
              const rows = [];

              // iterates over posts and creates a row for every two of them
              for (let i = 0; i < posts.length - 1; i += 2) {
                rows.push(generateRow(posts[i], posts[i + 1]));
              }

              // renderedItems - number of items already rendered
              let renderedItems = 0;

              const renderItems = (index) => {
                // timeout simulates delay in loading items (f.e. API call)
                setTimeout(() => {
                  // hide spinner
                  spinner.style.display = 'none';

                  postsContainer.appendChild(rows[index]);
                }, 1500);
              };

              const loadItems = () => {
                if (renderedItems < rows.length) {
                  // show spinner
                  postsContainer.appendChild(spinner);
                  spinner.style.display = 'flex';

                  renderItems(renderedItems);

                  renderedItems++;

                  // Removes event listener after all items have been loaded
                  if (renderedItems === rows.length) {
                    window.removeEventListener('completed.mdb.infiniteScroll', loadItems);
                  }
                }
              };

              // load items when window is scrolled to the end
              window.addEventListener('completed.mdb.infiniteScroll', loadItems);

              // init infinite scroll
              new mdb.InfiniteScroll(window);
            
        
    

Infinite scroll - API


Import

Importing components depends on how your application works. If you intend to use the MDBootstrap ES format, you must first import the component and then initialize it with the initMDB method. If you are going to use the UMD format, just import the mdb-ui-kit package.

        
            
            import { InfiniteScroll, initMDB } from "mdb-ui-kit";
            initMDB({ InfiniteScroll });
          
        
    
        
            
            import 'mdb-ui-kit';
          
        
    

Usage

Via data attributes

Using the Infinite scroll method doesn't require any additional JavaScript code - simply add data-mdb-infinite-scroll-init attribute to container element and use other data attributes to set all options. For ES format, you must first import and call the initMDB method.

        
            
            <div data-mdb-infinite-scroll-init>
              Sample content
            </div>
          
        
    

Via JavaScript

        
            
            const infiniteScrollInstance = new InfiniteScroll(document.getElementById('element'), {
              infinite-direction: '...',
            });
          
        
    
        
            
            const infiniteScrollInstance = new mdb.InfiniteScroll(document.getElementById('element'), {
              infinite-direction: '...',
            });
          
        
    

Via jQuery

Note: By default, MDB does not include jQuery and you have to add it to the project on your own.

        
            
            $(document).ready(() => {
              $('.example-class').infiniteScroll(options);
            });
          
        
    

Options

Options can be passed via data attributes or JavaScript. For data attributes, append the option name to data-mdb-, as in data-mdb-infinite-direction="y".

Name Type Default Description
infiniteDirection String 'y' Defines an example scroll direction.

Methods

Name Description Example
dispose Removes an instance of the lazy element infiniteScrollInstance.toggle()
getInstance Static method which allows you to get the infinite scroll instance associated to a DOM element. InfiniteScroll.getInstance(infiniteScrollElement)
getOrCreateInstance Static method which returns the infinite scroll instance associated to a DOM element or create a new one in case it wasn't initialized. InfiniteScroll.getOrCreateInstance(infiniteScrollElement)
        
            
            const infiniteScrollElement = document.getElementById('element');
            const infiniteScrollInstance = new InfiniteScroll(infiniteScrollElement);
            infiniteScrollInstance.dispose();
          
        
    
        
            
            const infiniteScrollElement = document.getElementById('element');
            const infiniteScrollInstance = new mdb.InfiniteScroll(infiniteScrollElement);
            infiniteScrollInstance.dispose();
          
        
    

Events

Name Description
completed.mdb.infiniteScroll This event fires immediately after scrolling to the end of the container.
        
            
      const infiniteScrollElement = document.getElementById('element');
      infiniteScrollElement.addEventListener('completed.mdb.infiniteScroll', (e) => {
        // do something...
      });