LazyLoad
Puts its content on the page only once it is scrolled near, holding its height until then.
Demo
Paragraph 1. Keep scrolling: the pictures below are not on the page yet.
Paragraph 2. Keep scrolling: the pictures below are not on the page yet.
Paragraph 3. Keep scrolling: the pictures below are not on the page yet.
Paragraph 4. Keep scrolling: the pictures below are not on the page yet.
Paragraph 5. Keep scrolling: the pictures below are not on the page yet.
Paragraph 6. Keep scrolling: the pictures below are not on the page yet.
Paragraph 7. Keep scrolling: the pictures below are not on the page yet.
Paragraph 8. Keep scrolling: the pictures below are not on the page yet.
The end.
Not loaded yet: scroll the box.
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/lazy_load.qweimport ui/theme.qwe use theme_cssuse ui/lazy_load.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
component LazyLoadDemoLive() { state shown = 0 <div.demo-stack> <div id="lazy-load-demo-box" tabindex="0" aria-label="A long page" style="height: 240px; overflow: auto; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); padding: 0 16px"> {for i in range(1, 9) => <p key={i}>Paragraph {i}. Keep scrolling: the pictures below are not on the page yet.</p>} <LazyLoad scroller="lazy-load-demo-box" margin="40px" height="120px" on_show={() => { shown += 1 }}> <div id="lazy-load-demo-content" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px"> {for i in range(3) => <div key={i} style="height: 120px; border-radius: var(--ui-radius); background: var(--ui-accent-soft); display: grid; place-items: center">Picture {i + 1}</div>} </div> </LazyLoad> <p>The end.</p> </div> <p.demo-note>{shown == 0 ? "Not loaded yet: scroll the box." : "Loaded once it came near."}</p> </div>}view LazyLoadDemo() = <div.demo-stack> <LazyLoadDemoLive/> <LazyLoad height="100px" placeholder="Loading…"> <div style="padding: 14px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius)">This block, placed in the page, was made when the gallery scrolled near it.</div> </LazyLoad> </div>Source
// LazyLoad: puts its content on the page only once it is scrolled near, for a// heavy part low on a page: a map, a chart, an embedded video, a grid of// pictures. Until then it is a placeholder of the height you give, so the page// does not jump. The content comes from the server as data and is made in the// browser when its time comes; what it holds (images, iframes) loads then.//// <LazyLoad height="320px"><iframe src="https://www.youtube.com/embed/..." ...></iframe></LazyLoad>// <LazyLoad height="200px" margin="0px" placeholder="Loading the picture…"><img src="/big.jpg" alt="..."/></LazyLoad>//// children: the content. height: the placeholder's height, a CSS length// ("200px"). margin: how far ahead it loads, a CSS length ("300px"); "0px" is// only when in view. placeholder: text shown in the grey box until then// (inside one of your components, markup too: a Skeleton). scroller: the id of the scrolling box it is in, when not the// window. label: what the placeholder is called for screen readers// ("Content loading"). on_show(): inside one of your components, called with// nothing when the content is put on the page.import ui/theme.qwe use ui_clslet lazy_load_css = css`.ui-lazy { display: block; min-width: 0; }.ui-lazy-wait { display: grid; place-items: center; min-height: var(--h, 200px); border-radius: var(--ui-radius); background: var(--ui-subtle); color: var(--ui-muted); font: 13px/1.4 var(--ui-font); }.ui-lazy-shown { animation: ui-lazy-in .25s ease-out; }@keyframes ui-lazy-in { from { opacity: 0; } }@media (prefers-reduced-motion: reduce) { .ui-lazy-shown { animation: none; } }`component LazyLoad(height: str = "200px", margin: str = "300px", placeholder = null, scroller: str? = null, label: str = "Content loading", on_show = null, class: str? = null, children) { style global lazy_load_css state seen = false <div class={ui_cls(["ui-lazy", seen && "ui-lazy-shown", class])} @mount={(el) => { let root = scroller != null ? js("document.getElementById", scroller) : null let w = js_new("IntersectionObserver", (entries, obs) => { if !seen && any(entries, (en) => en.isIntersecting) { seen = true obs.disconnect() on_show && on_show() } }, { root, rootMargin: margin }) w.observe(el) () => w.disconnect() }}> {seen ? children : <div.ui-lazy-wait style={`--h: ${height}`} role="status" aria-label={label}>{placeholder}</div>} </div>}Related
Thread 0 posts
On LazyLoad: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.