Skip to content

Instantly share code, notes, and snippets.

@IceCreamYou
Last active February 2, 2026 19:39
Show Gist options
  • Select an option

  • Save IceCreamYou/4f085b180a1608b99cb2 to your computer and use it in GitHub Desktop.

Select an option

Save IceCreamYou/4f085b180a1608b99cb2 to your computer and use it in GitHub Desktop.
Blurs Google Calendar event names to make it easier to share screenshots of your availability.

Sometimes for scheduling purposes it would be nice to be able to take a screenshot of your calendar and send it to someone, but you may not want to show that someone the names of every event on your calendar. This code and bookmarklet solves that problem by blurring out event names on your calendar.

Here is the code:

var style = document.getElementById('--style') || document.createElement('style'), // <style> element holding blur/hide rules
    spans = document.querySelectorAll('[data-eventchip] span'); // This worked as of May 3, 2023 but it may change.

// Add the styles
style.id = '--style';
style.innerHTML = trustedTypes.createPolicy('forceInner', { createHTML: (t) => t }).createHTML(`
    .--blur { -webkit-filter: blur(4px); filter: blur(4px); }
    .rsvp-no-chip.--hide, .rsvp-no-bg.--hide { opacity: 0; }
`);
document.head.appendChild(style);

// Blur active event titles
for (var i = 0, l = spans.length; i < l; i++) {
    spans[i].classList.toggle('--blur');
}

Run it once (e.g. in the browser console) to blur, then run it again to un-blur.

And here is that code as a bookmarklet:

javascript:void%20function(){var%20a=document.getElementById(%22--style%22)||document.createElement(%22style%22),b=document.querySelectorAll(%22[data-eventchip]%20span%22);a.id=%22--style%22,a.innerHTML=trustedTypes.createPolicy(%22forceInner%22,{createHTML:a=%3Ea}).createHTML(`
%20%20%20%20.--blur%20{%20-webkit-filter:%20blur(4px);%20filter:%20blur(4px);%20}
%20%20%20%20.rsvp-no-chip.--hide,%20.rsvp-no-bg.--hide%20{%20opacity:%200;%20}
`),document.head.appendChild(a);for(var%20c=0,d=b.length;c%3Cd;c++)b[c].classList.toggle(%22--blur%22)}();

This page doesn't allow linking bookmarklets, so you'll need to add the bookmarklet manually.

@swbrattain
Copy link

@IceCreamYou
Copy link
Author

I just updated the original post with a fix.

@aurelijusrozenas
Copy link

aurelijusrozenas commented May 4, 2023

EDIT: haha, @IceCreamYou beat me to it :)

Updated @c-harding variant:

{
    escapeHTMLPolicy = trustedTypes.createPolicy("forceInner", {
        createHTML: (to_escape) => to_escape
    });
    let style;
    if ((style = document.getElementById('--style'))) style.remove();
    else {
        style = document.createElement('style'); // <style> element holding blur/hide rules

        // Add the styles
        style.id = '--style';
        style.innerHTML = escapeHTMLPolicy.createHTML(`
            [data-eventchip]::after {
                content: attr(data-time) !important;
                position: absolute;
                z-index: 2;
                color: black;
                left: 4px;
                font-size: 11px;
                text-shadow: 0 0 3px white;
            }
            [data-eventchip] div {
                -webkit-filter: blur(4px);
                filter: blur(4px);
            }
        `);
        document.head.appendChild(style);
    }
    [...document.querySelectorAll('[data-eventchip]')].forEach(chip => {
        chip.dataset.time = (chip.textContent.match(/\d\d?:\d\d  \d\d?:\d\d/) ?? chip.textContent.match(/\d\d?:\d\d?/))?.[0]??''
    })
}
javascript:(function()%7B%7Blet%20escapeHTMLPolicy%20%3D%20trustedTypes.createPolicy(%22forceInner%22%2C%20%7BcreateHTML%3A%20(to_escape)%20%3D%3E%20to_escape%7D)%3Blet%20style%3Bif%20((style%20%3D%20document.getElementById('--style')))%20%7Bstyle.remove()%3B%7D%20else%20%7Bstyle%20%3D%20document.createElement('style')%3Bstyle.id%20%3D%20'--style'%3Bstyle.innerHTML%20%3D%20escapeHTMLPolicy.createHTML(%60%5Bdata-eventchip%5D%3A%3Aafter%20%7Bcontent%3A%20attr(data-time)%20!important%3Bposition%3A%20absolute%3Bz-index%3A%202%3Bcolor%3A%20black%3Bleft%3A%204px%3Bfont-size%3A%2011px%3Btext-shadow%3A%200%200%203px%20white%3B%7D%5Bdata-eventchip%5D%20div%20%7B-webkit-filter%3A%20blur(4px)%3Bfilter%3A%20blur(4px)%3B%7D%60)%3Bdocument.head.appendChild(style)%3B%7D%5B...document.querySelectorAll('%5Bdata-eventchip%5D')%5D.forEach(chip%20%3D%3E%20%7Bchip.dataset.time%20%3D%20(chip.textContent.match(%2F%5Cd%5Cd%3F%3A%5Cd%5Cd%20%E2%80%93%20%5Cd%5Cd%3F%3A%5Cd%5Cd%2F)%20%3F%3F%20chip.textContent.match(%2F%5Cd%5Cd%3F%3A%5Cd%5Cd%3F%2F))%3F.%5B0%5D%20%3F%3F%20''%7D)%7D%7D)()

