CSS Bookmarklets for Testing and Fixing

I regularly have to test sites in development, review some third-party site, or just use a site in my day-to-day time wasting (and banking) rituals. I’ve relied on viewing the page’s source or popping into my browser’s dev tools to find a missing element, copy un-transformed text, check for inline styles, and so on. Typically I am relying on CSS and not JavaScript, as that is where I excel.

I got a little annoyed doing that all the time, and this morning I had reason to visit Pinterest and mostly lost my marbles at its login overlay and refusal to scroll. So I channeled that rage and taught myself to build a bookmarklet to dump that Pinterest overlay crap. I have created a few more that include my standard styles for testing, styles that perhaps you (dear reader) will find useful.

I’ll have basic instructions below showing you how you can build your own and/or modify the ones I’ve provided.

Note your browser’s Content Security Policy may prevent the script in a bookmarklet from modifying a page, in which case you can run it in the browser console. In Firefox use Ctrl + Shift + K, In Chrome use Ctrl + Shift + J.

Bookmarklets You May Steal

Note that I say may steal. That’s me giving you permission. Note that I call them bookmarklets. That’s me not giving into the term favelets or whatever HotJava called them (was it hot links?).

Restore Link Underlines

You know what’s cool? Removing link underlines and providing terrible link color contrast. It’s so cool, in fact, that I want to make those sites less cool. As well as usable. Read my rant on this.

This bookmarklet restores link underlines across the board. Every link. After all, if you want the link underlines, you probably don’t care that the designer would freak out at the noise it adds to the page.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('a[href]{text-decoration:underline !important}',0);})()

Restore Focus Outlines (or Fix Virgin America)

Just as cool as removing link underlines is removing the outline on elements that get focus as you tab through a page. After all, if you’ve hidden the links, why not hide when the links are selected. Virgin America tends to agree.

This bookmarklet not only restores the outline (in the form of the two-pixel dotted blue line), but also adds a drop shadow for those cases where the blue is lost against the surrounding colors.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('*:focus{outline:2px dotted #00f !important;box-shadow: 0 0 2em rgba(0,0,0,.75) !important;}',0);})()

Find Inline Styles

Over at Algonquin Studios we have worked in the content management space for, well, since the dawn of content management systems. One of the risks of using a CMS is that your authors may accidentally (or intentionally) embed styles whether by pasting rich-text from elsewhere or by features built into the WYSIWYG editor within the tool. This is most common with text styles.

Sometimes it is faster to just find the elements that have a style attribute on them, as that’s the first clue that there may be a conflict that needs to be corrected. This option will find any of those elements and give them a yellow background along with a two-pixel dotted red border (like the Windows “hot dog” theme from the previous century).

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('*[style]{border:2px dotted #f00 !important;background-color:#ff0 !important;}',0);})()

Find Duplicate ARIA Roles

In ARIA, there are a few instances of roles that should only appear once on a page. These landmark roles are banner, contentinfo, and main. In addition, the W3C HTML5.1 specification notes that there must be only one main element per page.

This bookmarklet will identify any additional instances of any of the once-per-page items above. If you know enough about coding ARIA, then you probably know enough about finding which of the roles/elements is on repeat. Offending items will have a two-pixel dotted red border and red background.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('*[role=main]:nth-of-type(n+2),*[role=banner]:nth-of-type(n+2),*[role=contentinfo]:nth-of-type(n+2),main:nth-of-type(n+2){border:2px dotted #f00 !important;background-color:#f00;}',0);})()

Find Missing Alt Attributes

An image without an alt attribute can be anything from an annoyance to a barrier to those using assistive technologies. Being able to quickly identify those images on a page can save time when figuring where to focus your efforts.

This bookmarklet will find those images and give them a two-pixel dotted red border. Note that it only looks for images with a missing alt, as a blank alt attribute is often perfectly valid.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('img:not([alt]){border:2px dotted #f00 !important;background-color:#f00;}',0);})()

Fix Pinterest

When you visit Pinterest without a Pinterest account, or without being logged in, you are prompted to sign up/in by a terrible overlay. In addition, the page won’t scroll past a certain point. This annoys me. So I made a bookmarklet to remove the two overlays and re-enable scrolling. You can test it on my abandoned Pinterest page.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('.Modal, .UnauthBanner {display: none !important;}',0);b.insertRule('.hasFooter.Grid.Module{overflow-y:visible !important;}',0);b.insertRule('.noScroll{overflow:auto !important;}',0);})()

