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 🙏

© 2026 – Pkg Stats / Ryan Hefner

scale-like-image

v1.2.1

Published

Makes any HTML element scale responsively like an image

Readme

ScaleLikeImage

A lightweight JavaScript library that makes any HTML element scale responsively like an image, maintaining aspect ratio and fitting within its container using CSS transforms.

Features

  • 🎯 Simple API - Just pass in your elements, it handles the rest
  • 📱 Fully Responsive - Automatically adjusts on window resize, orientation change
  • 🎨 Padding Aware - Respects container padding just like native images
  • Performance Optimized - Uses CSS transforms and ResizeObserver
  • 🔧 No Dependencies - Pure vanilla JavaScript, ~4KB minified
  • 🌐 Universal - Works with any HTML element (divs, charts, infographics, etc.)

Installation

NPM

npm install scale-like-image

CDN

<script src="https://cdn.jsdelivr.net/npm/scale-like-image@latest/dist/scale-like-image.min.js"></script>

Direct Download

<!-- Development (with sourcemap) -->
<script src="dist/scale-like-image.js"></script>

<!-- Production (minified, 4.5KB) -->
<script src="dist/scale-like-image.min.js"></script>

ESM Import

import scaleLikeImage from 'scale-like-image';

Quick Start

// Make an element scale like an image
scaleLikeImage('#my-chart');

// Multiple elements
scaleLikeImage('.infographic');

// With options
scaleLikeImage('#content', {
    defaultWidth: 1200,
    maxScale: 1
});

How It Works

The library wraps your element in a div and applies CSS transforms to scale it proportionally, just like an image with object-fit: contain. Your element is set to a fixed width internally and visually scales to fit the available space.

Before

<div class="chart">
    <!-- Your content -->
</div>

After (automatically created)

<div class="sli-wrapper" style="width: 100%; overflow: hidden; height: 300px;">
    <div class="chart sli-scaled" style="width: 800px; transform-origin: top left; transform: scale(0.5);">
        <!-- Your content -->
    </div>
</div>

API

scaleLikeImage(elements, options)

Parameters

  • elements - Can be:

    • CSS selector string: '.my-class' or '#my-id'
    • Single Element: document.getElementById('chart')
    • NodeList: document.querySelectorAll('.item')
    • Array of Elements: [elem1, elem2]
  • options - Configuration object (optional)

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | defaultWidth | number | 800 | Fixed width applied to the element for scaling calculations (px) | | maxScale | number | 1 | Maximum scale factor (1 = never scale up) | | minScale | number | 0 | Minimum scale factor (0 = no limit) | | maintainHeight | boolean | true | Adjust wrapper height after scaling | | responsive | boolean | true | Auto-update on resize | | debounceDelay | number | 100 | Resize debounce delay (ms) | | className | object | See below | Custom class names | | onScale | function | null | Callback: (element, scaleFactor) => {} | | offset | number | 0 | Pixel offset for width calculation | | scaleBelow | number|null | null | Width threshold — element is natural above this width, scales down like an image below it |

Default Class Names

{
    wrapper: 'sli-wrapper',
    scaled: 'sli-scaled'
}

Return Value

Returns a controller object with these methods:

const controller = scaleLikeImage('#my-element');

// Manually trigger rescaling
controller.update();

// Update options
controller.setOptions({ maxScale: 1.5 });

// Get current scale factors
const scales = controller.getScale();
// Returns: [{ element: Element, scale: 0.75 }]

// Remove all modifications
controller.destroy();

// Access managed elements
controller.elements   // Array of elements
controller.wrappers   // Array of wrapper divs

Examples

Basic Usage

<!-- Your fixed-width element -->
<div id="infographic" style="width: 1200px;">
    <h1>My Infographic</h1>
    <p>Content that needs to scale...</p>
</div>

<script>
// Make it scale like an image
scaleLikeImage('#infographic');
</script>

Multiple Elements

// Scale all dashboard widgets
scaleLikeImage('.dashboard-widget', {
    defaultWidth: 600,
    maxScale: 1.2
});

Manual Control

// Disable auto-resize and control manually
const controller = scaleLikeImage('.manual-element', {
    responsive: false
});

// Update when needed
document.getElementById('update-btn').addEventListener('click', () => {
    controller.update();
});

// Clean up when done
document.getElementById('remove-btn').addEventListener('click', () => {
    controller.destroy();
});

With Callback

scaleLikeImage('.tracked-element', {
    onScale: (element, scaleFactor) => {
        console.log(`Element scaled to ${scaleFactor}`);

        // Adjust other elements based on scale
        if (scaleFactor < 0.5) {
            element.classList.add('small-view');
        }
    }
});

No Width Required

// Elements without width get default 800px
scaleLikeImage('.no-width-element', {
    defaultWidth: 1000  // Override default
});

Advanced Usage

Dynamic Content

const controller = scaleLikeImage('.dynamic-content');

// After content changes
function loadNewContent() {
    // ... modify element content ...
    controller.update();  // Recalculate scale
}

Responsive Breakpoints

const controller = scaleLikeImage('.responsive-element');

// Adjust options based on viewport
function updateOptions() {
    if (window.innerWidth < 768) {
        controller.setOptions({ maxScale: 0.8 });
    } else {
        controller.setOptions({ maxScale: 1 });
    }
}

window.addEventListener('resize', updateOptions);

Integration with Frameworks

// React example
useEffect(() => {
    const controller = scaleLikeImage(ref.current, {
        defaultWidth: 1200
    });

    return () => {
        controller.destroy();
    };
}, []);

Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)
  • Opera (latest)
  • IE11 (with ResizeObserver polyfill)
  • Mobile browsers (iOS Safari, Chrome Mobile)

Common Use Cases

  1. Infographics - Fixed-width designs that need to be responsive
  2. Charts & Graphs - Data visualizations with specific dimensions
  3. Timeline Components - Horizontal timelines that need to fit containers
  4. Dashboard Widgets - Fixed-size widgets in responsive layouts
  5. Marketing Materials - Promotional content with precise layouts
  6. Interactive Demos - UI components that need proportional scaling

Troubleshooting

Element not scaling

  • Check that the wrapper's parent has available width
  • Verify JavaScript is loading after DOM is ready

Scale calculation seems wrong

  • Check for CSS box-sizing on the wrapper's parent
  • Use offset option to fine-tune if needed

Performance issues

  • Increase debounceDelay for resize events
  • Consider disabling responsive and manually calling update()
  • Use CSS will-change: transform on frequently scaled elements

Tips

  1. defaultWidth is always applied - The library sets your element to defaultWidth and scales from there
  2. Overflow - The wrapper has overflow: hidden automatically
  3. Print styles - Consider destroying/recreating for print: controller.destroy()
  4. Animations - Apply to the wrapper, not the scaled element
  5. Z-index issues - Adjust on the wrapper as needed

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues, questions, or suggestions, please open an issue on GitHub.