Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/zerodevx/svelte-img

High-performance responsive/progressive images for SvelteKit
https://github.com/zerodevx/svelte-img

progressive-image-loading responsive-images svelte sveltekit vite-plugin

Last synced: 6 days ago
JSON representation

High-performance responsive/progressive images for SvelteKit

Awesome Lists containing this project

README

        

# svelte-img

> High-performance responsive/progressive images for SvelteKit.

Automatically transform local images into multiple widths and next-gen formats, then render a
minimally invasive LQIP-included HTML representation into your SvelteKit project.

Includes special effects:

- [x] Fade-in on image reveal
- [x] Parallax vertical scroll effect

Hope you like cats. Demo: https://zerodevx.github.io/svelte-img/

## Install

Install the package:

```
$ npm i -D @zerodevx/svelte-img
```

Add `imagetools` plugin into your `vite.config.js`:

```js
import { defineConfig } from 'vite'
import { sveltekit } from '@sveltejs/kit/vite'
import { imagetools } from '@zerodevx/svelte-img/vite'

export default defineConfig({
plugins: [sveltekit(), imagetools()]
})
```

Optionally, to silence typescript
[warnings](https://github.com/JonasKruckenberg/imagetools/issues/160) on image imports, create a new
file at `src/ambient.d.ts`:

```js
// Squelch warnings of image imports from your assets dir
declare module '$lib/assets/*' {
var meta
export default meta
}
```

### Under the hood

Local image transformations are delegated to the excellent
[`vite-imagetools`](https://github.com/JonasKruckenberg/imagetools) with a custom `run` directive.
This preset generates optimised images with sensible defaults, including a `base64` low-quality
image placeholder.

Invoke the preset with the `?as=run` query param:

```js
import imageMeta from 'path/to/asset?as=run'
```

## Usage

Use anywhere in your Svelte app:

```html

// Import original full-sized image with `?as=run` query param
import cat from '$lib/assets/cat.jpg?as=run'
import Img from '@zerodevx/svelte-img'

Very meow
```

The image component renders into:

```html




Very meow

```

## Features

### Change default widths/formats

By default, `svelte-img` generates 9 variants of an original full-sized image - at `480/1024/1920`
widths in `avif/webp/jpg` formats; and a `16px webp/base64` low-quality image placeholder (LQIP).

To change this globally, edit your `vite.config.js`:

```js
import ...

// By default, `run` is set to 'w=480;1024;1920&format=avif;webp;jpg' (9 variants)
export default defineConfig({
plugins: [
sveltekit(),
imagetools({
profiles: {
// Now we change `run` to generate 4 variants instead: 640/1280w in webp/jpg
run: new URLSearchParams('w=640;1280&format=webp;jpg')
}
})
]
})
```

> [!NOTE]
> `runDefaultDirectives` is deprecated and will be removed in the next major; use `profiles`
> instead. When a profile is not used, behaviour falls back to standard `vite-imagetools`, which in
> turn take defaults from `defaultDirectives` as usual, so both can co-exist.

### Profiles

Use profiles to manage multiple defaults. Define in your `vite.config.js`:

```js
export default defineConfig({
plugins: [
sveltekit(),
imagetools({
profiles: {
sm: new URLSearchParams('w=640&format=webp;jpg'),
lg: new URLSearchParams('w=640;1280;1920&format=webp;jpg')
}
})
]
})
```

Then invoke in your app:

```js
import sm from '$lib/a/1.jpg?as=sm' // use `sm` profile
import lg from '$lib/a/2.jpg?as=lg' // use `lg` profile
import normal from '$lib/a/3.jpg?as=run'
```

### On a per-image basis

Widths/formats can be applied to a particular image. From your `.svelte` file:

```html

// We override defaults to generate 4 variants: 720/1560w in webp/jpg
import src from '$lib/a/cat.jpg?w=720;1560&format=webp;jpg&as=run'
import Img from '@zerodevx/svelte-img'

cat
```

> [!NOTE]
> Order of `format` matters - the _last_ format is used as the fallback image.

If just **one** variant is generated, then only the `` tag renders, so:

```html

// Generate only 1 variant: 640x640 in jpg
import src from '$lib/a/cat.jpg?w=640&h=640&format=jpg&as=run'
import Img from '@zerodevx/svelte-img'

cat
```

Renders into:

```html
cat
```

### Change LQIP width

The `run` directive takes an optional parameter that sets the LQIP's width. Using `?as=run` defaults
to `16px` LQIP - functionally equivalent to `?as=run:16`. Increase for a higher quality LQIP (eg.
`?as=run:32` for `32px` LQIP) at the expense of a larger inline `base64` (larger HTML size).

To disable LQIP, set `?as=run:0`.

For a dominant single-colour background, set `?as=run:1`, so:

```html

import src from '$lib/a/cat.jpg?as=run:1'
import Img from '@zerodevx/svelte-img'

cat
```

Renders into:

```html


```

### Other transformations

The full [repertoire](https://github.com/JonasKruckenberg/imagetools/blob/main/docs/directives.md)
of transformation directives offered by
[`vite-imagetools`](https://github.com/JonasKruckenberg/imagetools) can be used.

```html

// Generate all 9 variants at fixed 600px height
import src from '$lib/a/cat.jpg?h=600&fit=cover&normalize&as=run'
import Img from '@zerodevx/svelte-img'

cat
```

### Responsive Image Sizes

Use the `sizes` attribute to define media conditions that provide hints as to which image size to
select when those conditions are true. Read up more on
[responsive images and the picture element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture).

```html

import src from '$lib/a/cat.jpg?w=480;800&as=run'
import Img from '@zerodevx/svelte-img'

cat
```

Renders into:

```html




cat

```

### Lazy loading

`svelte-img` utilises the browser's native lazy loading capability by setting the `loading="lazy"`
attribute on the rendered `` tag by default. This is supported by
[most modern browsers](https://caniuse.com/loading-lazy-attr). To load an image eagerly instead:

```html

import src from '$lib/a/cat.jpg?as=run'
import Img from '@zerodevx/svelte-img'

cat
```

### Batch loading local images

Use `Vite`'s `import.meta.glob` [feature](https://vitejs.dev/guide/features.html#glob-import).

```html

import Img from '@zerodevx/svelte-img'

const modules = import.meta.glob('$lib/a/cats/*.*', {
import: 'default',
eager: true,
query: { w: 640, h: 640, fit: 'cover', as: 'run' }
})
const images = Object.entries(modules).map((i) => i[1])

{#each images as src}
cat
{/each}
```

### Remote images from an API

Use the `svelte-img` component on its own by passing a `src` object, like so:

```html

import Img from '@zerodevx/svelte-img'

const src = {
sources: {
// Order is important; last format is fallback img
webp: 'path/to/480.webp 480w, ...', //srcset
jpeg: '...'
},
img: { src: 'path/to/img', w: 1920, h: 1080 },
}

cat
```

### Blurred image placeholders

Natively, browsers do already apply _some_ blur when displaying low resolution images. That's enough
for me, but you can apply your own using CSS.

```html

import Img from '@zerodevx/svelte-img'
import src from '$lib/a/cat.jpg?as=run'
import { onMount } from 'svelte'

let ref, loaded
onMount(() => {
if (ref.complete) loaded = true
})


(loaded = true)} />

.wrap {
position: relative;
overflow: hidden;
}
.blur {
position: absolute;
inset: 0;
backdrop-filter: blur(20px);
pointer-events: none;
}
.loaded {
display: none;
}

```

## Special Effects

### Fade-in on reveal

Reveal images with a fade-in effect (aka medium.com) when they are loaded **and** in the viewport.

```html

import src from '$lib/a/cat.jpg?as=run'
import { FxReveal as Img } from '@zerodevx/svelte-img'

cat

:global(.my-img) {
width: 640px;
height: 480px;

/* These CSS vars (with their default values) are exposed */
--reveal-transform: scale(1.02);
--reveal-transition: opacity 1s ease-in, transform 0.8s ease-out;
--reveal-filter: blur(20px);
}

```

### Parallax

Apply a vertical parallax scrolling effect to an image, where `factor` is a decimal value between 0
and 1, that controls how much slower the element scrolls, relative to the scrolling speed:

- A value closer to 0 is faster, while a value closer to 1 is slower.
- A value of 1 behaves normally.
- A value of 0 effectively makes the element fixed on the page.

The default factor is `0.75`.

```html

import src from '$lib/a/cat.jpg?as=run'
import { FxParallax as Img } from '@zerodevx/svelte-img'

cat

:global(.my-img) {
width: 100%;
height: 28rem;
}

```

## Development

Library is packaged via [SvelteKit](https://kit.svelte.dev/docs/packaging). Standard Github
[contribution workflow](https://docs.github.com/en/get-started/quickstart/contributing-to-projects)
applies.

### Tests

End-to-end testing via [Playwright](https://github.com/microsoft/playwright). To run tests
headlessly:

```
$ npm run test
```

## Changelog

Please refer to the [releases](https://github.com/zerodevx/svelte-img/releases) page.

## License

ISC