Reset Text Size (Added January 30)

Sadly, it is not uncommon for sites to reset the default size of the text on the page. Too often that is done to satisfy a design change. One site where I find the text too small to read comfortably, or at all, is Daring Fireball. I know I am not the only one to feel this way.

This bookmarklet will resize the text on the body element to 100%, ideally conforming to whatever your default browser preferences are. It works great on Daring Fireball, but could easily be overridden on sites that set the text size in other ways and/or on other elements.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('body{font-size:100% !important;}',0);})()

Find Empty Elements (Added May 6)

It is not uncommon for a WYSIWYG editor in a CMS or on a comment site to throw extra empty p elements into the content. While I once wrote a style into my development CSS to highlight these issues, I was reminded of the potential utility by a Happy Cog post on pseudo classes.

This bookmarklet will find elements that are empty — no content, no whitepsace. It will not highlight images (by excluding elements with a src attribute) nor form inputs (by excluding elements with a type element), two common self-terminating elements that will otherwise trigger this. It isn’t perfect, but you are welcome to make it your own.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('*:not([src]):not([type]):empty{border:2px dotted #00f !important;background-color:#00f;}',0);})()

Invert Page (Added August 17, updated Dec. 8, 2016)

I have a nifty app on my phone that allows me to turn the brightness down to barely visible. This is handy when reading at night. Even when very dark, sometimes the black text on white page is just too hard on my eyes.

This bookmarklet will invert the entire page (like looking at a negative of a film photo). It then goes through and unverts (I just made up a word) all img and video elements. It won’t work on background images, which also makes this a handy testing tool. Also, since pages that exclude a background color don’t invert properly for me in Chrome, and since checking for a null value is nigh impossible, I just force the background to nearly black (which means it satisfies my goal of painless reading at night). Note, the latest update also removes any background color from the html element. You can just chop the document.body.style.backgroundColor='#111'; off the end if you don’t want it.

javascript:(function () { var css = 'html {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); } img {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); } video {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); } html { background-color: transparent; }'; var head = document.getElementsByTagName('head')[0]; var style = document.createElement('style'); if (!window.counter) { window.counter = 1; } else { window.counter++; if (window.counter % 2 == 0) { var css = 'html{-webkit-filter:invert(0%);-moz-filter:invert(0%);-o-filter:invert(0%);-ms-filter:invert(0%);}img{-webkit-filter:invert(0%);-moz-filter:invert(0%);-o-filter:invert(0%);-ms-filter:invert(0%);}video{-webkit-filter:invert(0%);-moz-filter:invert(0%);-o-filter:invert(0%);-ms-filter:invert(0%);}html{background-color:transparent;}' } } style.type = 'text/css'; if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); document.body.style.backgroundColor='#111'; }());

Remove Twitter Moments (Added December 15)

People really don’t like Twitter Moments. I don’t think we need to remove it, but I understand lots of people find it hugely distracting. All this does is hide the option in the menu bar. It will also fail when Twitter updates its code again in n weeks.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('li.moments{display: none;}',0);})()

I made a request at Stack Overflow to put underlines on links so they more visible (especially since they don’t have enough contrast with the surrounding text). While it gets debated and (based on feedback) probably ignored, I made a bookmarklet to restore links where I need them.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('.post-text a:link, .post-text a:visited, .comment-copy a:link, .comment-copy a:visited{text-decoration:underline !important}',0);})()

Show Twitter Image Alt Text (Added January 3, 2017)

During an A11yNYC event tonight discussing alternative text for images, somebody asked how to see any alternative text applied to images on Twitter. The answer is use a screen reader or your browser’s inspector, but that seems unfortunate. So I made a bookmarklet to display a Twitter image’s alt text on top of the image. This is quick and dirty. The tweets must be loaded, it does not work on tweets with more than one image, it has not been thoroughly tested, and is not ideal code. But it is a start. Corrections / improvements welcome.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('a[href]{text-decoration:underline !important}',0);b.insertRule('div.alt{position:absolute;top:0;bottom:0;right:0;left:0;width:100%;z-index:999999;background-color:rgba(0,0,0,.75);color:#fff;box-sizing:border-box;padding:1em 2em;font-size:calc(1em + .25vw)}',0);var imgContainers=document.querySelectorAll('.AdaptiveMedia > div > div > div');for(i=0;i<imgContainers.length;i++){var imgs=imgContainers[i].getElementsByTagName('img');for(j=0;j<imgs.length;j++){var altDiv=document.createElement('div');altDiv.className='alt',imgAlts=imgs[j].getAttribute('alt'),altDiv.innerText=imgAlts,imgs[j].parentNode.insertBefore(altDiv,imgs[j].nextSibling)}}})();

