Profile picture

GustavBylund

+46 (0)73 026 26 86hello@gustavbylund.semaistho

A nicer reading experience on imgur albums

I often read comics on imgur, but it’s not the greatest experience. By default imgur albums doesn’t load the full quality images, but displays a lower quality placeholder until you click on the image to expand. Makes a lot of sense for imgur in order to reduce bandwidth, but makes no sense for me when I’m trying to read blurred text. Imgur also displays the images in a maximum width of slightly over 700px unless you click on them, which is not enough for even a 1080p portrait monitor, let alone 1440p or 4K.

This is a bookmarklet that makes reading comics on imgur a lot nicer by displaying the full quality image and expanding it to fill 100% of the screen width.

Word of warning, the comics linked below are about child abuse and are really depressing. They are also really good.

Before:

screenshot of comic before using bookmarklet Look at all this wasted space on the right side! 😠

After:

screenshot of comic after using bookmarklet This is much nicer. The text is actually readable!

You can try it out for yourself on the Clarissa Comics

Update 2 - Not everything should be a bookmarklet

It’s sometimes just easier if it’s not a bookmarklet. Check out /imgur-reader instead.

Update 1 - Updated Bookmarklet v2

I found a way to make the bookmarklet a lot simpler and to work better in general. See below for an explanation.

Drag the following link to your bookmark bar!

Imgur album

Or add this code to a bookmark:

javascript:document.write(_widgetFactory._.config.gallery.image.album_images.map(e=>`<img src="https://i.imgur.com/${e.hash}${e.ext}">`).join("\n"));const style=document.createElement("style");style.type="text/css",style.innerHTML=`
  html, body {
    margin: 0;
    padding: 0;
    background: #141518;
  }
  img {
    display: block;
    margin: 0 auto;
    max-width: 100%;
  }
  `,document.head.appendChild(style);

How it works - updated

I found out that imgur stores the metadata for all of their images in a _widgetFactory object on window. This makes finding the URLs to the images a lot simpler, since I don’t have to parse any HTML.

I also updated the bookmarklet to completely replace the entire document so that none of the previous dynamic adding of images on scroll will muck anything up.

document.write(
  _widgetFactory._.config.gallery.image.album_images
    .map(i => `<img src="https://i.imgur.com/${i.hash}${i.ext}">`)
    .join('\n'),
)

const style = document.createElement('style')
style.type = 'text/css'
style.innerHTML = `
  html, body {
    margin: 0;
    padding: 0;
    background: #141518;
  }
  img {
    display: block;
    margin: 0 auto;
    max-width: 100%;
  }
  `
document.head.appendChild(style)

How it works - old version

Imgur serves all of their compressed low quality images with a g on the end, so the following snippet of code can be used to replace the low quality src with the original:

image.src = image.src.replace(/g\.(jpe?g|png)$/, '.$1')

Imgur also serves gifs, but they are never compressed or shrunk so far as I could tell.

The rest of the code is used to find out when new images are added to the page, since imgur doesn’t load all of the images into DOM at once. It also adds some styling that expands the images to fill the width of the screen if the image is big enough.

const selector = 'img.post-image-placeholder'

const style = document.createElement('style')
style.type = 'text/css'
style.innerHTML = `
  #inside {
    width: 100% !important;
    margin: 0 auto !important;
    padding: 0 !important;
  }
  #right-content {
    display: none !important;
  }
  .post-header {
    position: static !important;
    margin: 0 auto !important;
  }
  .left.post-pad {
    width: 100% !important;
  }
  .post-container {
    width: 100% !important;
  }
  .post-image-placeholder {
    position: static !important;
    width: unset !important;
    height: unset !important;
    max-width: 100% !important;
    max-height: unset !important;
    opacity: 1 !important;
  }
  .post-image-placeholder + img {
    display: none;
  }
`
document.head.appendChild(style)

const loadOriginal = image => {
  if (!image.src) {
    return
  }
  image.src = image.src.replace(/g\.(jpe?g|png)$/, '.$1')
}

Array.from(document.querySelectorAll(selector)).forEach(loadOriginal)

const targetNode = document.querySelector(`.post-images>div`)

const config = {
  childList: true,
}

const callback = events => {
  events.forEach(event => {
    Array.from(event.addedNodes).forEach(node => {
      if (!node.classList.contains('post-image-container')) {
        return
      }
      const image = node.querySelector('.post-image-placeholder')
      loadOriginal(image)
    })
  })
}

const observer = new MutationObserver(callback)

if (window.imgurAlbumViewer) {
  window.imgurAlbumViewer.disconnect()
}

observer.observe(targetNode, config)

window.imgurAlbumViewer = observer