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
class like in the example below.
- User
- User circle
- User group
- User minus
- User plus
- Users
<ul
id="basic-example"
data-twe-infinite-scroll-init
class="h-[261px] w-80 overflow-y-scroll">
<li class="me-2 flex items-center border dark:border-neutral-600 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
</svg>
</span>
User
</li>
<li
class="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</span>
User circle
</li>
<li
class="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z" />
</svg>
</span>
User group
</li>
<li
class="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M22 10.5h-6m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM4 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 0110.374 21c-2.331 0-4.512-.645-6.374-1.766z" />
</svg>
</span>
User minus
</li>
<li
class="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM4 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 0110.374 21c-2.331 0-4.512-.645-6.374-1.766z" />
</svg>
</span>
User plus
</li>
<li
class="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
</svg>
</span>
Users
</li>
</ul>
// Initialization for ES Users
import {
InfiniteScroll,
initTWE,
} from "tw-elements";
initTWE({ InfiniteScroll });
// An array of icon names
const icons = [
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z"
clip-rule="evenodd" />
</svg>
</span>
User`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"
clip-rule="evenodd" />
</svg>
</span>
User circle`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M8.25 6.75a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0zM15.75 9.75a3 3 0 116 0 3 3 0 01-6 0zM2.25 9.75a3 3 0 116 0 3 3 0 01-6 0zM6.31 15.117A6.745 6.745 0 0112 12a6.745 6.745 0 016.709 7.498.75.75 0 01-.372.568A12.696 12.696 0 0112 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 01-.372-.568 6.787 6.787 0 011.019-4.38z"
clip-rule="evenodd" />
<path
d="M5.082 14.254a8.287 8.287 0 00-1.308 5.135 9.687 9.687 0 01-1.764-.44l-.115-.04a.563.563 0 01-.373-.487l-.01-.121a3.75 3.75 0 013.57-4.047zM20.226 19.389a8.287 8.287 0 00-1.308-5.135 3.75 3.75 0 013.57 4.047l-.01.121a.563.563 0 01-.373.486l-.115.04c-.567.2-1.156.349-1.764.441z" />
</svg>
</span>
User group`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M10.375 2.25a4.125 4.125 0 100 8.25 4.125 4.125 0 000-8.25zM10.375 12a7.125 7.125 0 00-7.124 7.247.75.75 0 00.363.63 13.067 13.067 0 006.761 1.873c2.472 0 4.786-.684 6.76-1.873a.75.75 0 00.364-.63l.001-.12v-.002A7.125 7.125 0 0010.375 12zM16 9.75a.75.75 0 000 1.5h6a.75.75 0 000-1.5h-6z" />
</svg>
</span>
User minus`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M6.25 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM3.25 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM19.75 7.5a.75.75 0 00-1.5 0v2.25H16a.75.75 0 000 1.5h2.25v2.25a.75.75 0 001.5 0v-2.25H22a.75.75 0 000-1.5h-2.25V7.5z" />
</svg>
</span>
User plus`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M4.5 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM14.25 8.625a3.375 3.375 0 116.75 0 3.375 3.375 0 01-6.75 0zM1.5 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM17.25 19.128l-.001.144a2.25 2.25 0 01-.233.96 10.088 10.088 0 005.06-1.01.75.75 0 00.42-.643 4.875 4.875 0 00-6.957-4.611 8.586 8.586 0 011.71 5.157v.003z" />
</svg>
</span>
Users`,
];
// 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="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
${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.twe.infiniteScroll", () => {
// Return nothing when user appended all of the generated items
if (itemIndex === icons.length - 1) return;
console.log("Appended new items");
// 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 = [
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z"
clip-rule="evenodd" />
</svg>
</span>
User`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"
clip-rule="evenodd" />
</svg>
</span>
User circle`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M8.25 6.75a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0zM15.75 9.75a3 3 0 116 0 3 3 0 01-6 0zM2.25 9.75a3 3 0 116 0 3 3 0 01-6 0zM6.31 15.117A6.745 6.745 0 0112 12a6.745 6.745 0 016.709 7.498.75.75 0 01-.372.568A12.696 12.696 0 0112 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 01-.372-.568 6.787 6.787 0 011.019-4.38z"
clip-rule="evenodd" />
<path
d="M5.082 14.254a8.287 8.287 0 00-1.308 5.135 9.687 9.687 0 01-1.764-.44l-.115-.04a.563.563 0 01-.373-.487l-.01-.121a3.75 3.75 0 013.57-4.047zM20.226 19.389a8.287 8.287 0 00-1.308-5.135 3.75 3.75 0 013.57 4.047l-.01.121a.563.563 0 01-.373.486l-.115.04c-.567.2-1.156.349-1.764.441z" />
</svg>
</span>
User group`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M10.375 2.25a4.125 4.125 0 100 8.25 4.125 4.125 0 000-8.25zM10.375 12a7.125 7.125 0 00-7.124 7.247.75.75 0 00.363.63 13.067 13.067 0 006.761 1.873c2.472 0 4.786-.684 6.76-1.873a.75.75 0 00.364-.63l.001-.12v-.002A7.125 7.125 0 0010.375 12zM16 9.75a.75.75 0 000 1.5h6a.75.75 0 000-1.5h-6z" />
</svg>
</span>
User minus`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M6.25 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM3.25 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM19.75 7.5a.75.75 0 00-1.5 0v2.25H16a.75.75 0 000 1.5h2.25v2.25a.75.75 0 001.5 0v-2.25H22a.75.75 0 000-1.5h-2.25V7.5z" />
</svg>
</span>
User plus`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M4.5 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM14.25 8.625a3.375 3.375 0 116.75 0 3.375 3.375 0 01-6.75 0zM1.5 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM17.25 19.128l-.001.144a2.25 2.25 0 01-.233.96 10.088 10.088 0 005.06-1.01.75.75 0 00.42-.643 4.875 4.875 0 00-6.957-4.611 8.586 8.586 0 011.71 5.157v.003z" />
</svg>
</span>
Users`,
];
// 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="me-2 flex items-center border-x border-b dark:border-neutral-600 dark:text-white">
${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.twe.infiniteScroll", () => {
// Return nothing when user appended all of the generated items
if (itemIndex === icons.length - 1) return;
console.log("Appended new items");
// Append next element to the scrollable container
basicElement.appendChild(items[itemIndex]);
// Increment amount of items that are appended
itemIndex++;
});
Direction
Use data-twe-infinite-direction
attribute to define the
scrolling direction.
User
User circle
User group
User minus
User plus
Users
<div
id="direction-example"
data-twe-infinite-scroll-init
data-twe-infinite-direction="x"
class="flex max-w-[1000px] overflow-x-scroll whitespace-nowrap text-center">
<span class="mx-5 flex py-4 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
</svg>
</span>
<span class="flex items-end">User</span>
</span>
<span class="mx-5 flex py-4 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</span>
<span class="flex items-end">User circle</span>
</span>
<span class="mx-5 flex py-4 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z" />
</svg>
</span>
<span class="flex items-end">User group</span>
</span>
<span class="mx-5 flex py-4 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M22 10.5h-6m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM4 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 0110.374 21c-2.331 0-4.512-.645-6.374-1.766z" />
</svg>
</span>
<span class="flex items-end">User minus</span>
</span>
<span class="mx-5 flex py-4 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM4 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 0110.374 21c-2.331 0-4.512-.645-6.374-1.766z" />
</svg>
</span>
<span class="flex items-end">User plus</span>
</span>
<span class="mx-5 flex py-4 dark:text-white">
<span class="mx-4 py-1 [&>svg]:w-14"
><svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
</svg>
</span>
<span class="flex items-end">Users</span>
</span>
</div>
// Initialization for ES Users
import {
InfiniteScroll,
initTWE,
} from "tw-elements";
initTWE({ 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 = [
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z"
clip-rule="evenodd" />
</svg>
</span>
<span class="flex items-end">User</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"
clip-rule="evenodd" />
</svg>
</span>
<span class="flex items-end">User circle</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M8.25 6.75a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0zM15.75 9.75a3 3 0 116 0 3 3 0 01-6 0zM2.25 9.75a3 3 0 116 0 3 3 0 01-6 0zM6.31 15.117A6.745 6.745 0 0112 12a6.745 6.745 0 016.709 7.498.75.75 0 01-.372.568A12.696 12.696 0 0112 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 01-.372-.568 6.787 6.787 0 011.019-4.38z"
clip-rule="evenodd" />
<path
d="M5.082 14.254a8.287 8.287 0 00-1.308 5.135 9.687 9.687 0 01-1.764-.44l-.115-.04a.563.563 0 01-.373-.487l-.01-.121a3.75 3.75 0 013.57-4.047zM20.226 19.389a8.287 8.287 0 00-1.308-5.135 3.75 3.75 0 013.57 4.047l-.01.121a.563.563 0 01-.373.486l-.115.04c-.567.2-1.156.349-1.764.441z" />
</svg>
</span>
<span class="flex items-end">User group</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M10.375 2.25a4.125 4.125 0 100 8.25 4.125 4.125 0 000-8.25zM10.375 12a7.125 7.125 0 00-7.124 7.247.75.75 0 00.363.63 13.067 13.067 0 006.761 1.873c2.472 0 4.786-.684 6.76-1.873a.75.75 0 00.364-.63l.001-.12v-.002A7.125 7.125 0 0010.375 12zM16 9.75a.75.75 0 000 1.5h6a.75.75 0 000-1.5h-6z" />
</svg>
</span>
<span class="flex items-end">User minus</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M6.25 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM3.25 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM19.75 7.5a.75.75 0 00-1.5 0v2.25H16a.75.75 0 000 1.5h2.25v2.25a.75.75 0 001.5 0v-2.25H22a.75.75 0 000-1.5h-2.25V7.5z" />
</svg>
</span>
<span class="flex items-end">User plus</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M4.5 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM14.25 8.625a3.375 3.375 0 116.75 0 3.375 3.375 0 01-6.75 0zM1.5 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM17.25 19.128l-.001.144a2.25 2.25 0 01-.233.96 10.088 10.088 0 005.06-1.01.75.75 0 00.42-.643 4.875 4.875 0 00-6.957-4.611 8.586 8.586 0 011.71 5.157v.003z" />
</svg>
</span>
<span class="flex items-end">Users</span>`,
];
// 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");
// Change HTML code inside created span element using icon we are currently working on
element.innerHTML = `
<span class="mx-5 flex py-4 dark:text-white">
${icon}
</span>
`;
// 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.twe.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 = [
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z"
clip-rule="evenodd" />
</svg>
</span>
<span class="flex items-end">User</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"
clip-rule="evenodd" />
</svg>
</span>
<span class="flex items-end">User circle</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
fill-rule="evenodd"
d="M8.25 6.75a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0zM15.75 9.75a3 3 0 116 0 3 3 0 01-6 0zM2.25 9.75a3 3 0 116 0 3 3 0 01-6 0zM6.31 15.117A6.745 6.745 0 0112 12a6.745 6.745 0 016.709 7.498.75.75 0 01-.372.568A12.696 12.696 0 0112 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 01-.372-.568 6.787 6.787 0 011.019-4.38z"
clip-rule="evenodd" />
<path
d="M5.082 14.254a8.287 8.287 0 00-1.308 5.135 9.687 9.687 0 01-1.764-.44l-.115-.04a.563.563 0 01-.373-.487l-.01-.121a3.75 3.75 0 013.57-4.047zM20.226 19.389a8.287 8.287 0 00-1.308-5.135 3.75 3.75 0 013.57 4.047l-.01.121a.563.563 0 01-.373.486l-.115.04c-.567.2-1.156.349-1.764.441z" />
</svg>
</span>
<span class="flex items-end">User group</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M10.375 2.25a4.125 4.125 0 100 8.25 4.125 4.125 0 000-8.25zM10.375 12a7.125 7.125 0 00-7.124 7.247.75.75 0 00.363.63 13.067 13.067 0 006.761 1.873c2.472 0 4.786-.684 6.76-1.873a.75.75 0 00.364-.63l.001-.12v-.002A7.125 7.125 0 0010.375 12zM16 9.75a.75.75 0 000 1.5h6a.75.75 0 000-1.5h-6z" />
</svg>
</span>
<span class="flex items-end">User minus</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M6.25 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM3.25 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM19.75 7.5a.75.75 0 00-1.5 0v2.25H16a.75.75 0 000 1.5h2.25v2.25a.75.75 0 001.5 0v-2.25H22a.75.75 0 000-1.5h-2.25V7.5z" />
</svg>
</span>
<span class="flex items-end">User plus</span>`,
`<span class="mx-4 py-1 [&>svg]:w-14">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor">
<path
d="M4.5 6.375a4.125 4.125 0 118.25 0 4.125 4.125 0 01-8.25 0zM14.25 8.625a3.375 3.375 0 116.75 0 3.375 3.375 0 01-6.75 0zM1.5 19.125a7.125 7.125 0 0114.25 0v.003l-.001.119a.75.75 0 01-.363.63 13.067 13.067 0 01-6.761 1.873c-2.472 0-4.786-.684-6.76-1.873a.75.75 0 01-.364-.63l-.001-.122zM17.25 19.128l-.001.144a2.25 2.25 0 01-.233.96 10.088 10.088 0 005.06-1.01.75.75 0 00.42-.643 4.875 4.875 0 00-6.957-4.611 8.586 8.586 0 011.71 5.157v.003z" />
</svg>
</span>
<span class="flex items-end">Users</span>`,
];
// 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");
// Change HTML code inside created span element using icon we are currently working on
element.innerHTML = `
<span class="mx-5 flex py-4 dark:text-white">
${icon}
</span>
`;
// 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.twe.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
Loading...
<div
data-twe-infinite-scroll-init
class="max-h-[500px] overflow-y-scroll py-3 text-center"
id="spinners-and-async-example">
<div id="images">
<img
src="https://tecdn.b-cdn.net/img/Photos/Slides/img%20(100).webp"
class="mb-3 h-auto w-full" />
<img
src="https://tecdn.b-cdn.net/img/Photos/Slides/img%20(105).webp"
class="mb-3 h-auto w-full" />
<img
src="https://tecdn.b-cdn.net/img/Photos/Slides/img%20(106).webp"
class="mb-3 h-auto w-full" />
</div>
<div
id="spinner"
class="hidden h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-e-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] text-surface dark:text-white"
role="status">
<span
class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]"
>Loading...</span
>
</div>
</div>
// Initialization for ES Users
import {
InfiniteScroll,
initTWE,
} from "tw-elements";
initTWE({ 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 classes to imgages
let classes = ["mb-3", "h-auto", "w-full"];
classes.forEach((className) => imgElement.classList.add(className));
// 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.classList.replace("hidden", "inline-block");
// Fetch your API
fetch('YOUR_API/getNextItem')
.then(response => response.json)
.then(imgUrl => {
// Hide spinner after data loads
spinner.classList.replace("inline-block", "hidden");
// 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.twe.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 classes to imgages
let classes = ["mb-3", "h-auto", "w-full"];
classes.forEach((className) => imgElement.classList.add(className));
// 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.classList.replace("hidden", "inline-block");
// Fetch your API
fetch('YOUR_API/getNextItem')
.then(response => response.json)
.then(imgUrl => {
// Hide spinner after data loads
spinner.classList.replace("inline-block", "hidden");
// 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.twe.infiniteScroll', loadImages);
Window
You can apply the InfiniteScroll
instance to a window.
<!--Main layout-->
<main class="my-5">
<!--Section: Posts-->
<section
class="container mx-auto mb-4 text-center xl:w-[60%]"
id="posts">
<div class="grid grid-cols-1 place-items-center gap-4 md:grid-cols-2">
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-1-strong dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light">
<img
class="rounded-lg"
data-twe-lazy-load-init
data-twe-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/29.jpg"
data-twe-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
alt="" />
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
</div>
<h5 class="mb-3 mt-5 text-xl text-surface dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-surface dark:text-neutral-200">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
illo. Quos architecto deserunt saepe.
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-1-strong dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light">
<img
class="rounded-lg"
data-twe-lazy-load-init
data-twe-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/27.jpg"
data-twe-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
alt="" />
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
</div>
<h5
class="mb-3 mt-5 text-xl font-normal text-surface dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-surface dark:text-neutral-200">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
illo. Quos architecto deserunt saepe.
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-1-strong dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light">
<img
class="rounded-lg"
data-twe-lazy-load-init
data-twe-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/25.jpg"
data-twe-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
alt="" />
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
</div>
<h5
class="mb-3 mt-5 text-xl font-normal text-surface dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-surface dark:text-neutral-200">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
illo. Quos architecto deserunt saepe.
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-1-strong dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light">
<img
class="rounded-lg"
data-twe-lazy-load-init
data-twe-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/24.jpg"
data-twe-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
alt="" />
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
</div>
<h5
class="mb-3 mt-5 text-xl font-normal text-surface dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-surface dark:text-neutral-200">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
illo. Quos architecto deserunt saepe.
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-1-strong dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light">
<img
class="rounded-lg"
data-twe-lazy-load-init
data-twe-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/31.jpg"
data-twe-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
alt="" />
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
</div>
<h5
class="mb-3 mt-5 text-xl font-normal text-surface dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-surface dark:text-neutral-200">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
illo. Quos architecto deserunt saepe.
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-1-strong dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light">
<img
class="rounded-lg"
data-twe-lazy-load-init
data-twe-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/23.jpg"
data-twe-lazy-placeholder="https://placehold.it/1321x583?text=Loading"
alt="" />
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
</div>
<h5
class="mb-3 mt-5 text-xl font-normal text-surface dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-surface dark:text-neutral-200">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam cupiditate veniam voluptatibus laudantium cum dolorem
illo. Quos architecto deserunt saepe.
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
Read more
</button>
</div>
</div>
<div
id="spinner"
class="hidden h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-e-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] text-surface dark:text-white"
role="status">
<span
class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]"
>Loading...</span
>
</div>
</section>
<!--Section: Posts-->
</main>
<!--Main layout-->
// Initialization for ES Users
import {
InfiniteScroll,
Ripple,
LazyLoad,
initTWE,
} from "tw-elements";
initTWE({ Ripple, LazyLoad });
const postsContainer = document.getElementById("posts");
const spinner = document.getElementById("spinner");
const itemsImg = [
{
img: "https://tecdn.b-cdn.net/img/Photos/Others/images/31.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/23.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/29.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/27.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/25.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/24.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/31.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/32.jpg",
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="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-shadow-1-strong dark:bg-neutral-700"
>
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light"
>
<img
class="rounded-lg"
src="${post.img}"
alt=""
/>
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"
></div>
</a>
</div>
</div>
<h5 class="mt-5 mb-3 text-xl font-normal text-surface dark:text-white">
${post.title}
</h5>
<p class="text-center mb-3 text-surface dark:text-neutral-200">
${post.text}
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
>
Read more
</button>
</div>
`;
};
// posts - array of templates
const posts = itemsImg.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");
let classes = ["grid", "grid-cols-1", "md:grid-cols-2", "gap-4"];
classes.forEach((className) => el.classList.add(className));
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.classList.replace("inline-block", "hidden");
postsContainer.appendChild(rows[index]);
}, 1500);
};
const loadItems = () => {
if (renderedItems < rows.length) {
// show spinner
postsContainer.appendChild(spinner);
spinner.classList.replace("hidden", "inline-block");
renderItems(renderedItems);
renderedItems++;
// Removes event listener after all items have been loaded
if (renderedItems === rows.length) {
window.removeEventListener("completed.twe.infiniteScroll", loadItems);
}
}
};
// load items when window is scrolled to the end
window.addEventListener("completed.twe.infiniteScroll", loadItems);
// init infinite scroll
new InfiniteScroll(window);
const postsContainer = document.getElementById("posts");
const spinner = document.getElementById("spinner");
const itemsImg = [
{
img: "https://tecdn.b-cdn.net/img/Photos/Others/images/31.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/23.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/29.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/27.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/25.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/24.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/31.jpg",
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://tecdn.b-cdn.net/img/Photos/Others/images/32.jpg",
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="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-shadow-1-strong dark:bg-neutral-700"
>
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-twe-ripple-init
data-twe-ripple-color="light"
>
<img
class="rounded-lg"
src="${post.img}"
alt=""
/>
<a href="#!">
<div
class="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"
></div>
</a>
</div>
</div>
<h5 class="mt-5 mb-3 text-xl font-normal text-surface dark:text-white">
${post.title}
</h5>
<p class="text-center mb-3 text-surface dark:text-neutral-200">
${post.text}
</p>
<button
type="button"
data-twe-ripple-init
data-twe-ripple-color="light"
class="mb-3 inline-block rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-info-3 transition duration-150 ease-in-out hover:bg-info-accent-300 hover:shadow-info-2 focus:bg-info-accent-300 focus:shadow-info-2 focus:outline-none focus:ring-0 active:bg-info-600 active:shadow-info-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
>
Read more
</button>
</div>
`;
};
// posts - array of templates
const posts = itemsImg.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");
let classes = ["grid", "grid-cols-1", "md:grid-cols-2", "gap-4"];
classes.forEach((className) => el.classList.add(className));
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.classList.replace("inline-block", "hidden");
postsContainer.appendChild(rows[index]);
}, 1500);
};
const loadItems = () => {
if (renderedItems < rows.length) {
// show spinner
postsContainer.appendChild(spinner);
spinner.classList.replace("hidden", "inline-block");
renderItems(renderedItems);
renderedItems++;
// Removes event listener after all items have been loaded
if (renderedItems === rows.length) {
window.removeEventListener("completed.twe.infiniteScroll", loadItems);
}
}
};
// load items when window is scrolled to the end
window.addEventListener("completed.twe.infiniteScroll", loadItems);
// init infinite scroll
new twe.InfiniteScroll(window);