A bookmarklet is a bookmarked link (so in the bookmarks bar of your browser) which runs Javascript on the page you're viewing to change the page's functionality in some way.

Bookmarklets are really easy to create: they're simply a normal link element `<a>` with the `javascript:` prefix in the href attribute:

<a href="javascript:alert('Hello there');">Friendly bookmarklet</a>

Saving bookmarklets to use around the web is also simple: click and drag the link to the bookmark bar of your browser. When you click the bookmarked link, the Javascript will run on whichever page you're currently viewing. This makes bookmarklets very useful if you want to change sites you don't control: for instance, if you're reading a site which has low contrast text or very long lines, you could create a bookmarklet to automatically change the styles of the page to make it easier to read.

Creating a bookmarklet

Let's create a bookmarklet which changes the style of a page. This consists of a few steps:

  1. Write some CSS which will improve the page's style;
  2. Create a style tag in Javascript and add our CSS to that element;
  3. Inject our improved styles into the page.

Step 1: CSS

Open the page you want to change, and inspect the elements to update (right-click > inspect element). Play around in the developer tools to find styles which look right, then create a CSS file with the changes you want. Our example CSS:

/* this'll look great */
h1 {
    color: red;
}

p {
    line-height: 2em;
    font-size: 18px;
}

.main {
    max-width: 800px;
}

Step 2: Creating elements

The next step is to create a style element and populate it with our CSS. Creating an element is straightforward:

var style = document.createElement('style');

We'll then need to add our CSS into the new element. Having line-breaks in the CSS could cause issues in some browsers, so remove all the line-breaks from the CSS:

h1{color: red;}p{line-height: 2em;font-size: 18px;}.main{max-width: 800px;}

then add that string to the innerText of the style element:

style.innerText = 'h1{color: red;}p{line-height: 2em;font-size: 18px;}.main{max-width: 800px;}';

Step 3: Injecting into the page

The final step is getting our improved styles into the page. Essentially all we need to do is add our style element at the end of the <head> element, and our new styles will override the page's exisitng styles. (Obviously, the usual CSS rules apply here - if someone's added `!important` everywhere in their CSS, or have nested selectors to the nth-degree, then your style won't affect the page and you'll have a lot of tweaking to do!)

// find the <head> element
// getElementsByTagName returns an array-like structure, so access the 
// first element - [0] - to get a reference to the actual head tag
var head = document.getElementsByTagName('head')[0];

// 'style' is the variable we set earlier which holds the new <style> tag with our CSS
head.appendChild(style);

Putting it all together

Now we have our Javascript snippet, all we need to do now is to add it to a link:

<a href="javascript:var style=document.createElement('style');style.innerText='h1{color: red;}p{line-height: 2em;font-size: 18px;}.main{max-width: 800px;}';var head=document.getElementsByTagName('head')[0];head.appendChild(style);">Change all the styles!</a>

Try dragging the link to your bookmark bar and see what it does: Change all the styles!

Problems

Bookmarklets are fun, but don't run someone else's bookmarklet without checking what it does first. The method we're using, where Javascript injects elements into a page, is also used to attack sites: this is known as [Cross-Site Scripting](https://www.owasp.org/index.php/Cross-site_scripting) (or XSS). Since we created our bookmarklet we know what it does is harmless, but snippets copied from around the web may not be. Cross-site scripting attacks usually use the same method but inject Javascript into the page, which can then run as if the site's creator added it. This matters since Javascript can access cookies on sites - i.e. all your logins. If you ran a dodgy bookmarklet while you were on Twitter, then the script could potentially post tweets under your account.

For instance, this bookmarklet logs the content of all the current site's cookies to the console, which demonstrates that Javascript we've added to the page can act as if the site had included it:

<a href="javascript:var script=document.createElement('script');script.innerHTML='console.log(document.cookie);';var head=document.getElementsByTagName('head')[0];head.appendChild(script);">Log cookie</a>

Log cookie

Obviously, this is a massive over-simplification of XSS attacks, and when using bookmarklets you have to run the link yourself which is not the ideal way of getting access to sites since you may never use the bookmarklet on the correct site. However, you should be aware of this if you've found a bookmarklet on another site - just check what the code's doing before you run it.