Hover✨ Premium

Scratch Reveal

Digital scratch card: a canvas covers a text reward; scratch with mouse or finger, or click "Reveal all" to clear it in one go.

CanvasRevealGame

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →

3 usage examples

Poll results in a messaging app — team chat interface — Scratch Reveal example 1

① Poll results in a messaging app — team chat interface

WhenAfter a poll sent in a message thread, vote results are hidden behind a scratch card; each participant scratches their version to reveal the percentages.
WhyHiding results behind a scratch card prevents group influence before everyone has voted, and creates a collective reveal moment instead of a simple counter update.
Settings260×88 px container embedded in a message bubble. .sck-reveal holds two result rows (name + percentage + bar) layered over the chat interface.
Surprise destination — travel application — Scratch Reveal example 2

② Surprise destination — travel application

WhenIn a travel app, a large scratch card (420×180 px) hides the recommended weekend destination; the user scratches to discover the city and country.
WhyA large scratch card turns a destination recommendation into an event rather than a simple dropdown; the deliberate friction increases engagement before the reveal.
Settings420×180 px container centred in the main section. .sck-reveal shows the city name large (28 px), the country, and an ideal season tag.
Course completion badge — e-learning interface — Scratch Reveal example 3

③ Course completion badge — e-learning interface

WhenAt the end of a learning path, the level badge (gold, silver, bronze) is hidden behind a small scratch card (180×90 px); the learner scratches to reveal it after completing all modules.
WhyA scratchable badge turns course completion into a memorable ritual — the learner earns unlocking their reward by hand rather than seeing it appear automatically.
Settings180×90 px container in the reward area of a progress interface. .sck-reveal shows the badge icon, the level title, and a rank label (gold/silver/bronze).

How it works

The .fx-0375-root frame holds a .sck-container that layers a .sck-reveal div (the reward: text, background colour) and a .sck-cover canvas positioned absolute on top. On load, setup() uses fixed internal dimensions of W=300 px and H=150 px (hard-coded), and multiplies by devicePixelRatio for the canvas resolution, then fills the canvas with a solid grey. The display size of the canvas (CSS on .sck-container) may differ from 300×150 — scratch coordinates are normalised by scaleX = W / rect.width and scaleY = H / rect.height to always cover the full visible surface. On a Retina screen, the internal canvas is twice its displayed size, keeping scratch edges sharp.

mousemove and touchmove events on the canvas erase a 40 px radius circle at the pointer's position via ctx.globalCompositeOperation = 'destination-out': this operation makes the canvas transparent where the pointer passes, revealing .sck-reveal underneath. touchmove calls preventDefault() to block scrolling. Erasing is permanent: there is no automatic reset.

A .sck-reveal-btn button calls ctx.clearRect() to clear the entire canvas in one click. The .sck-reveal div carries aria-live="polite" so its content is announced by screen readers.

Accessibility

  • Reduced motion: scratching is a user gesture — there is no automatic animation to disable. The experience is identical under prefers-reduced-motion: reduce. The "Reveal all" button lets users uncover the reward without scratching.
  • "Reveal all" button: a native <button> clears the entire canvas in one click or key press — an alternative to scratching for users who cannot use a mouse.
  • Reward announcement: the .sck-reveal div carries aria-live="polite"; its content is announced by screen readers when it becomes perceptible (after full scratch or "Reveal all" click). Note: aria-live only announces content when the text changes; make sure the text is present from load.
  • Decorative canvas: the scratch canvas carries aria-hidden="true". All useful information is in .sck-reveal.

Browser compatibility

2D canvas (destination-out) + 2 KB of JavaScript, no dependency. The destination-out operation is available in all modern browsers. devicePixelRatio available everywhere. Touch events available on all modern mobiles. Measured in Chromium 151, Firefox 153 and WebKit 26: scratching, full reveal and aria-live announcement identical in all three. On Safari iOS, touch scratching works correctly with touch-action: none.

Chrome 60+✓ Full
Firefox 55+✓ Full
Safari 11+✓ Full
Edge 79+✓ Full
Mobile iOS 11+✓ Full (touch)
Android Chrome 60+✓ Full (touch)

Without JavaScript, the canvas stays in place and hides .sck-reveal — the reward is not visible. It is advisable to add a static reveal link or button visible without JavaScript.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0375-root">
  <div class="sck-wrap">
    <div class="sck-container">
      <div class="sck-reveal" aria-live="polite">YOU WON!</div>
      <canvas class="sck-cover" aria-hidden="true"></canvas>
    </div>
    <button class="sck-reveal-btn" type="button">Reveal all</button>
    <span class="sck-label" aria-hidden="true">Scratch to reveal</span>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Reward to reveal (HTML — content of .sck-reveal) "YOU WON!" on a coloured background Replace with any HTML: a promo code, an SVG image, a profile text. The .sck-reveal background is fully customisable in CSS.
Scratch brush radius (JS — radius = 40) 40 px Lower to 20 px for more precise scratching (thin finger); raise to 60-80 px to clear quickly with a broad movement.
Canvas colour (JS — fillStyle in setup()) grey (#aaa) Switch to #c0a060 for a golden tint, #b0b0b0 for silver. You can also use a gradient (createLinearGradient) or draw a pattern before calling fill().
Reveal button label (HTML — content of .sck-reveal-btn) "Reveal all" Replace with "Reveal now", "I give up!" or any contextual label.
Canvas size (CSS — .sck-container) 300×150 px Adjust the container's width and height. The canvas automatically fits those dimensions via setup().

FAQ

Yes. After each erase, read pixels with ctx.getImageData() and count transparent pixels (alpha channel = 0). If the ratio exceeds 70%, trigger your action (validation animation, API call). Note: getImageData() can be expensive on a large canvas — throttle checks (every 50 ms, for example).
Yes. Call setup() again: it clears and refills the canvas. You can expose this function from outside by assigning it to root._reset = setup.
This effect is a UI information-reveal component — not a gambling mechanism. There is no server-side random number generator, no integrity check, no applicable regulation (gambling laws). For a real lottery system, the result must be generated and validated server-side before display.