I happened across a great Chrome extension a year or so back, called Hide YouTube Comments, which does what it says very well. The YouTube comments section has always been full of vitriol spewed by mostly anonymous users, and apparently Google has no plans to clean it up, so... I chose to hide them.

Then more recently I stumbled across an even better one called DF YouTube (Distraction Free), which lets you choose to hide a lot more than just the comments. You can hide suggested videos, trending videos, and a lot of other elements that make up the YouTube experience.

Seeing that gave me an idea - why not do this for other sites? A lot of sites load extra content along the top and in sidebars, whose purpose is to keep you on the site longer and engaged more. It's trivial to hide, say, the trends panel in Twitter, but there's is absolutely zero impetus for them to add that option.

I don't need the distractions though, so I wrote Twitter Distraction Remover. Or if you'd just like to check out the code, it's available on GitHub.

Lessons Learned

This was a pretty interesting problem to solve, and it took me a few tries to get something I liked. I'm still not sure it's the best way to do it but it's working okay so far.

1. If you want to use 'sync' storage, group data together

My "options" page originally saved each checkbox click individually, which is fine for local storage since there's no limitation other than a 5 MB cap. On the other hand, sync storage has many limitations on how much and how often data can be saved. I ended up changing my code to save settings as an array of IDs (each one assigned to an individual checkbox), to take advantage of sync storage without hitting the limits.

var optionIds = ['hide_moments','hide_notifications','hide_messages',

function loadOptions() {
    chrome.storage.sync.get('options', function(result) {
        if (result != undefined && result.options != undefined) {
            result.options.forEach(function(id) {
                document.getElementById(id).checked = true;

function saveOptions() {
    var options = [];
    optionIds.forEach(function(id) {
        if (document.getElementById(id).checked) {
    chrome.storage.sync.set({'options': options});

2. Build up your selector before modifying the DOM

Every web page is represented behind-the-scenes by a document object model, or DOM, which you can parse and change, delete from or add to. You can find the elements you're interested in changing by figuring out which css selectors represent them, and then manipulate them.

My first attempt was to traverse the DOM once for each selector I wanted to hide. For example, the "Notifications" link is assigned a "notifications" class, so I'd look for that and hide it. Then I'd move on to the next element. That resulted in over a dozen updates to the page, which is suboptimal. I ended up building the selector instead, so the number of times I traversed the DOM was kept to a minimum.

3. Show all and hide some, or hide all and show some?

I figured I could just let the page load and then hide everything the user didn't want to see. The problem is that, even though the process was fairly quick, it was never quick enough to avoid some choppiness. The elements showed up for a moment before disappearing. It was annoying.

I ended up applying a stylesheet via content script, which hides everything by default. Then I show those things that the user hasn't selected to be hidden. This might cause the page to appear to be loading elements a second longer than normal, but it's a better experience than the other way around.


I can already see one interesting effect of reducing the clutter.

By selecting "Others' Tweet Activity" in the options, you won't see comments, likes, or retweets anymore. I didn't realize before just how much I used those indicators to decide what was funny / interesting / worth retweeting. Without them, I can finally judge content on its own merit. It's like watching a sitcom without the laugh track - you suddenly realize just how uninteresting most of them are.