1.0.0 • Published 3 years ago

@plaiceholder/blurhash v1.0.0

Weekly downloads
11
License
Apache-2.0
Repository
github
Last release
3 years ago

Sponsors 🖤

Become a project sponsor to access premium features, including:

  1. Studio
    Upload your images and transform to beautifully lightweight placeholders (like magic, but real) ✨
  2. API
    (TBC, depending on sponsor interest)

Individuals

Support Plaiceholder and get access to premium features via plaiceholder.co. Your support will be greatly appreciated!

Organizations

Support Plaiceholder via your organization. Your logo will show up here and on plaiceholder.co with a link to your website.

See Pricing and T&Cs


Table of Contents

  1. Introduction
  2. Setup
  3. Plugins
    1. Next.js
  4. FAQs

Examples

Jump to the examples directory to see working demos for Next.js, 11ty and more...


Introduction

"Plaiceholder" is a collection of Node.js helpers for creating low quality image placeholders, with 4 approaches to choose from:

  1. CSS (recommended)
  2. SVG
  3. Base64
  4. Blurhash

Disclaimer: It's worth taking pros/cons of each approach with a grain of salt. Although initial tests locally and on WebPageTest have proved successful, extra research needs to be completed to determine the fastest solution.

Setup

CSS

Converts a specified image Buffer into a low-res placeholder, outputted as a set of linear-gradients (in the form of a JavaScript style object).

Pros: Fast DOMContentLoaded and LCP
Cons: ? (Still figuring out)

For a "blurred" effect, extend the returned styles with filter: blur(<value>) and transform: scale(<value>).

Installation

npm i @plaiceholder/css

Example

import fs from "fs";
import path from "path";
import { promisify } from "util";
import { getPixelsCSS } from "@plaiceholder/css";

const image = await promisify(fs.readFile)(
  path.join("path", "to", "your", "image.jpg")
);

const css = await getPixelsCSS(image);

console.log(css);

// Outputs
// {
//   backgroundImage: "…"
//   backgroundPosition: "…"
//   backgroundSize: "…"
//   backgroundRepeat: "…"
// }

SVG

Converts a specified image Buffer into a low-res placeholder, outputted as an SVG.

Pros: Fast DOMContentLoaded and LCP
Cons: ? (Still figuring out)

For a "blurred" effect, extend the returned SVG's styles with filter: blur(<value>) and transform: scale(<value>).

Although it returns the SVG in the format of React.createElement() arguments, you are not constrained to using React.js.

e.g. See the 11ty example.

Installation

npm i @plaiceholder/svg

Example

import fs from "fs";
import path from "path";
import { promisify } from "util";
import { getPixelsSVG } from "@plaiceholder/svg";

const image = await promisify(fs.readFile)(
  path.join("path", "to", "your", "image.jpg")
);

const svg = await getPixelsSVG(image);

console.log(svg);

// Outputs
// [
//   "svg",
//   { ...props }
//   [
//     [
//       "rect",
//       { ...childProps }
//     ],
//     ...etc
//   ]
// ]

Base64

Converts a specified image Buffer into a low-res image, encoded as Base64 string.

Pros: Fast DOMContentLoaded and LCP
Cons: ? (Still figuring out)

For a "blurred" effect, add filter: blur(<value>) and transform: scale(<value>) styles to the image.

Installation

npm i @plaiceholder/base64

Example

import fs from "fs";
import path from "path";
import { promisify } from "util";
import { getBase64 } from "@plaiceholder/base64";

const image = await promisify(fs.readFile)(
  path.join("path", "to", "your", "image.jpg")
);

const base64 = await getBase64(image);

console.log(base64);

// Outputs
// data:image/jpeg;base64,/9j/2wBDAAYEBQY…

Blurhash

Converts a specified image Buffer into a low-res image, encoded as Blurhash string accompanied by its width and height

Pros: Lightweight, fast DOMContentLoaded and LCP
Cons: As it uses canvas, it's not ideal to use Blurhash for above-the-fold content.

This can be passed into a library such as react-blurhash.

Installation

npm i @plaiceholder/blurhash

Example

import fs from "fs";
import path from "path";
import { promisify } from "util";
import { getBlurhash } from "@plaiceholder/blurhash";

const image = await promisify(fs.readFile)(
  path.join("path", "to", "your", "image.jpg")
);

const blurhash = await getBlurhash(image);

console.log(blurhash);

// Outputs
//  {
//    hash: "U.QSL{%1bdxtR...",
//    height: 32,
//    width: 32
//  }

Plugins

Next.js

A tiny helper function to access public files in server-side functions or getStaticProps()

Installation

npm i @plaiceholder/next

Example

In this example, we're going to use the @plaiceholder/base64 package to create a Base64 string for a single image inside a Next.js Page.

We'll then apply the string to an <img> element (hidden from screen-readers) and position underneath our Image whilst it's loading.

  1. Add your chosen image to the public directory.

    In this case, our image is public/keila-joa.jpg

    In it's current state, @plaiceholder/next only supports local images.

  2. Create a new page (or add to an existing page), and add the following:

    1. Call getBase64() inside getStaticProps() with your image's path without the public prefix. This will return the Base64 string as a static prop.

    2. Add custom styles to position (and blur) the placeholder img underneath Next.js' Image whilst it loads.

    An aria-hidden ensures the content is hidden from screen-readers.

    // pages/index.jsx
    import * as React from "react";
    import Image from "next/image";
    import { getImage } from "@plaiceholder/next";
    import { getBase64 } from "@plaiceholder/base64";
    
    export const getStaticProps: GetStaticProps = async () => {
      const imgSrc = "/keila-joa.jpg";
      const img = await getImage(imgSrc);
      const imgBase64 = await getBase64(img);
    
      return {
        props: {
          imgBase64,
          imgSrc,
        },
      };
    };
    
    function Index({ imgBase64, imgSrc }) {
      return (
        <main>
          <div style={{ position: "relative", overflow: "hidden" }}>
            {/* Our placeholder image */}
            <img
              aria-hidden="true"
              alt=""
              src={imgBase64}
              style={{
                position: "absolute",
                top: 0,
                left: 0,
                right: 0,
                bottom: 0,
                width: "100%",
                height: "100%",
                /* Adjust the content to fit */
                objectFit: "cover",
                objectPosition: "center",
                /* Blur the image and scale to avoid transparent corners */
                filter: "blur(2rem)",
                transform: "scale(1.2)",
              }}
            />
            {/* Your image, optimized by next/image */}
            <Image src={imgSrc} width={4032} height={3024} />
          </div>
        </main>
      );
    }
    
    export default Index;
  3. Run your Next.js app to see the results in action!

    You should expect to see the placeholder first, then the image optimized by Next.js

FAQs

Why have you misspelled "placeholder"?

A Plaice is a flat fish that lays stationary on the sea-bed, much like an image placehol… actually this is bullshit, all the other good names were taken.

What about remote images in Next.js?

In it's current state, @plaiceholder/next only supports local images (added to public). PRs to add support for remote images are welcomed ❤️.