<div class="locker" data-locker="css-cheat-sheet">
<!-- The content you want to lock goes in here -->
<div class="locker-content">
<h3>The Complete CSS Cheat Sheet (PDF)</h3>
<p>Every selector, property, and shorthand on two printable pages. Keep it next to your keyboard and stop googling flexbox.</p>
<a class="download-button" href="css-cheat-sheet.pdf" download>Download the PDF</a>
</div>
<!-- The overlay visitors see while the content is locked -->
<div class="locker-overlay">
<svg class="locker-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z"/></svg>
<p class="locker-title">This content is locked</p>
<p class="locker-hint">Share this page on any network below to unlock the download instantly.</p>
<!-- Icons: Font Awesome Free 6 (fontawesome.com) - CC BY 4.0 -->
<div class="locker-share">
<a href="#" data-share="x" aria-label="Share on X">
<svg viewBox="0 0 512 512" aria-hidden="true"><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"/></svg>
</a>
<a href="#" data-share="facebook" aria-label="Share on Facebook">
<svg viewBox="0 0 320 512" aria-hidden="true"><path d="M80 299.3V512H196V299.3h86.5l18-97.8H196V166.9c0-51.7 20.3-71.5 72.7-71.5c16.3 0 29.4 .4 37 1.2V7.9C291.4 4 256.4 0 236.2 0C129.3 0 80 50.5 80 159.4v42.1H14v97.8H80z"/></svg>
</a>
<a href="#" data-share="linkedin" aria-label="Share on LinkedIn">
<svg viewBox="0 0 448 512" aria-hidden="true"><path d="M100.28 448H7.4V148.9h92.88zM53.79 108.1C24.09 108.1 0 83.5 0 53.8a53.79 53.79 0 0 1 107.58 0c0 29.7-24.1 54.3-53.79 54.3zM447.9 448h-92.68V302.4c0-34.7-.7-79.2-48.29-79.2-48.29 0-55.69 37.7-55.69 76.7V448h-92.78V148.9h89.08v40.8h1.3c12.4-23.5 42.69-48.3 87.88-48.3 94 0 111.28 61.9 111.28 142.3V448z"/></svg>
</a>
<a href="#" data-share="pinterest" aria-label="Share on Pinterest">
<svg viewBox="0 0 384 512" aria-hidden="true"><path d="M204 6.5C101.4 6.5 0 74.9 0 185.6 0 256 39.6 296 63.6 296c9.9 0 15.6-27.6 15.6-35.4 0-9.3-23.7-29.1-23.7-67.8 0-80.4 61.2-137.4 140.4-137.4 68.1 0 118.5 38.7 118.5 109.8 0 53.1-21.3 152.7-90.3 152.7-24.9 0-46.2-18-46.2-43.8 0-37.8 26.4-74.4 26.4-113.4 0-66.2-93.9-54.2-93.9 25.8 0 16.8 2.1 35.4 9.6 50.7-13.8 59.4-42 147.9-42 209.1 0 18.9 2.7 37.5 4.5 56.4 3.4 3.8 1.7 3.4 6.9 1.5 50.4-69 48.6-82.5 71.4-172.8 12.3 23.4 44.1 36 69.3 36 106.2 0 153.9-103.5 153.9-196.8C384 71.3 298.2 6.5 204 6.5z"/></svg>
</a>
<a href="#" data-share="reddit" aria-label="Share on Reddit">
<svg viewBox="0 0 512 512" aria-hidden="true"><path d="M373 138.6c-25.2 0-46.3-17.5-51.9-41l0 0c-30.6 4.3-54.2 30.7-54.2 62.4l0 .2c47.4 1.8 90.6 15.1 124.9 36.3c12.6-9.7 28.4-15.5 45.5-15.5c41.3 0 74.7 33.4 74.7 74.7c0 29.8-17.4 55.5-42.7 67.5c-2.4 86.8-97 156.6-213.2 156.6S45.5 410.1 43 323.4C17.6 311.5 0 285.7 0 255.7c0-41.3 33.4-74.7 74.7-74.7c17.2 0 33 5.8 45.7 15.6c34-21.1 76.8-34.4 123.7-36.4l0-.3c0-44.3 33.7-80.9 76.8-85.5C325.8 50.2 347.2 32 373 32c29.4 0 53.3 23.9 53.3 53.3s-23.9 53.3-53.3 53.3zM157.5 255.3c-20.9 0-38.9 20.8-40.2 47.9s17.1 38.1 38 38.1s36.6-9.8 37.8-36.9s-14.7-49.1-35.7-49.1zM395 303.1c-1.2-27.1-19.2-47.9-40.2-47.9s-36.9 22-35.7 49.1c1.2 27.1 16.9 36.9 37.8 36.9s39.3-11 38-38.1zm-60.1 70.8c1.5-3.6-1-7.7-4.9-8.1c-23-2.3-47.9-3.6-73.8-3.6s-50.8 1.3-73.8 3.6c-3.9 .4-6.4 4.5-4.9 8.1c12.9 30.8 43.3 52.4 78.7 52.4s65.8-21.6 78.7-52.4z"/></svg>
</a>
<a href="#" data-share="whatsapp" aria-label="Share on WhatsApp">
<svg viewBox="0 0 448 512" aria-hidden="true"><path d="M380.9 97.1C339 55.1 283.2 32 223.9 32c-122.4 0-222 99.6-222 222 0 39.1 10.2 77.3 29.6 111L0 480l117.7-30.9c32.4 17.7 68.9 27 106.1 27h.1c122.3 0 224.1-99.6 224.1-222 0-59.3-25.2-115-67.1-157zm-157 341.6c-33.2 0-65.7-8.9-94-25.7l-6.7-4-69.8 18.3L72 359.2l-4.4-7c-18.5-29.4-28.2-63.3-28.2-98.2 0-101.7 82.8-184.5 184.6-184.5 49.3 0 95.6 19.2 130.4 54.1 34.8 34.9 56.2 81.2 56.1 130.5 0 101.8-84.9 184.6-186.6 184.6zm101.2-138.2c-5.5-2.8-32.8-16.2-37.9-18-5.1-1.9-8.8-2.8-12.5 2.8-3.7 5.6-14.3 18-17.6 21.8-3.2 3.7-6.5 4.2-12 1.4-32.6-16.3-54-29.1-75.5-66-5.7-9.8 5.7-9.1 16.3-30.3 1.8-3.7.9-6.9-.5-9.7-1.4-2.8-12.5-30.1-17.1-41.2-4.5-10.8-9.1-9.3-12.5-9.5-3.2-.2-6.9-.2-10.6-.2-3.7 0-9.7 1.4-14.8 6.9-5.1 5.6-19.4 19-19.4 46.3 0 27.3 19.9 53.7 22.6 57.4 2.8 3.7 39.1 59.7 94.8 83.8 35.2 15.2 49 16.5 66.6 13.9 10.7-1.6 32.8-13.4 37.4-26.4 4.6-13 4.6-24.1 3.2-26.4-1.3-2.5-5-3.9-10.5-6.6z"/></svg>
</a>
</div>
</div>
</div>
/* Demo page styling */
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background-color: #f1f5f9;
}
.locker-content h3 {
margin: 0 0 10px;
font-size: 22px;
color: #0f172a;
}
.locker-content p {
margin: 0 0 20px;
font-size: 15px;
line-height: 1.6;
color: #475569;
}
.download-button {
display: inline-block;
padding: 12px 22px;
font-weight: 700;
text-decoration: none;
color: #fff;
background-color: #3e7bd6;
border-radius: 8px;
}
.download-button:hover {
background-color: #3069c2;
}
/* The content locker component */
/* Every knob you might want to tweak lives in one place */
.locker {
--locker-radius: 12px;
--locker-blur: 8px;
--locker-speed: .4s;
--locker-accent: #3e7bd6;
--locker-overlay: linear-gradient(160deg, rgba(30, 41, 59, .92), rgba(15, 23, 42, .96));
--locker-button: 44px;
position: relative;
max-width: 520px;
border-radius: var(--locker-radius);
overflow: hidden;
box-shadow: 0 4px 24px rgba(15, 23, 42, .12);
}
/* The content being locked; the blur fades away smoothly on unlock */
.locker-content {
padding: 30px;
background-color: #fff;
transition: filter var(--locker-speed) ease;
}
/* Blur the content and block clicks and text selection while it is locked */
.locker:not(.unlocked) .locker-content {
filter: blur(var(--locker-blur));
pointer-events: none;
user-select: none;
}
/* The dark overlay that sits on top of the locked content */
.locker-overlay {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6px;
padding: 20px;
text-align: center;
color: #fff;
background: var(--locker-overlay);
transition: opacity var(--locker-speed) ease, visibility var(--locker-speed);
}
/* Fade the overlay away once the locker is unlocked */
.locker.unlocked .locker-overlay {
opacity: 0;
visibility: hidden;
}
.locker-icon {
width: 34px;
height: 34px;
fill: #94a3b8;
}
.locker-title {
margin: 4px 0 0;
font-size: 20px;
font-weight: 700;
}
.locker-hint {
margin: 0 0 10px;
font-size: 14px;
line-height: 1.5;
color: #cbd5e1;
}
/* The row of round share buttons; each button reads its own --brand color */
.locker-share {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
.locker-share a {
display: flex;
align-items: center;
justify-content: center;
width: var(--locker-button);
height: var(--locker-button);
border-radius: 50%;
background-color: var(--brand);
transition: transform .15s ease;
}
.locker-share a:hover,
.locker-share a:focus-visible {
transform: scale(1.12);
}
.locker-share svg {
width: 18px;
height: 18px;
fill: #fff;
}
/* The official brand color for each network */
[data-share=x] { --brand: #000000; }
[data-share=facebook] { --brand: #0866ff; }
[data-share=linkedin] { --brand: #0a66c2; }
[data-share=pinterest] { --brand: #e60023; }
[data-share=reddit] { --brand: #ff4500; }
[data-share=whatsapp] { --brand: #25d366; }
/* The email form used by the email signup variant */
.locker-form {
display: flex;
gap: 8px;
width: 100%;
max-width: 340px;
}
.locker-form input {
flex: 1;
min-width: 0;
padding: 10px 14px;
font-size: 14px;
color: #fff;
background-color: #1e293b;
border: 1px solid #475569;
border-radius: 6px;
}
.locker-form input::placeholder {
color: #94a3b8;
}
.locker-form button {
padding: 10px 18px;
font-size: 14px;
font-weight: 700;
color: #fff;
background-color: var(--locker-accent);
border: 0;
border-radius: 6px;
cursor: pointer;
}
.locker-form button:hover {
filter: brightness(.9);
}
/* Keep things calm for visitors who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
.locker-content, .locker-overlay, .locker-share a {
transition: none;
}
}
// The share dialog URL for every supported network; {url} becomes the page's address
const networks = {
x: 'https://x.com/intent/post?url={url}',
facebook: 'https://www.facebook.com/sharer/sharer.php?u={url}',
linkedin: 'https://www.linkedin.com/sharing/share-offsite/?url={url}',
pinterest: 'https://pinterest.com/pin/create/button/?url={url}',
reddit: 'https://www.reddit.com/submit?url={url}',
whatsapp: 'https://wa.me/?text={url}'
};
// Read or save an unlock flag; storage can be blocked in private or embedded pages
const remember = (key, value) => {
try { return value ? localStorage.setItem(key, value) : localStorage.getItem(key); } catch (e) { return null; }
};
// Reveal the content and remember the unlock so it stays open on return visits
const unlock = locker => {
locker.classList.add('unlocked');
locker.querySelector('.locker-content').inert = false;
remember('locker_' + locker.dataset.locker, 'unlocked');
};
// Set up every locker on the page
document.querySelectorAll('.locker').forEach(locker => {
// Keep clicks and keyboard focus out of the content while it is locked
locker.querySelector('.locker-content').inert = true;
// Unlocked on a previous visit? Reveal it immediately and skip the rest
if (remember('locker_' + locker.dataset.locker)) return unlock(locker);
// Unlock by sharing: one click handler per share button
locker.querySelectorAll('[data-share]').forEach(button => button.addEventListener('click', event => {
event.preventDefault();
// Build the share link for the clicked network with this page's URL filled in
const url = networks[button.dataset.share].replace('{url}', encodeURIComponent(location.href));
// Open the network's share dialog in a small centered popup window
const popup = window.open(url, 'share', 'popup,width=600,height=600,left=' + (screen.width - 600) / 2 + ',top=' + (screen.height - 600) / 2);
// Popup blocked? Fall back to a new tab and unlock after a short delay
if (!popup) { window.open(url, '_blank'); setTimeout(() => unlock(locker), 5000); return; }
// Watch the popup; once it closes, the share is done and we can unlock
const watcher = setInterval(() => {
if (popup.closed) { clearInterval(watcher); unlock(locker); }
}, 500);
}));
// Unlock by email: used by the email signup variant if the form exists
const form = locker.querySelector('.locker-form');
if (form) form.addEventListener('submit', event => {
event.preventDefault();
// Send the address to your newsletter system here, then reveal the content
unlock(locker);
});
});