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-te-infinite-scroll-init
class="h-[261px] w-80 overflow-y-scroll">
<li class="mr-2 flex items-center border dark:border-neutral-600">
<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="mr-2 flex items-center border-x border-b dark:border-neutral-600">
<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="mr-2 flex items-center border-x border-b dark:border-neutral-600">
<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="mr-2 flex items-center border-x border-b dark:border-neutral-600">
<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="mr-2 flex items-center border-x border-b dark:border-neutral-600">
<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="mr-2 flex items-center border-x border-b dark:border-neutral-600">
<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,
initTE,
} from "tw-elements";
initTE({ 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="mr-2 flex items-center border-x border-b">
${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("complete.te.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="mr-2 flex items-center border-x border-b">
${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("complete.te.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++;
});
Hey there 👋 we want to make TW elements a community-driven project. It's open source and free, and we would like it to stay that way. If you enjoy it, help the project grow by sharing it with your peers. Every share counts, thank you!
Direction
Use data-te-infinite-direction
attribute to define the
scrolling direction.
User
User circle
User group
User minus
User plus
Users
<div
id="direction-example"
data-te-infinite-scroll-init
data-te-infinite-direction="x"
class="flex max-w-[1000px] overflow-x-scroll whitespace-nowrap text-center">
<span class="mx-5 flex py-4">
<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">
<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">
<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">
<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">
<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">
<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,
initTE,
} from "tw-elements";
initTE({ 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">
${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("complete.te.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">
${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("complete.te.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
.webp)
.webp)
.webp)
Loading...
<div
data-te-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-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"
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,
initTE,
} from "tw-elements";
initTE({ 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('complete.te.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('complete.te.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-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light">
<img
class="rounded-lg"
data-te-lazy-load-init
data-te-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/29.jpg"
data-te-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-[#4f4f4f] dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-[#4f4f4f] 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-te-ripple-init
data-te-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-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-info-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light">
<img
class="rounded-lg"
data-te-lazy-load-init
data-te-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/27.jpg"
data-te-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-[#4f4f4f] dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-[#4f4f4f] 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-te-ripple-init
data-te-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-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light">
<img
class="rounded-lg"
data-te-lazy-load-init
data-te-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/25.jpg"
data-te-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-[#4f4f4f] dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-[#4f4f4f] 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-te-ripple-init
data-te-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-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light">
<img
class="rounded-lg"
data-te-lazy-load-init
data-te-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/24.jpg"
data-te-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-[#4f4f4f] dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-[#4f4f4f] 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-te-ripple-init
data-te-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-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light">
<img
class="rounded-lg"
data-te-lazy-load-init
data-te-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/31.jpg"
data-te-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-[#4f4f4f] dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-[#4f4f4f] 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-te-ripple-init
data-te-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-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
Read more
</button>
</div>
<div class="flex flex-col items-center">
<div
class="block rounded-lg bg-white shadow-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700">
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light">
<img
class="rounded-lg"
data-te-lazy-load-init
data-te-lazy-src="https://tecdn.b-cdn.net/img/Photos/Others/images/23.jpg"
data-te-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-[#4f4f4f] dark:text-white">
This is the title of an article
</h5>
<p class="mb-3 text-center text-[#4f4f4f] 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-te-ripple-init
data-te-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-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
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-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"
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,
initTE,
} from "tw-elements";
initTE({ 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 arzticle",
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-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700"
>
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-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-[#4f4f4f] dark:text-white">
${post.title}
</h5>
<p class="text-center mb-3 text-[#4f4f4f] dark:text-neutral-200">
${post.text}
</p>
<button
type="button"
data-te-ripple-init
data-te-ripple-color="light"
class="inline-block mb-3 rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-info-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
>
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("complete.te.infiniteScroll", loadItems);
}
}
};
// load items when window is scrolled to the end
window.addEventListener("complete.te.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 arzticle",
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-[0_2px_5px_0_rgba(0,0,0,0.25),0_3px_10px_0px_rgba(0,0,0,0.2)] dark:bg-neutral-700"
>
<div
class="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-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-[#4f4f4f] dark:text-white">
${post.title}
</h5>
<p class="text-center mb-3 text-[#4f4f4f] dark:text-neutral-200">
${post.text}
</p>
<button
type="button"
data-te-ripple-init
data-te-ripple-color="light"
class="inline-block mb-3 rounded-full bg-info px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-info-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
>
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("complete.te.infiniteScroll", loadItems);
}
}
};
// load items when window is scrolled to the end
window.addEventListener("complete.te.infiniteScroll", loadItems);
// init infinite scroll
new te.InfiniteScroll(window);