A lightweight, framework-agnostic browser watermark library with visible, image, and blind watermarks.
Documentation · Live examples · Configuration · Discussions · Changelog
English · 简体中文
watermark-js-plus is a canvas-based TypeScript library for adding watermarks in the browser. It works with vanilla JavaScript and frontend frameworks without requiring a framework-specific adapter.
Use it to protect a page or container with a visible watermark, render a watermark directly into an existing image, or create and reveal low-opacity blind watermarks. The library also supports runtime updates, grid layouts, rich styling, and automatic recovery from common DOM tampering.
- Three focused APIs — page and container watermarks, image watermarks, and blind watermarks.
- Rich content — text, multi-line text, images, and rich text.
- Flexible layouts — default and configurable grid layouts with precise positioning.
- Advanced styling — opacity, rotation, typography, shadows, gradients, patterns, filters, and animation.
- Lifecycle control — create, update, check, and destroy watermark instances at runtime.
- Tamper recovery — optional
MutationObservermonitoring recreates modified or removed watermark nodes. - TypeScript-first — complete public type declarations are included.
- Multiple delivery formats — ESM, CommonJS, UMD, IIFE, CDN, and a dedicated legacy-browser entry.
| Export | Use case | Guide |
|---|---|---|
Watermark |
Add a watermark over the page or a specific container | Page and container watermarks |
ImageWatermark |
Render text or an image watermark into an existing <img> element |
Image watermarks |
BlindWatermark |
Create a low-opacity watermark and reveal it from a captured image | Blind watermarks |
npm install watermark-js-pluspnpm add watermark-js-plusyarn add watermark-js-plusimport { Watermark } from 'watermark-js-plus'
const watermark = new Watermark({
content: 'Confidential',
width: 220,
height: 160,
rotate: 22,
globalAlpha: 0.15,
})
await watermark.create()Pass a selector or an element through parent to scope the watermark to a specific container. The target container must establish a positioning context, for example with position: relative:
#report {
position: relative;
}const watermark = new Watermark({
parent: '#report',
content: 'Internal use only',
})
await watermark.create()Update or remove an existing watermark with its lifecycle methods:
await watermark.changeOptions({ content: 'Updated watermark' }, 'append')
const exists = await watermark.check()
watermark.destroy()Most applications should use the standard watermark-js-plus entry shown above. If your bundler supports tree-shaking, you can use the preserved-module ESM entry to help it exclude unused modules:
import { Watermark } from 'watermark-js-plus/es'The ESM entry also exports BlindWatermark and ImageWatermark. When using movable: true, import the stylesheet separately:
import 'watermark-js-plus/style.css'See the optimized imports guide for details.
BlindWatermark.decode() enhances a blind watermark contained in an image and returns the processed image as a data URL:
import { BlindWatermark } from 'watermark-js-plus'
BlindWatermark.decode({
url: '/images/blind-watermark.png',
onSuccess: (imageBase64: string) => {
const decodedImage = new Image()
decodedImage.src = imageBase64
decodedImage.alt = 'Decoded blind watermark'
document.body.appendChild(decodedImage)
},
})Pin the package version when loading it from a CDN:
<script src="https://cdn.jsdelivr.net/npm/watermark-js-plus@1.6.6/dist/index.iife.min.js"></script>
<script>
const watermark = new WatermarkPlus.Watermark({
content: 'Confidential',
})
watermark.create()
</script>The core package is framework-agnostic. Live examples are available for vanilla JavaScript, React, Next.js, Remix, Vue 2, Vue 3, Nuxt, Quasar, Angular, SvelteKit, Astro, IIFE, and Webpack.
Watermark rendering requires browser DOM and Canvas APIs. In SSR applications, create the watermark in a client-side lifecycle hook such as useEffect() or onMounted().
The default entry targets modern browsers. Use the dedicated entry for IE11 and partial IE10/IE9 compatibility, including the blind-watermark decode fallback introduced in v1.6.6:
import { Watermark } from 'watermark-js-plus/ie'See the legacy-browser guide for details.
- DOM tamper recovery is a best-effort deterrent, not a security boundary or DRM system. A user with full control of the page runtime can still bypass it.
- Blind watermark visibility depends on screenshot scaling, image compression, display characteristics, and background colors.
BlindWatermark.decode()reveals the watermark visually; it does not extract the original text as structured data.- Cross-origin images must provide suitable CORS headers before Canvas can safely export the result.
- Getting started
- Configuration reference
- Core API lifecycle
- Optimized ESM imports
- Live framework examples
- Demo collection
Contributions are welcome. Read the contribution guide, open an issue, or start a discussion.
Please follow the project Code of Conduct when participating.
Thanks to everyone who has contributed to watermark-js-plus.
MIT © Michael Sun