npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

svelte-medium-image-zoom

v0.1.5

Published

Accessible medium.com-style image zoom for Svelte

Downloads

908

Readme

svelte-medium-image-zoom

NPM Version NPM License NPM Unpacked Size NPM Downloads

The original medium.com-inspired image zooming library for Svelte.
View the storybook examples to see various usages.

Features:

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 rems 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.