Fix LinkedIn Profile (Added August 15, 2017)

Sometimes I go to Google to look up a name, and often the search results bring me to LinkedIn. The problem is that LinkedIn throws a stupid sign-up modal in front of the content and turns off all scrolling. This is easy enough to fix with the browser’s inspector, or just a quickie bookmarklet.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('#advocate-modal{display:none !important;}',0);b.insertRule('body.advocate-modal-visible,body{overflow:auto !important;}',0);})();

Focus Interactive Controls (Added July 11, 2018)

Keyboard testing involves hitting the Tab a lot. Sometimes you want to see the focus styles, sometimes you want to see the order of the page, or see what is hidden, or hear how a screen reader announces controls. This bookmarklet will loop through every interactive control on the page, sitting on each one for one second. Also, once you start it, you cannot stop it. You can adjust the timing (to give a screen reader more time to announce each one) and you can adjust the CSS selector in the document.querySelectorAll (to maybe pull only interactive controls that are within <main>, for example). Or steal Scott O’Hara’s.

javascript:(function(){try{for(var e=document.querySelectorAll("a[href], area[href], input:not([disabled]), button:not([disabled]), select:not([disabled]), textarea:not([disabled]), iframe, object, embed, summary, [tabindex]:not([tabindex='-1']), [contenteditable=true], video[controls], audio[controls]"),t=0;t<e.length;t++)!function(t){setTimeout(function(){e[t].focus()},1000*t)}(t)}catch(e){console.log('getInteractives(): '+e)}})()

Reading Order (Added April 13, 2019)

I wrote up a whole thing in a detailed post, so go there to copy the script: Reading Order Bookmarklet

Show Tweet Image Alt Text (Added August 23, 2019; updated December 29, 2020)

There is still no easy way to see the alt text for an image in a tweet. Twitter’s developers eschewed the best practices of id attributes or reasonable structure, which made creating simple styles a bit tricky. So this isn’t perfect, but yeah. In the meantime, read how to improve your tweet accessibility.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('a[role=link] div[aria-label]::after,div[aria-label][data-testid=previewInterstitial]::after{content:attr(aria-label);display:block;background-color:rgba(0,0,0,.8);color:#ff0;font-family:\'Segoe UI\',-apple-system,BlinkMacSystemFont,Roboto,Oxygen-Sans,Ubuntu,Cantarell,\'Helvetica Neue\',sans-serif;padding:1em;position:absolute;top:0;left:0;right:0;z-index:1}',0);b.insertRule('[dir=auto]>svg{display:none}',0);b.insertRule('a[role=link] div[aria-label]{display:contents;margin-top:unset !important;margin-bottom:unset !important}',0);})();

Fix GitHub Tables (Added January 20, 2020)

If you create a table on GitHub, there is a style intended to make it fit into the page container by adding scrollbars. It uses display: block, and (as we know) that style strips table semantics in browsers making them useless for screen reader users. This bookmarklet undoes that style.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('.markdown-body table{display:table}',0);})()

Dismissable 44×44 Cursor (Added August 26, 2020)

I took Jarek Smith’s bookmarklet to show a 44 pixel square cursor and modified it to dismiss the cursor when you press Esc. Obviously there is some risk to using Esc, but I figure for testing it is fine, until it is not, and then you can customize it to a key or combination that works for you. A better solution is to destroy the CSS block entirely, but I have to go make dinner.

javascript:(function(){ var style = document.createElement('style'), styleContent = document.createTextNode('* { cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJBJREFUeNrs2dEKgDAIhWEN3/+VLYtBF12MppHwDxY0uvg4DJpORcSl0bB4uPcwq+oFHu8/956pbtJsAAYMGDBgwIABA044t3pMEgb8VU2XsWdn1o/aUUn4bchPBWNFYWvVidxbCFGmr7YULBs1YDPfsYcXEi9ryvDjAAwYMGDAgAED7nK8bHG7qNLs6nYXYAAheh5j8Qw5fwAAAABJRU5ErkJggg==) 22 22, auto !important}'); style.appendChild(styleContent ); var caput = document.getElementsByTagName('head'); caput[0].appendChild(style); document.onkeydown=function(e){var n;('key'in(e=e||window.event)?'Escape'==e.key||'Esc'==e.key:27==e.keyCode)&&(n=document.createElement('style'),document.head.appendChild(n),n.sheet.insertRule('*{cursor:revert !important}',0))}; })();

