Lazy Loading Images in Svelte
One of the website speed optimization tips: Download images only when needed (i.e. when the image enters the viewport), which is "lazy loading". This technology has been around for a while and there are many excellent tutorials on how to implement it.
However, even with sufficient resources, lazy loading implementations will vary by project or framework. This article will use the Intersection Observer API and onLoad events to achieve lazy image loading using the Svelte JavaScript framework.
If you are not familiar with the Svelte framework, you can refer to Tristram Tokyo’s introduction to Svelte.
Practical examples
I integrated this approach when testing the speed of Shop Ireland (an application based on Svelte and Sapper). Our goal is to make it as fast as possible. The performance of the homepage was affected because the browser downloaded many images that weren't displayed on the screen at all, so we naturally turned to lazy loading.
Svelte itself is already very fast, because all the code is precompiled. However, once we added lazy loading to the image, the speed was significantly improved.
We will complete the process together. You can get the final code for this demo from GitHub and read the description of how it works.
The final effect is as follows:
Quickly start Svelte
You may already have a Svelte application, but if not, let's create a new Svelte project and run it locally. Enter:
npx degit sveltejs/template my-svelte-project cd my-svelte-project npm install npm run dev
Now you should be able to run a starter application on http://localhost:5000.
Add components folder
The initial Svelte demo only has one App.svelte file and has no components yet. Let's set up the components needed for this demo. Since there is no components folder, create one in the src folder. In this folder, create an Image folder - it will save the components of our presentation.
We will let our components do two things. First, they will check when the image enters the viewport. Then, when the image enters, the component will wait for the image file to be loaded before displaying the image.
The first component will be a<intersectionobserver></intersectionobserver>
, it revolves around the second component<imageloader></imageloader>
Package. The reason I like this setup is that it allows each component to focus on doing one action rather than trying to pack a bunch of actions in one component.
Let's go from<intersectionobserver></intersectionobserver>
The component starts.
Observe the intersection
Our first component will be a working implementation of the Intersection Observer API. Intersection Observer is a pretty complex thing, but the point is that it monitors child elements and notifies us when they enter the bounding box of its parent element. Therefore, the image can be used as a child of some parent elements, and we can get prompts in advance when they scroll into the view.
While it's a good idea to dig deep into the ins and outs of the Intersection Observer API - Travis Almand has a good description of this - we'll use the handy Svelte component written by Rich Harris for svelte.dev.
Before we dig into its specific features, let's set it up first. Create a new IntersectionObserver.svelte file and put it into the src/components/Image folder. We will define the component here using the following code:
import { onMount } from 'svelte'; export let once = false; export let top = 0; export let bottom = 0; export let left = 0; export let right = 0; let intersecting = false; let container; onMount(() => { if (typeof IntersectionObserver !== 'undefined') { const rootMargin = `${bottom}px ${left}px ${top}px ${right}px`; const observer = new IntersectionObserver(entries => { intersecting = entries[0].isIntersecting; if (intersecting && once) { observer.unobserve(container); } }, { rootMargin }); observer.observe(container); return () => observer.unobserve(container); } // Old browser fallback function handler() { const bcr = container.getBoundingClientRect(); intersecting = ( (bcr.bottom bottom) > 0 && (bcr.right right) > 0 && (bcr.top - top) window.removeEventListener('scroll', handler); }); div { width: 100%; height: 100%; } <div bind:this="{container}"> <slot></slot> </div>
We can use this component as a wrapper for other components, which will determine for us whether the wrapped component intersects the viewport.
If you are familiar with the structure of the Svelte component, you will see that it follows a pattern that starts with the script, goes into the style, and ends with a marker. It sets some options we can pass, including the once property, as well as the values of the top, right, bottom and left distances of the edge of the screen, which define where the intersection starts.
We will ignore the distance and use the once property instead. This will ensure that the images are loaded only once, as they enter the viewport.
The main logic of the component is located in the onMount section. This will set our observer to check our element to determine if it "intersects" with the visible area of the screen.
For older browsers, it also attaches a scroll event to check if the element is visible when we scroll, and then if we determine that it is available and once is true, it will remove this listener.
Loading the image
Let's use<intersectionobserver></intersectionobserver>
The components are packaged in<imageloader></imageloader>
The image is loaded conditionally around the component. Again, this is from<intersectionoberserver></intersectionoberserver>
The component that receives notifications, so it knows it's time to load the image.
This means we need to create a new component file in components/Image. Let's name it ImageLoader.svelte. Here is the code we want to use inside it:
export let src export let alt import IntersectionObserver from './IntersectionObserver.svelte' import Image from './Image.svelte' <intersectionobserver let:intersecting="{intersecting}" once="{true}"> {#if intersecting} <image src="%7Bsrc%7D" alt="{alt}"></image> {/if} </intersectionobserver>
This component takes some image-related properties—src and alt—we will use them to create the actual markup of the image. Note that we imported two components in the script section, including the one we just created<intersectionobserver></intersectionobserver>
And another named<image></image>
The component we haven't created yet, but will be covered later.
<intersectionobserver></intersectionobserver>
By acting as the<image></image>
Component wrappers to work. Check its properties. We set once to true so the image only loads when we see it the first time.
Then we use Svelte's slot property. What are they? Let's introduce it next.
Passing values using slot attribute
Like ours<intersectionobserver></intersectionobserver>
Such a wrapper component is very convenient for passing properties to the subcomponents it contains. Svelte provides us with something called slot property to achieve this.
In our<intersectionobserver></intersectionobserver>
In the component, you may have noticed this line:
<slot></slot>
This passes the intersecting property to any component we give it. In this case, our<imageloader></imageloader>
The component receives this property when using the wrapper. We use let:intersecting={intersecting} to access the property as follows:
<intersectionobserver let:intersecting="{intersecting}" once="{true}"></intersectionobserver>
We can then use the intersecting value to determine when to load<image></image>
Components. In this case, we use if condition to check when it is loading:
<intersectionobserver let:intersecting="{intersecting}" once="{true}"> {#if intersecting} <image src="%7Bsrc%7D" alt="{alt}"></image> {/if} </intersectionobserver>
If a cross occurs, load<image></image>
and receive alt and src attributes. You can learn more about slot properties in this Svelte tutorial.
We have now prepared the code for display when the image scrolls to the screen<image></image>
Components. Let's finally start building the component.
Display image when loading
Yes, you guessed it: let's add an Image.svelte file to the components/Image folder for our<image></image>
Components. This is the component that takes our alt and src attributes and sets them on the img element.
The following is the component code:
export let src export let alt import { onMount } from 'svelte' let loaded = false let thisImage onMount(() => { thisImage.onload = () => { loaded = true } }) img { height: 200px; opacity: 0; transition: opacity 1200ms ease-out; } img.loaded { opacity: 1; } <img src="/static/imghw/default1.png" data-src="https://img.php.cn/" class="lazy" alt="Lazy Loading Images in Svelte">
Check out the demo again:
Remember that you can download the full code for this demo from GitHub. If you want to see how it works on a production site, check out my Shop Ireland project. Lazy loading is used for homepages, category pages, and search pages to help speed up. I hope you can use it for your own Svelte project!
The above is the detailed content of Lazy Loading Images in Svelte. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











At the start of a new project, Sass compilation happens in the blink of an eye. This feels great, especially when it’s paired with Browsersync, which reloads

Let’s attempt to coin a term here: "Static Form Provider." You bring your HTML

In this week's roundup of platform news, Chrome introduces a new attribute for loading, accessibility specifications for web developers, and the BBC moves

Two articles published the exact same day:

The first part of this two-part series detailed how we can get a two-thumb slider. Now we'll look at a general multi-thumb case, but with a different and

This is me looking at the HTML element for the first time. I've been aware of it for a while, but haven't taken it for a spin yet. It has some pretty cool and

GooFonts is a side project signed by a developer-wife and a designer-husband, both of them big fans of typography. We’ve been tagging Google

The document head might not be the most glamorous part of a website, but what goes into it is arguably just as important to the success of your website as its
