Click-to-Reveal Blur
🤓 Want a quick “privacy blur” effect? Wrap any section with data-reveal and it will render blurred until clicked/tapped.
Clicking toggles reveal/hide, and you can also use a tiny “Reveal all / Hide all” control if you want.
<!--
Click-to-Reveal Blur (Privacy Toggle)
- No frameworks
- Works on desktop + mobile
- Blur any block by adding: data-reveal
- Optional per-block label: data-reveal-label="Tap to reveal"
Usage examples:
<div data-reveal data-reveal-label="Tap to reveal preview"> ... </div>
<img data-reveal src="thumb.jpg" alt="Preview">
Optional controls:
<button type="button" data-reveal-all>Reveal all</button>
<button type="button" data-hide-all>Hide all</button>
-->
<style>
/* Scoped with .vs-reveal-root so it won’t mess with your site */
.vs-reveal-root [data-reveal]{
position:relative;
cursor:pointer;
user-select:none;
-webkit-tap-highlight-color: transparent;
}
/* The blurred state */
.vs-reveal-root [data-reveal].is-hidden{
filter: blur(14px);
transform: translateZ(0); /* keeps blur smooth on some browsers */
}
/* Overlay label */
.vs-reveal-root [data-reveal].is-hidden::after{
content: attr(data-reveal-label);
position:absolute;
inset:0;
display:grid;
place-items:center;
text-align:center;
padding:14px;
font: 800 14px/1.2 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;
color:#0c0f14;
background: rgba(255,255,255,.72);
border: 1px solid rgba(30,40,80,.14);
border-radius: 14px;
box-shadow: 0 10px 30px rgba(20,24,70,.08);
pointer-events:none;
}
/* Make overlay fit nicely when the reveal element is a block with no radius */
.vs-reveal-root [data-reveal].is-hidden{
border-radius: 14px;
overflow: hidden;
}
/* Optional: a subtle “pressed” feel */
.vs-reveal-root [data-reveal]:active{
transform: scale(.995);
}
</style>
<script>
(function(){
"use strict";
// Wrap your reveal section in <div class="vs-reveal-root"> ... </div>
// If you don’t, we’ll fall back to document (still safe because selectors are scoped).
var root = document.querySelector(".vs-reveal-root") || document;
function ensureLabel(el){
if (!el.getAttribute("data-reveal-label")) {
el.setAttribute("data-reveal-label", "Tap to reveal");
}
}
function hide(el){
ensureLabel(el);
el.classList.add("is-hidden");
el.setAttribute("aria-hidden", "true");
}
function show(el){
el.classList.remove("is-hidden");
el.removeAttribute("aria-hidden");
}
function toggle(el){
if (el.classList.contains("is-hidden")) show(el);
else hide(el);
}
function all(){
return Array.prototype.slice.call(root.querySelectorAll("[data-reveal]"));
}
// Initialize all reveal blocks as hidden by default
all().forEach(function(el){
hide(el);
// Make sure positioned overlay works on inline elements too
var cs = window.getComputedStyle(el);
if (cs.display === "inline") el.style.display = "inline-block";
// If element has no height (e.g., empty), overlay can't show; that's fine.
});
// Click/tap to toggle (supports nested clicks too)
root.addEventListener("click", function(e){
var el = e.target.closest ? e.target.closest("[data-reveal]") : null;
if (!el || !root.contains(el)) return;
toggle(el);
}, true);
// Optional controls
var btnRevealAll = root.querySelector("[data-reveal-all]");
if (btnRevealAll) {
btnRevealAll.addEventListener("click", function(){
all().forEach(show);
});
}
var btnHideAll = root.querySelector("[data-hide-all]");
if (btnHideAll) {
btnHideAll.addEventListener("click", function(){
all().forEach(hide);
});
}
})();
</script>
<!-- Example wrapper (optional, but recommended for scoping) -->
<div class="vs-reveal-root">
<p style="margin:10px 0">
<button type="button" data-reveal-all>Reveal all</button>
<button type="button" data-hide-all>Hide all</button>
</p>
<div data-reveal data-reveal-label="Tap to reveal preview" style="padding:14px;border:1px solid rgba(30,40,80,.14);border-radius:14px;background:#fff">
<strong>Hidden preview</strong><br>
This block starts blurred and reveals on click/tap.
</div>
</div>
Comments (0)
No comments yet — be the first.