Unset Font Weights (Added January 28, 2022)

Many sites use a custom font. When that custom font is thicker, such as using a headline font for body text, the site owner may make it thinner by adjusting the font-weight. The problem is sometimes the font is broken, does not load, or the developer just has much better eyes, and the text ends up being far too narrow. This bookmarklet unsets all font-weight (though you may need to tweak it for some sites) except on <strong>, <b>, and <h1> through <h6>. If the font is too narrow at any weight, this bookmarklet will not address it.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('*:not(strong):not(b):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6){font-weight:unset !important}',0);})()

Re-enable Text Selection (Added March 25, 2022)

Some devs may use the CSS property user-select to prevent users from selecting text, either because they misunderstand the web in general or because they are trying to prevent draggable controls from also selecting. This bookmarklet will unset that rule for all elements.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('*{user-select:unset !important}',0);})()

Fix Twitter Homoglyphs (Added April 3, 2023)

It is trivially easy to impersonate someone else on Twitter, as its repeated Twitter Blue debacle has shown. Because nobody at Twitter enabled font-feature-settings: "ss01" for tweets (only handles), homoglyph attacks (where characters like l and I look the same) are still easy, and a paid blue check can compound confusion. This bookmarklet enables the settings to make characters easier to distinguish

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule('body * {font-variant-alternates: styleset(ss01) !important;}',0);b.insertRule('@font-feature-values TwitterChirp{@styleset { ss01: 1 }}',0);})()

Make/Modify Your Own Bookmarklet

The Virgin America site is made usable for those who navigate with a keyboard by restoring link underlines and adding focus styles to elements.

If you look at the code chunks above, you’ll see I am doing the same thing over and over. I am using the JavaScript CSSStyleSheet.insertRule() method to insert a new style rule into the page’s stylesheet. Not only does the Mozilla Developer Network have a great overview with sample code, but David Walsh shows similar code with some minor tweaks.

This approach allows me to leverage my CSS skills to write selectors to find and style elements on the page. Since CSS has so many powerful selectors, I find this easier to quickly repurpose. In addition to adding a new style, I always include !important with each so that it will override any inline styles.

If you are writing a function from scratch, make sure you minify it to take up less space (you may bump into character limits for a bookmarklet). Pre-pend javascript: and make it the href value of a link and you are done.

Here is a sample block of code you can use with the styles rendered in bold so you can replace them with your favorite selector. In this example I have two style rules so you can see how to add additional selectors.

javascript:(function(){var a=document.createElement('style'),b;document.head.appendChild(a);b=a.sheet;b.insertRule("a[href]{text-decoration:underline !important}",0);b.insertRule("*[style]{border:2px dotted #f00 !important;background-color:#f00;}",0);})()

And with that you should be off to the races.


Links to my posts referenced above:

Update: February 14, 2015

It’s hard to use bookmarklets on mobile devices, but I have a solution.

Update: March 4, 2016

I’ve been adding more into the article over the last year, but Ted Drake just posted one for showing aria-label values on a page. I felt it was worth linking.



Invert Page is cool. Possible don’t invert images when run this bookmarklet?

darkj2k; . Permalink
In response to darkj2k. Reply

I wrote the bookmarklet to not invert (or rather, re-invert) any img and video elements. It will still invert CSS background images. I chose not to un-invert background images because they are often used behind content, so inverted content would be illegible. Also, an entire page background image that is bright would still be too bright when reading in the dark.

aroselli; . Permalink

Hi, thanks for gathering all those bookmarklets :)

I made one by myself, based on a very large CSS file: https://github.com/ffoodd/a11y.css
It’s meant to warn developper about possible mistakes in HTML code thanks to CSS. It’s widely documented with a website (http://ffoodd.github.io/a11y.css/) to test and explain selectors, and a wiki (https://github.com/ffoodd/a11y.css/wiki) to explain the code itself.

Id’ love to have your opinion about this. And it’s still evolving, so feel free to open an issue :)

In response to Gaël Poupard. Reply

This looks pretty handy. It reminds me of Heydon Pickering’s Revenge.css (though his was not the first). I would have to play around with it a bit to get a sense of where it fits in my toolbox.

Leave a Comment or Response

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>