@CM217217
Copy link

CM217217 commented Jan 5, 2024

I stumbled across this but am not familiar with or comfortable using this method. However, I did stumble across a Chrome Extension called Obfuscate-calendar that does exactly this. Just thought I would share in case others that are not comfortable with this method also stumble across this page.

@estevecastells
Copy link

I just saw this thread but I essentially built this over the weekend as a Chrome extension too. I used it starting a bookmarklet a friend did and made it as an extension to help a non-technical friend who used it as a bookmarktlet and due to changing CSS classes kept breaking.

Hope it can help someone maybe: https://chromewebstore.google.com/detail/google-calendar-event-blu/bdpgjkaeeamhppnplcomkdalokmnnicj

@c-harding
Copy link

I’ve just updated mine above: innerText rather than innerHTML works fine

// These selectors were recorded on 2023-02-03 and may change.
{
    let style;
    if ((style = document.getElementById('--style'))) style.remove();
    else {
        style = document.createElement('style'); // <style> element holding blur/hide rules
    
        // Add the styles
        style.id = '--style';
        style.innerText = `
            [data-eventchip]::after {
                content: attr(data-time) !important;
                position: absolute;
                z-index: 2;
                color: black;
                left: 4px;
                font-size: 11px;
                text-shadow: 0 0 3px white;
            }
            [data-eventchip] div {
                -webkit-filter: blur(4px);
                filter: blur(4px);
            }
        `;
        document.head.appendChild(style);
    }
    [...document.querySelectorAll('[data-eventchip]')].forEach(chip => {
        chip.dataset.time = (chip.textContent.match(/\d\d?:\d\d  \d\d?:\d\d/) ?? chip.textContent.match(/\d\d?:\d\d?/))?.[0]??''
    })
}
javascript:(function(){let style;if((style=document.getElementById('--style')))style.remove();else{style=document.createElement('style');style.id='--style';style.innerText='[data-eventchip]::after{content:attr(data-time)!important;position:absolute;z-index:2;left:4px;font-size:11px;text-shadow:0 0 3px white;}[data-eventchip] div{-webkit-filter:blur(4px);filter:blur(4px)}';document.head.appendChild(style);}const timeRegex=/^\d\d?:\d\d(  \d\d?:\d\d)?/;[...document.querySelectorAll('[data-eventchip]')].forEach(chip=>chip.dataset.time=(chip.textContent.match(/\d\d?:\d\d  \d\d?:\d\d/)??chip.textContent.match(/\d\d?:\d\d?/))?.[0]??'')})()

@nahu02
Copy link

nahu02 commented Feb 2, 2026

Hey,

the last solution by @c-harding didn't work perfectly for me - it would randomly leave only some timestamps visible in place of blurred text for some (but not all) events.
[Edit: Looking at the code once more, it's probably because I use a 12 hour clock, and \d\d?:\d\d doesn't match eg. 11am ]

Relying on you guys' work and like 10 minutes of vibecoding "I" turned this into a tampermonkey userscript.
Note that like @IceCreamYou 's version, it hides the event texts completely and doesn't show any timestamp text.

If you use a userscript manager you may find it useful.
https://gist.github.com/nahu02/5219705c84ab29a9928dbf3b1b0e6b3f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment