svelte-medium-image-zoom
v0.1.5
Published
Accessible medium.com-style image zoom for Svelte
Downloads
908
Maintainers
Readme
svelte-medium-image-zoom
The original medium.com-inspired image zooming library for Svelte.
View the storybook examples
to see various usages.
Features:
<img />
, includingloading="lazy"
<div>
and<span>
with anybackground-image
,background-size
, andbackground-position
- Custom zoom modal content (👇)
- Zero
dependencies
Requirements to know about:
<dialog>
element (caniuse dialog)ResizeObserver
(caniuse ResizeObserver)- Package build target is
ESNext
. If you need to support older environments, run this package through your build system.
Quickstart
npm install --save svelte-medium-image-zoom
<script lang="ts">
import Zoom from 'svelte-medium-image-zoom';
import 'svelte-medium-image-zoom/dist/styles.css';
</script>
<Zoom>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/media/andres-iga.jpg"
width="500"
/>
</Zoom>
API
Note: component type props are rendered as snippets
, check this for more.
example use
export interface ZoomProps {
// Accessible label text for when you want to unzoom.
// Default: 'Minimize image'
a11y_name_button_unzoom?: string;
// Accessible label text for when you want to zoom.
// Default: 'Expand image'
a11y_name_button_zoom?: string;
// Your image (required).
children: Snippet<[]>;
// Custom CSS class to add to the unzoom and zoom buttons.
class_button?: string;
// Custom CSS class to add to the zoomed <dialog>.
class_dialog?: string;
// Transition duration for modal image and overlay elements.
// Default: 300ms
duration?: string | number;
// Provide your own unzoom button icon.
// Default: ICompress
icon_unzoom?: Snippet<[]>;
// Provide your own zoom button icon.
// Default: IEnlarge
icon_zoom?: Snippet<[]>;
// Tell the component whether or not it should be zoomed.
// Default: false
is_zoomed?: boolean;
// Listen for hints from the component about when you
// should zoom (`true` value) or unzoom (`false` value).
on_zoom_change?: (value: boolean) => void;
// Specify what type of element should be used for
// internal component usage. This is useful if the
// image is inside a <p> or <button>, for example.
// Default: 'div'
wrap_element?: 'div' | 'span';
// Provide your own custom modal content component.
zoom_content?: Snippet<[{
img: Snippet<[]>;
button_unzoom: Snippet<[]>;
modal_state: IModalState;
on_unzoom: () => void;
}]>;
// Offset in pixels the zoomed image should
// be from the window's boundaries.
// Default: 0
zoom_margin?: number;
}
Basic Usage
Import the component and the CSS, wrap your image with the component, and the component will handle it's own state.
<script lang="ts">
import Zoom from 'svelte-medium-image-zoom';
import 'svelte-medium-image-zoom/dist/styles.css';
</script>
<!-- <img /> -->
<Zoom>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</Zoom>
<!-- <div> -->
<Zoom>
<div
aria-label="That Wanaka Tree, New Zealand by Laura Smetsers"
role="img"
class="div-img"
style="
background-color: #fff;
background-image: url(/media/laura-smetsers.jpg);
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
width: 500px;
height: 300px;
"
></div>
</Zoom>
Controlled usage
Import the component and the CSS, wrap your image with the component, and then dictate the is_zoomed
with on_zoom_change
handler state to the component.
<script lang="ts">
import Zoom from 'svelte-medium-image-zoom';
import 'svelte-medium-image-zoom/dist/styles.css';
let is_zoomed = $state(false);
</script>
<Zoom
{is_zoomed}
on_zoom_change={(z) => (is_zoomed = z)}
wrap_element="span"
zoom_margin={25}
>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
decoding="async"
loading="lazy"
/>
</Zoom>
The on_zoom_change
prop accepts a callback that will receive true
or false
based on events that occur (like click or scroll events) to assist you in
determining when to zoom and unzoom the component.
Styles
You can import the default styles from svelte-medium-image-zoom/dist/styles.css
and override the values from your code, or you can copy the styles.css
file and alter it to your liking. The latter is the best
option, given rem
s should be used instead of px
to account for different
default browser font sizes, and it's hard for a library to guess at what these
values should be.
An example of customizing the transition duration, timing function, overlay
background color, and unzoom button styles with :focus-visible
can be found in
this story: custom-modal-styles.
Custom zoom modal content
If you want to customize the zoomed modal experience with a caption, form, or
other set of components, you can do so by providing a custom component to the
zoom_content
prop.
View the live example of custom zoom modal content.
Below is some example code that demonstrates how to use this feature.
<script lang="ts">
import Zoom from 'svelte-medium-image-zoom';
import 'svelte-medium-image-zoom/dist/styles.css';
</script>
<Zoom>
{#snippet zoom_content({ img, button_unzoom, modal_state })}
{@render button_unzoom()}
<figure>
{@render img()}
<figcaption
class="zoom-caption zoom-caption--bottom"
class:zoom-caption--loaded={modal_state === 'LOADED'}
>
That Wanaka Tree, also known as the Wanaka Willow, is a willow tree located at the
southern end of Lake Wānaka in the Otago region of New Zealand.
<cite className="zoom-caption-cite">
Wikipedia, <a
className="zoom-caption-link"
href="https://en.wikipedia.org/wiki/That_Wanaka_Tree"
>
That Wanaka Tree
</a>
</cite>
</figcaption>
</figure>
{/snippet}
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
decoding="async"
loading="lazy"
/>
</Zoom>
Credits
This project is inspired from rpearce's react-medium-image-zoom
library.