Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@phucbm/magnetic-button

phucbm369MIT0.0.6TypeScript support: included

A lightweight TypeScript library that creates smooth magnetic attraction effects for HTML elements

magnetic, button, hover, animation, typescript, ui, interaction

readme

🧲 Magnetic Button

A lightweight TypeScript library that creates smooth magnetic attraction effects for HTML elements. Elements with the data-magnetic attribute will gently follow the mouse cursor when it's nearby, creating an engaging hover interaction.

npm version npm downloads npm downloads jsdelivr hits GitHub release pages-build-deployment Publish on Release license Made in Vietnam

✨ Features

  • Zero dependencies - Lightweight and fast
  • TypeScript support - Full type definitions included
  • Auto-initialization - Works with data attributes out of the box
  • Customizable - Fine-tune distance, attraction, and animation speed
  • Smooth animations - Uses linear interpolation for buttery smooth movement
  • Event callbacks - Hook into enter, exit, and update events
  • Modern browsers - Works in all modern browsers that support ES2022

🚀 Demo

Check out the live demo to see the magnetic effect in action!

📦 Installation

npm

npm install @phucbm/magnetic-button

pnpm

pnpm add @phucbm/magnetic-button

yarn

yarn add @phucbm/magnetic-button

CDN


<script type="module">
    import {MagneticButton} from 'https://unpkg.com/@phucbm/magnetic-button/dist/index.js'

    new MagneticButton()
</script>

<script src="https://unpkg.com/@phucbm/magnetic-button/dist/magnetic-button.js"></script>
<script>
    // MagneticButton is available on the window object
    const magnetic = new window.MagneticButton()
</script>

🎯 Quick Start

HTML + Data Attributes (Easiest)

<!DOCTYPE html>
<html>
<head>
    <style>
        .magnetic-btn {
            padding:1rem 2rem;
            border:2px solid #333;
            background:#1a1a1a;
            color:white;
            border-radius:8px;
            cursor:pointer;
            transition:border-color 0.3s ease;
        }

        .magnetic-btn.magnetizing {
            border-color:#ff6b6b;
            box-shadow:0 0 20px rgba(255, 107, 107, 0.3);
        }
    </style>
</head>
<body>
<!-- Basic usage -->
<button class="magnetic-btn" data-magnetic>
    Hover me!
</button>

<!-- With custom parameters -->
<button
        class="magnetic-btn"
        data-magnetic
        data-distance="150"
        data-attraction="0.3"
        data-fraction="0.2">
    Custom magnetic button
</button>

<script type="module">
    import {MagneticButton} from '@phucbm/magnetic-button'

    new MagneticButton() // Auto-initializes all elements with data-magnetic
</script>
</body>
</html>

JavaScript/TypeScript

import {MagneticButton} from '@phucbm/magnetic-button'

// Auto-initialize all elements with data-magnetic attribute
new MagneticButton()

// Or target a specific element
const button = document.querySelector('.my-button')
new MagneticButton(button, {
    distance: 200,
    attraction: 0.5,
    fraction: 0.1,
    onEnter: (data) => console.log('Magnetized!', data),
    onExit: (data) => console.log('Released!', data)
})

⚙️ Configuration Options

Data Attributes

Add these attributes to your HTML elements to customize the magnetic effect:

Attribute Type Default Description
data-magnetic - - Required. Enables magnetic effect on the element
data-distance number 200 Range within which the magnetic effect is active (pixels)
data-attraction number 0.3 Strength of magnetic pull (0 = strong, 1 = weak)
data-fraction number 0.1 Speed of magnetic movement (0 = instant, 1 = slow)

JavaScript Options

When initializing with JavaScript, you can pass these options:

Option Type Default Description
activeClass string 'magnetizing' CSS class added when magnetic effect is active
attraction number 0.3 Strength of magnetic pull (0 = strong, 1 = weak)
distance number 200 Range within which magnetic effect is active (pixels)
fraction number 0.1 Speed of magnetic movement (0 = instant, 1 = slow)
onEnter function () => {} Callback fired when mouse enters magnetic area
onExit function () => {} Callback fired when mouse exits magnetic area
onUpdate function () => {} Callback fired continuously while in magnetic area

🎭 CSS Classes

The library automatically adds CSS classes that you can style:

Class When Applied Description
.is-magnetized Always Added to all magnetic elements for identification
.magnetizing On hover Added when mouse is within magnetic range (customizable via activeClass option)

📋 API Reference

Constructor

new MagneticButton(target ? : HTMLElement | null, options ? : MagneticButtonOptions)

Parameters:

  • target - The HTML element to apply magnetic effect to. If null or omitted, auto-initializes all elements with data-magnetic attribute
  • options - Configuration options (see table above)

Event Data

Callback functions receive a MagneticData object with the following properties:

Property Type Description
deltaX number Horizontal offset from element center
deltaY number Vertical offset from element center
distance number Distance between mouse and element center

🎨 Examples

Strong Attraction


<button data-magnetic data-distance="120" data-attraction="0.1">
    Strong Pull
</button>

Subtle Effect


<button data-magnetic data-distance="80" data-attraction="0.8" data-fraction="0.05">
    Subtle Movement
</button>

Large Detection Area


<button data-magnetic data-distance="300" data-attraction="0.4">
    Wide Range
</button>

With Event Callbacks

new MagneticButton(document.querySelector('.special-btn'), {
    distance: 150,
    attraction: 0.3,
    onEnter: (data) => {
        console.log('Entered magnetic field!')
        // Play sound, trigger animation, etc.
    },
    onExit: (data) => {
        console.log('Left magnetic field!')
        // Reset state, stop animation, etc.
    },
    onUpdate: (data) => {
        // Update UI based on mouse position
        if (data.distance < 50) {
            console.log('Very close to button!')
        }
    }
})

🎯 Tips and Best Practices

Performance

  • The library is optimized and uses requestAnimationFrame internally
  • Avoid initializing too many magnetic elements simultaneously (recommended max: ~20-30)

CSS Styling

/* Smooth transitions for non-magnetic properties */
.magnetic-btn {
    transition:border-color 0.3s ease, box-shadow 0.3s ease;
}

/* Active state styling */
.magnetic-btn.magnetizing {
    border-color:#ff6b6b;
    box-shadow:0 0 20px rgba(255, 107, 107, 0.3);
}

/* Ensure transform doesn't interfere with other transforms */
.magnetic-btn {
    transform-origin:center;
}

Accessibility

The magnetic effect doesn't interfere with keyboard navigation or screen readers, making it accessible by default.

Framework Integration

React:

import {useEffect, useRef} from 'react'
import {MagneticButton} from '@phucbm/magnetic-button'

function MyButton(){
    const buttonRef = useRef(null)

    useEffect(() => {
        const magnetic = new MagneticButton(buttonRef.current, {
            distance: 150,
            attraction: 0.3
        })
    }, [])

    return <button ref={buttonRef}>Magnetic Button</button>
}

Vue:


<template>
  <button ref="buttonRef">Magnetic Button</button>
</template>

<script setup>
  import {ref, onMounted} from 'vue'
  import {MagneticButton} from '@phucbm/magnetic-button'

  const buttonRef = ref(null)

  onMounted(() => {
    new MagneticButton(buttonRef.value, {
      distance: 150,
      attraction: 0.3
    })
  })
</script>

🌐 Browser Support

  • Chrome 63+
  • Firefox 61+
  • Safari 13.1+
  • Edge 79+

📄 License

MIT © phucbm

🤝 Contributing

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