Watermark
A container-level watermark layer that sits on top of the content without intercepting any interaction, suitable for preventing sensitive information from leaking.
Rendering engine: text and grayscale image watermarks are drawn on a canvas (the tile is tiled via toDataURL as a background), scaled by devicePixelRatio so they stay sharp on high-DPI screens; SSR and canvas-less environments automatically fall back to an SVG data-uri (fill=currentColor follows the theme). Both paths render an identical structure, and true hydration takes over after validating it. Tiles are cached by paint parameters and repainted only when a relevant attribute or the theme color changes; window resize is handled natively by background tiling.
Text Watermark
Basic text watermark
text generates a diagonally tiled unit; with repeat the unit is tiled, otherwise a single unit is centered.
Single Unit and Opacity
Single centered + opacity
opacity controls the transparency of the watermark layer (0–1, automatically clamped to bounds).
Image Watermark
Image watermark
Image Grayscale
grayscale: grayscale image filter
With grayscale, the image watermark is converted to grayscale via canvas filter: grayscale(1) (cross-origin images require CORS headers from the origin, otherwise it falls back to the original image); canvas-less environments fall back to a layer CSS filter, so the capability is never lost.
No Interaction Interception
Normal content interaction
The watermark layer has `pointer-events: none`, so interactions with buttons / inputs above are completely unaffected.
Empty Container
Watermark shown without content
When the container has no slot content at all, the watermark layer still renders.
Multi-line, Rotate and Font
Multi-line text / rotate / font family
text supports a JSON array (or \n) for multiple lines; rotate controls the angle (default -30); font-size / font-weight / font-family are applied to the canvas text; color accepts 11 preset names (resolved to --oas-preset-* tokens, dark-adaptive) or any CSS color value. By default the watermark follows the theme text color (visible in dark mode too, and repainted automatically on theme switch). The first tile intentionally keeps CJK text (["内部资料","CONFIDENTIAL"]) to demonstrate multi-font rendering through the canvas font stack.
Gap and Offset
gap / offset tiling parameters
gap="[x,y]" controls the tile spacing (defaults to the tile size) and offset="[x,y]" controls the starting offset (defaults to gap/2); width / height resize the text tile (auto-fit to content when unset: rotated bounding box + padding, so every tile fully contains the text at default density), and z-index raises the watermark layer (default 2).
Staggered Layout
staggered odd/even row offset
With staggered, a second background layer offset by half a tile staggers the odd/even rows (repeat mode only).
Tamper Proof
tamper-proof: a watermark you cannot simply delete
No tampering detected yet
tamper-proof is on by default (="false" turns it off): a MutationObserver watches for the watermark layer being removed or its style being rewritten, re-mounts/restores it automatically, and fires an oas-remove event (detail.type is removed / modified). It deters casual removal, not determined attackers — it is not a security boundary.
Movable Watermark
movable: drag the watermark
With movable, the watermark layer takes over pointer input (grab/grabbing cursor) and writes the drag displacement to the offset attribute — a controlled channel, so the position survives re-renders. Note that in this mode the watermark layer intercepts interactions over the area it covers.
Fullscreen Watermark
fullscreen: a watermark covering the whole viewport
Click the button to enable a fullscreen watermark: the host becomes fixed and covers the viewport, stays put while the page scrolls, and intercepts no interaction; click again to turn it off.
With fullscreen, the component itself becomes position: fixed; inset: 0 covering the viewport (pointer-events: none) — no wrapper needed; it defaults to the topmost z-index, adjustable via the z-index attribute or the --oas-watermark-fullscreen-z-index CSS variable. It composes with repeat / staggered / movable / grayscale; without fullscreen, container mode behaves exactly as before. Note: slotted content is not laid out or interactive in fullscreen mode.
API
oas-watermark
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
color | Watermark text color: 11 preset names (--oas-preset-*) or any CSS color; defaults to the primary text token | string | — |
font-family | Font family (default sans-serif) | string | sans-serif |
font-size | Font size in px (default 16) | string | 16 |
font-weight | Font weight (default 400) | string | 400 |
fullscreen | Fullscreen watermark: the host becomes fixed inset:0 covering the viewport (pointer-events:none) at the topmost z-index by default (adjustable via the z-index attribute or --oas-watermark-fullscreen-z-index); stays put while scrolling | boolean | — |
gap | Tiling gap JSON [x,y] (defaults to tile size) | string | — |
grayscale | Grayscale filter for image watermarks (canvas filter: grayscale(1)); falls back to a layer CSS filter without canvas | boolean | — |
height | Text tile height (auto-fits content when unset; image default 120) | string | — |
image | Image watermark URL (takes precedence over text when present) | string | — |
movable | Draggable watermark (drag delta writes back to the offset attribute) | boolean | — |
offset | Tiling start offset in px or JSON [x,y] (default gap/2, visually identical to the old centered mode) | string | — |
opacity | Watermark layer transparency (0–1, auto-clamped) | string | 0.15 |
repeat | Boolean; when present the unit is tiled, otherwise a single unit is centered | boolean | — |
rotate | Rotation in degrees (default -30) | string | -30 |
staggered | Staggered layout (two-layer background, second layer offset by offset + gap/2; tiling mode only) | boolean | — |
tamper-proof | Tamper protection (default true): a MutationObserver re-mounts the layer when it is removed/modified and fires oas-remove; "false" disables it | string | true |
text | Text watermark content (either text or image) | string | — |
width | Text tile width (auto-fits content when unset: rotated bounding box + padding; image default 240) | string | — |
z-index | Watermark layer z-index (default 2); in fullscreen mode it is written to the host, overriding the default topmost level | string | — |
Events
| Event | Description |
|---|---|
oas-remove | Fired when tamper protection detects the layer being removed/modified, detail: { type: "removed" | "modified" } |
Slots
| Name | Description |
|---|---|
| default | Content covered by the watermark |
CSS Variables
| CSS Variable | Default |
|---|---|
--oas-watermark-fullscreen-z-index | 2147483647 |
The watermark is a decorative layer (aria-hidden + pointer-events: none): it is excluded from the accessibility tree and does not intercept interaction.