Markdown with HiDPI/Retina images

1.2k Views Asked by At

How can I display images on a HiDPI display using HTML produced from Markdown such that the images are shown in high resolution. Normally, I'd create <img> tags with srcset attributes or set the width and height on each image appropriately or use media queries. However, the result of Markdown images only allow for an alt attribute. Specifically, I'm using the marked library (I have no control over this).

I do have complete control over the CSS. Is there a way, in CSS, to at least make all images 1/3rd the logical pixels wide than they have physical pixels in width? That way I could require all images referenced in Markdown to be 3x. Is it as simple as this?

img {
  width: 33.33%;
}

Much better would be some way to have the browser download a different image depending on the devicePixelRatio of the device.

Using HTML is not an option. marked is used with the sanitize flag to escape any HTML. I'm hoping there's a CSS solution or some other clever mechanism.

4

There are 4 best solutions below

0
On

One way I've been able to work with HiDPI images coming out of Markdown is utilizing the title attribute. Image titles can be semantically meaningful and provide information to CSS to effectively size images using attribute selectors.

As an example, I can create a Markdown image like this:

![](http://images.ucode.com/logo_1200.png "Important example")

Then I can use an attribute selector to set the width from 1200px down to 400px, making it very crisp for devices with a devicePixelRatio of 3:

img[title~="important" i][title~="example" i] {
  width: 400px;
}

That says for all important examples to have a logical width of 400 pixels. If I feed it a 1200 pixel image, standard DPI devices will have a slower image download, but will otherwise be fine.

Ideally, there's a solution that I could feed multiple images for different devicePixelRatios. However, this is at least good enough for now.

2
On

To accomplish this via Markdown, simply use raw HTML. The rules state (bold added):

Markdown is not a replacement for HTML, or even close to it. Its syntax is very small, corresponding only to a very small subset of HTML tags. The idea is not to create a syntax that makes it easier to insert HTML tags. In my opinion, HTML tags are already easy to insert. The idea for Markdown is to make it easy to read, write, and edit prose. HTML is a publishing format; Markdown is a writing format. Thus, Markdown’s formatting syntax only addresses issues that can be conveyed in plain text.

For any markup that is not covered by Markdown’s syntax, you simply use HTML itself. There’s no need to preface it or delimit it to indicate that you’re switching from Markdown to HTML; you just use the tags.

Therefore, use <img> tags with srcset attributes and/or width and height just as you would in HTML. Markdown will pass them through as-is.

1
On

You can consider the device width and the device pixel ratio. So we can address this problem.

/* Large Monitors devices (large desktops, 1920px and up)*/
@media only screen and (max-width: 1920px) {

  .logo {
    width: 160px;
    height: 109px;
    background-image: url("/img/1920px/logo/logo-1x.png");
  }

  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and (     -o-min-device-pixel-ratio: 2/1),
  only screen and (        min-device-pixel-ratio: 2),
  only screen and (                min-resolution: 192dpi),
  only screen and (                min-resolution: 2dppx) {

    .logo {
      width: 160px;
      height: 109px;
      background-image: url("/img/1920px/logo/logo-2x.png");
    }

  }

}

/* Extra large devic
es (large desktops, 1280px and up)*/
@media only screen and (max-width: 1280px) {

  .logo {
    width: 120px;
    height: 82px;
    background-image: url("/img/1280px/logo/logo-1x.png");
  }

  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and (     -o-min-device-pixel-ratio: 2/1),
  only screen and (        min-device-pixel-ratio: 2),
  only screen and (                min-resolution: 192dpi),
  only screen and (                min-resolution: 2dppx) {

    .logo{
      width: 160px;
      height: 109px;
      background-image: url("/img/1280px/logo/logo-2x.png");
    }

  }
}

/* Large devices (desktops, 960px and up)*/
@media only screen and (max-width: 960px) {

  .logo{
    width: 100px;
    height: 68px;
    background-image: url("/img/960px/logo/logo-1x.png");
  }

  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and (     -o-min-device-pixel-ratio: 2/1),
  only screen and (        min-device-pixel-ratio: 2),
  only screen and (                min-resolution: 192dpi),
  only screen and (                min-resolution: 2dppx) {

    .logo{
      width: 160px;
      height: 109px;
      background-image: url("/img/960px/logo/logo-2x.png");
    }

  }

}

/* Medium devices (tablets, 640px and up)*/
@media only screen and (max-width: 640px) {

  .logo{
    width: 78px;
    height: 42px;
    background-image: url("/img/640px/logo/logo-1x.png");
  }

  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and (     -o-min-device-pixel-ratio: 2/1),
  only screen and (        min-device-pixel-ratio: 2),
  only screen and (                min-resolution: 192dpi),
  only screen and (                min-resolution: 2dppx) {

    .logo{
      width: 160px;
      height: 109px;
      background-image: url("/img/640px/logo/logo-2x.png");
    }

  }
}


/* Small devices (landscape phones, 320px and up)*/
@media only screen and (max-width: 320px) {

  .logo{
    width: 78px;
    height: 42px;
    background-image: url("/img/320px/logo/logo-1x.png");
  }

  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and (     -o-min-device-pixel-ratio: 2/1),
  only screen and (        min-device-pixel-ratio: 2),
  only screen and (                min-resolution: 192dpi),
  only screen and (                min-resolution: 2dppx) {

    .logo{
      width: 160px;
      height: 109px;
      background-image: url("/img/320px/logo/logo-2x.png");
    }

  }
}
0
On

Some platforms allow scaling of images specified in percentages.

Before: ![image|512x128](file.png)

After: ![image|512x128, 50%](file.png)

In addition, you can see other syntax examples here and here. But what works varies depending on the platform's Markdown implementation.