Pagination divides content into separate pages to prevent your pages from becoming too long and overwhelming. It also helps to improve the user experience by showing the smaller chunk of information so that the users can focus on important parts of the page with reduced scrolling.
Magento 2, by default, provides the pagination facility for the product pages, category pages, etc. It helps in easy navigation. Moreover, without pagination, the page load time would increase due to a large amount of content, links, etc. on a single page. It affects the user experience of the page and hence degrade the SEO!
The default Magento 2 does not provide pagination for a custom collection. To add pagination in Magento 2 custom collection, follow below steps and you’ll get the desired output.
Method to Add Pagination in Magento 2 Custom Collection
1. Create Controller File at Vendor\Extension\Controller\Index\Index.php
<?php namespace Vendor\Extension\Controller\Index; use Magento\Framework\App\Action\Context; use Magento\Framework\View\Result\PageFactory; use Magento\Framework\App\Action\Action; class Index extends Action { protected $resultPageFactory; public function __construct( Context $context, PageFactory $resultPageFactory ) { parent::__construct($context); $this->resultPageFactory = $resultPageFactory; } public function execute() { $resultPage = $this->resultPageFactory->create(); $resultPage->getConfig()->getTitle()->set(__('Custom Pagination')); return $resultPage; } }
2. Create block file at Vendor\Extension\Block\Index.php
<?php namespace Vendor\Extension\Block; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context; use Vendor\Extension\Model\Extension; use Magento\Framework\Pricing\Helper\Data as priceHelper; class Index extends Template { protected $customCollection; protected $priceHepler; public function __construct(Context $context, Extension $customCollection,priceHelper $priceHepler) { $this->customCollection = $customCollection; $this->priceHepler = $priceHepler; parent::__construct($context); } protected function _prepareLayout() { parent::_prepareLayout(); $this->pageConfig->getTitle()->set(__('Custom Pagination')); if ($this->getCustomCollection()) { $pager = $this->getLayout()->createBlock( 'Magento\Theme\Block\Html\Pager', 'custom.history.pager' )->setAvailableLimit([5 => 5, 10 => 10, 15 => 15, 20 => 20]) ->setShowPerPage(true)->setCollection( $this->getCustomCollection() ); $this->setChild('pager', $pager); $this->getCustomCollection()->load(); } return $this; } public function getPagerHtml() { return $this->getChildHtml('pager'); } public function getCustomCollection() { $page = ($this->getRequest()->getParam('p')) ? $this->getRequest()->getParam('p') : 1; $pageSize = ($this->getRequest()->getParam('limit')) ? $this->getRequest( )->getParam('limit') : 5; $collection = $this->customCollection->getCollection(); $collection->setPageSize($pageSize); $collection->setCurPage($page); return $collection; } public function getFormattedPrice($price) { return $this->priceHepler->currency(number_format($price, 2), true, false); } }
3.Create layout file at Vendor\Extension\view\frontend\layout\extension_index_index.xml
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="columns.top"> <block class="Magento\Theme\Block\Html\Title" name="page.main.title" template="html/title.phtml"/> <container name="page.messages" htmlTag="div" htmlClass="page messages"> <block class="Magento\Framework\View\Element\Template" name="ajax.message.placeholder" template="Magento_Theme::html/messages.phtml"/> <block class="Magento\Framework\View\Element\Messages" name="messages" as="messages" template="Magento_Theme::messages.phtml"/> </container> </referenceContainer> <referenceBlock name="page.main.title"> <action method="setPageTitle"> <argument translate="true" name="title" xsi:type="string">Custom Pagination</argument> </action> </referenceBlock> <referenceContainer name="content"> <block class="Vendor\Extension\Block\Index" name="ecustom_pagination" template="Vendor_Extension::index.phtml" cacheable="false" > </block> </referenceContainer> </body> </page>
4. Create template file at Vendor\Extension\view\frontend\templates\index.phtml
<?php if ($block->getPagerHtml()): ?> <div class="order-products-toolbar toolbar bottom"><?php echo $block->getPagerHtml(); ?></div> <?php endif ?> <?php $gridrecords = $block->getCustomCollection(); ?> <?php if ($gridrecords && sizeof($gridrecords)): ?> <div class="table-wrapper orders-history"> <table class="data table table-order-items history" id="my-orders-table"> <caption class="table-caption"><?php echo __('Grid Record') ?></caption> <thead> <tr> <th scope="col" class="col id"><?php echo __('ID') ?></th> <th scope="col" class="col title"><?php echo __('Created At') ?></th> <th scope="col" class="col product"><?php echo __('Product Name') ?></th> <th scope="col" class="col amount"><?php echo __('Price') ?></th> </tr> </thead> <tbody> <?php foreach ($gridrecords as $gridrecord): ?> <tr> <td data-th="<?= $block->escapeHtml(__('ID')) ?>" class="col id"> <?php echo $gridrecord->getId() ?> </td> <td data-th="<?= $block->escapeHtml(__('Created At')) ?>" class="col title"><?php echo date('Y-m-d', strtotime($gridrecord->getCreatedDate())); ?></td> <td data-th="<?= $block->escapeHtml(__('Product Name')) ?>" class="col product"> <?php echo $gridrecord->getProductName() ?> </td> <td data-th="<?= $block->escapeHtml(__('Price')) ?>" class="col amount"><?php echo $block->getFormattedPrice($gridrecord->getPrice()) ?></td> </tr> <?php endforeach; ?> </tbody> </table> </div> <?php if ($block->getPagerHtml()): ?> <div class="order-products-toolbar toolbar bottom"><?php echo $block->getPagerHtml(); ?></div> <?php endif ?> <?php else: ?> <div class="message info empty"><span><?php echo __('No any record.'); ?></span></div> <?php endif ?>

The grid created by the above implementation will be responsive! Hope this blog has served your purpose to implement pagination.
When adding pagination to a custom collection in Magento 2, it’s essential to control the number of items displayed per page. One effective way to achieve this is by using the setPageSize
method.
Thank You!