pixx
v0.1.4
Published
Create responsive, web friendly images and HTML code snippets.
Maintainers
Readme
pixx
Why
- 🖼️ Creating responsive images (images that adapt to different screen sizes) can be complicated and prone to errors.
- ✨
Pixxis the 'brute force' method to generate both the responsive images themselves and the corresponding HTML code needed to display them correctly. - ⏩ Using the sharp library, (a high-performance Node.js module for image processing),
pixxcreates different sizes and formats of your images. - Pixx accepts the following image types:
avif, gif, jpeg, jpg, png, tiff, webp, svg.- SVG:
<svg width="800px" height="800px"...</svg>- Images created will be '800px' and smaller.
- SVG:
- Pixx can output the following image types:
avif, gif, jpeg, jpg, png, tiff, webp. - 💻 This package uses the NodeJS environment.
- 📏 Pixx does not increase image size. Start with the largest optimized image for best results.
- 🔧 Pixx is designed to use in project development. The 'pixx' function is called and ran during build, so only HTML is shipped to production.
- 🔤 Your code must use double quote (ASCII 34
") or single quote (ASCII 39'). Fancy quotes other than these will breakpixxlogic. - ⚠️ Sharp error on Windows: Could not load the "sharp" module using the win32-x64 runtime.
- ✅ Solution:
npm install --include=optional sharp
- ✅ Solution:
Simple Start HTML
<!-- npm must be initiated and pixx installed. -->
<!-- npm init -y && npm i -D pixx -->
<!-- 1. add pix function to your html page in a 'script' tag. -->
<!-- index.html example. -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p>Simple Example</p>
<!-- Each pixx function needs it's own 'script' tag. -->
<script>
// img.jpg is 2560x1920.
pixx('img.jpg', {
jsx: false, // JSX syntax is default (e.g. class vs. className). Tell pixx return HTML syntax.
});
</script>
</body>
</html>// 2. Run pixxFlow to build the images and return raw html.
// create a JavaScript file with any name.
// index.js
import { pixxFlow } from 'pixx';
pixxFlow(); // creates a mirrored file: 'pixx-index.html'.
// or
pixxFlow({ overwrite: true }); // comments out the 'pixx' function and add html to 'index.html'.# 3. In the same terminal directory as your index.js, run:
node index.js # images will be created, html is returned and written to page.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p>Simple Example</p>
<!-- Each pixx function needs it's own 'script' tag -->
<!-- <script>
pixx('./images/img.jpg', {
// img.jpg is 2560x1920.
jsx: false, // JSX is default. Tell pixx return raw HTML.
});
</script> -->
<picture>
<source
type="image/avif"
sizes="auto"
srcset="
pixx_images/img.jpg/img_w300h225.avif 300w,
pixx_images/img.jpg/img_w600h450.avif 600w,
pixx_images/img.jpg/img_w900h675.avif 900w,
pixx_images/img.jpg/img_w1200h900.avif 1200w,
pixx_images/img.jpg/img_w1500h1125.avif 1500w,
pixx_images/img.jpg/img_w1800h1350.avif 1800w,
pixx_images/img.jpg/img_w2100h1575.avif 2100w,
pixx_images/img.jpg/img_w2400h1800.avif 2400w,
pixx_images/img.jpg/img_w2560h1920.avif 2560w
"
/>
<source
type="image/webp"
sizes="auto"
srcset="
pixx_images/img.jpg/img_w300h225.webp 300w,
pixx_images/img.jpg/img_w600h450.webp 600w,
pixx_images/img.jpg/img_w900h675.webp 900w,
pixx_images/img.jpg/img_w1200h900.webp 1200w,
pixx_images/img.jpg/img_w1500h1125.webp 1500w,
pixx_images/img.jpg/img_w1800h1350.webp 1800w,
pixx_images/img.jpg/img_w2100h1575.webp 2100w,
pixx_images/img.jpg/img_w2400h1800.webp 2400w,
pixx_images/img.jpg/img_w2560h1920.webp 2560w
"
/>
<source
type="image/jpg"
sizes="auto"
srcset="
pixx_images/img.jpg/img_w300h225.jpg 300w,
pixx_images/img.jpg/img_w600h450.jpg 600w,
pixx_images/img.jpg/img_w900h675.jpg 900w,
pixx_images/img.jpg/img_w1200h900.jpg 1200w,
pixx_images/img.jpg/img_w1500h1125.jpg 1500w,
pixx_images/img.jpg/img_w1800h1350.jpg 1800w,
pixx_images/img.jpg/img_w2100h1575.jpg 2100w,
pixx_images/img.jpg/img_w2400h1800.jpg 2400w,
pixx_images/img.jpg/img_w2560h1920.jpg 2560w
"
/>
<img
src="pixx_images/img.jpg/img-fallback_w2560h1920.jpg"
sizes="auto"
alt="pixx_image"
width="2560"
height="1920"
loading="lazy"
decoding="auto"
fetchpriority="auto"
/>
</picture>
</body>
</html>Simple Start JSX (Vite)
// 1. create a vite project and install pixx.
// npm create vite@latest // https://vite.dev/guide/
// npm i -D pixx
// Add pixx plugin to 'vite.config.ts'.
import { defineConfig } from 'vite';
import { pixxVitePlugin } from 'pixx';
export default defineConfig({
plugins: [pixxVitePlugin({ log: true })],
});
// 2. Add pixx function to your .jsx or .tsx page.
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. The space in file name will be replaced in the new images so HTML is valid. */}
{pixx('./images/happy face.jpg')}
</div>
);
}# 3. In the same terminal root directory, run:
npm run dev # images are created, pixxVitePlugin intercepts page and replaces pixx function with html.
# or
npm run build # images will be created, html is returned and written to page.// import pixx from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. The space in file name will be replaced so HTMl is valid. */}
{/* {pixx('./images/happy face.jpg')} */}
<picture>
<source
type="image/avif"
sizes="auto"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.avif 300w, pixx_images/happy_face.jpg/happy_face_w600h300.avif 600w, pixx_images/happy_face.jpg/happy_face_w720h360.avif 720w"
/>
<source
type="image/webp"
sizes="auto"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.webp 300w, pixx_images/happy_face.jpg/happy_face_w600h300.webp 600w, pixx_images/happy_face.jpg/happy_face_w720h360.webp 720w"
/>
<source
type="image/jpg"
sizes="auto"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.jpg 300w, pixx_images/happy_face.jpg/happy_face_w600h300.jpg 600w, pixx_images/happy_face.jpg/happy_face_w720h360.jpg 720w"
/>
<img
src="pixx_images/happy_face.jpg/happy_face-fallback_w720h360.jpg"
sizes="auto"
alt="pixx_image"
width="720"
height="360"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}Understanding Responsive Images: Resolution Switching, Multiple Types, and Art Direction
- All 'responsive image methods' must have
<meta name="viewport" content="width=device-width">added to the head section of the html page, for mobile browsers to use the actual device viewport in decision making. - Responsive Image Advantages
- When mobile or desktop browsers download and parse the HTML, the
sizes,srcsetandmediaattribute give clues to the browser about the best images to download. - Using these attributes, the browser decides the best image to download based on its viewport size and pixel density.
- sizes: inform the browser about how much of the viewport the image will fill.
- srcset: inform the browser about the available image widths to choose from.
- media: Art direction only. Completely different images can be offered depending on device screen size.
- When mobile or desktop browsers download and parse the HTML, the
Responsive Images
- Three main ways to use responsive images.
- Resolution Switching: Single image in multiple sizes. (e.g. img-100.jpg, img-200.jpg, img-300.jpg).
- Multiple Types: Single image in multiple sizes and types. (e.g. avif, webp, jpg).
- Art Direction: Multiple different images the browser will choose depending on viewport width.
- (e.g. img-full.jpg, img-crop.jpg).
Resolution Switching
- Uses the
imgelement with thesrcsetandsizesattributes. - Single image type. Browsers can choose from the srcset attribute, the image to download based of the device viewport, pixel density and sizes attribute.
- Fallback is the img
srcattribute. - Pros
- The least complex. Default sizes attribute is
auto(the 'img' width and height values). - Browser can choose from multiple image options.
- The least complex. Default sizes attribute is
- Cons
- Only single image type can be used at a time.
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{pixx('./images/lunar moon.jpg', {
picTypes: ['webp'],
sizes: ['(max-width: 450px) 75vw', '(max-width: 800px) 50vw', '25vw'],
})}
</div>
);
}// Single image type, multiple sizes.
// Explanation: As an example, device viewport has a width of 700px.
// The 'sizes media condition' tells browser 'if device screen is <= 450px, image will take 75% (338px) of width'.
// If viewport pixel density is 2x, browser will choose >= 676px image (338px x 2 = 676px).
// The closest image to satisfy the browser is 'pixx_images/lunar_moon.jpg/lunar_moon_w900h675.webp 900w'.
// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{/* {pixx('./images/lunar moon.jpg', {
picTypes: ['webp'],
sizes: ['(max-width: 450px) 75vw', '(max-width: 800px) 50vw', '25vw'],
})} */}
<img
src="pixx_images/lunar_moon.jpg/lunar_moon-fallback_w2560h1920.jpg"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.webp 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.webp 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.webp 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.webp 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.webp 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.webp 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.webp 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.webp 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.webp 2560w"
sizes="(max-width: 450px) 75vw, (max-width: 800px) 50vw, 25vw"
alt="pixx_image"
width="2560"
height="1920"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</div>
);
}Multiple Types
- Uses the
pictureandsourceelement with thesrcsetandsizesattributes. - Multiple image types. Browsers can choose what image size and type to download based on the device viewport and pixel density.
- Fallback is
imgelement. - Pros
- Use new and highly optimized image types, with fallback, for browsers that don't support them.
- Cons
- Code can be complex.
- Order matters. Browser takes the first truthy value.
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{pixx('./images/lunar moon.jpg')}
</div>
);
}// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{/* {pixx('./images/lunar moon.jpg')} */}
<picture>
<source
type="image/avif"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.avif 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.avif 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.avif 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.avif 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.avif 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.avif 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.avif 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.avif 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.avif 2560w"
/>
<source
type="image/webp"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.webp 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.webp 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.webp 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.webp 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.webp 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.webp 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.webp 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.webp 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.webp 2560w"
/>
<source
type="image/jpg"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.jpg 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.jpg 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.jpg 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.jpg 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.jpg 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.jpg 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.jpg 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.jpg 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.jpg 2560w"
/>
<img
src="pixx_images/lunar_moon.jpg/lunar_moon-fallback_w2560h1920.jpg"
sizes="auto"
alt="pixx_image"
width="2560"
height="1920"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}Art Direction
- Uses the
pictureandsourceelement with thesrcset,sizesandmediaattributes. - Multiple images. Browsers can choose between different images and their size and type to download based on the device viewport and pixel density.
- Switch different image formats based on first truthy media condition.
- Fallback is
imgelement. - Pros
- Switch image based viewport size.
- Cons
- Code can be complex.
- Order matters. Browser takes the first truthy value.
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. lunar moon.jpg is 2560x1920. */}
{/* at least one media condition is required. */}
{pixx(['./images/lunar moon.jpg', './images/happy face.jpg'], {
media: ['(max-width: 400px) happy face.jpg', '(min-width: 401px) lunar moon.jpg'],
sizes: ['(max-width: 400px) 100vw', '(min-width: 401px) 50vw', '100vw'],
})}
</div>
);
}// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920. happy face.jpg is 720x360. */}
{/* at least one media condition is required. */}
{/* {pixx(['./images/lunar moon.jpg', './images/happy face.jpg'], {
media: ['(max-width: 400px) happy face.jpg', '(min-width: 401px) lunar moon.jpg'],
sizes: ['(max-width: 400px) 100vw', '(min-width: 401px) 50vw', '100vw'],
})} */}
<picture>
<source
type="image/avif"
media="(min-width: 401px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.avif 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.avif 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.avif 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.avif 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.avif 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.avif 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.avif 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.avif 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.avif 2560w"
/>
<source
type="image/webp"
media="(min-width: 401px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.webp 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.webp 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.webp 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.webp 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.webp 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.webp 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.webp 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.webp 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.webp 2560w"
/>
<source
type="image/jpg"
media="(min-width: 401px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.jpg 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.jpg 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.jpg 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.jpg 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.jpg 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.jpg 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.jpg 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.jpg 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.jpg 2560w"
/>
<source
type="image/avif"
media="(max-width: 400px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.avif 300w, pixx_images/happy_face.jpg/happy_face_w600h300.avif 600w, pixx_images/happy_face.jpg/happy_face_w720h360.avif 720w"
/>
<source
type="image/webp"
media="(max-width: 400px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.webp 300w, pixx_images/happy_face.jpg/happy_face_w600h300.webp 600w, pixx_images/happy_face.jpg/happy_face_w720h360.webp 720w"
/>
<source
type="image/jpg"
media="(max-width: 400px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.jpg 300w, pixx_images/happy_face.jpg/happy_face_w600h300.jpg 600w, pixx_images/happy_face.jpg/happy_face_w720h360.jpg 720w"
/>
<img
src="pixx_images/happy_face.jpg/happy_face-fallback_w720h360.jpg"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
alt="pixx_image"
width="720"
height="360"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}Responsive Image Tips
- Pixx creates images below-the-fold by default.
- Images above-the-fold (e.g. images you see as soon as the web page loads) should have
aboveTheFold: trueoption set. - If you would like also use a 'preload' image, set
withPreload: trueoption.- The
<link preload ... />tag printed to the console should be added to the<head>section.
- The
Pixx Options
pixx('image1.jpg', optionDefaults);
// Options Overview.
export const optionDefaults = {
aboveTheFold: false, // Image will show on page load. Changes: loading: 'eager', fetchPriority: 'high', withBlur: true,
alt: 'pixx_image', // alternate image description.
backgroundSize: 'cover', // https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
blurSize: 16, // width of placeholder image in pixels. Smaller number, smaller placeholder image size.
classes: [], // array of class names added to 'img' element.
clean: false, // each run, delete images folder and create new.
decoding: 'auto', // "auto" | "sync" | "async". Image download priority. https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding
fallbackWidth: 0, // 'original image width'. Custom fallback image width in pixels.
fetchPriority: 'auto', // "auto" | "high" | "low". hints to browser image download importance. https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/fetchPriority
heights: [], // only create images with these heights. Aspect ratio is preserved. (e.g. heights: [200, 400, 600]).
jsx: true, // change to JSX syntax. (e.g. class becomes className).
incrementSize: 300, // size in pixels to create the next smaller image.
linuxPaths: true, // convert image path to linux. (e.g. false: "C:\images\myimage.jpg" vs. true: "/images/myimage.jpg").
loading: 'lazy', // "eager" | "lazy". 'img' element loading priority. Above-the-fold images should be 'eager'.
log: false, // Output build details to log file with same name as image. (e.g. img1.jpg => img1.jpg.log)
media: [], // Art direction only. Set media condition for each to display image.
newImagesDirectory: 'pixx_images', // directory name where images will be saved.
omit: { remove: '', add: '' }, // modify the image path in the HTML.
picTypes: ['avif', 'webp', 'jpg'], // "avif" | "gif" | "jpeg" | "jpg" | "png" | "tiff" | "webp".
preloadWidth: 0, // '30% of fallbackWidth'. Preload image is lower resolution.
showProgressBar: true, // display progress bar of image creation progress.
sizes: ['auto'], // media conditions that informs browser how much of the screen width image will need. Browser decides best image to download based on it's screen size and 'srcset' attribute. https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/sizes https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#sizes
styles: [], // key:value[]. 'img' element 'style' attribute. (e.g. styles: ["color: 'blue'", "lineHeight : 10", "padding: 20" ]).
title: '', // Text to display as tooltip when hover over image.
v: [], // placeholder for dynamic variables.
vite: false, // auto set options for Vite public folder. (e.g. true: newImagesDirectory: 'public' and omit: { remove: 'public/'} )
widths: [], // only create images with these 'widths'. (e.g. widths: [300, 900, 1200]).
withAnimation: false, // notifies the 'sharp' image library to keep image animation when creating new images.
withBlur: false, // when 'true', creates inline style base64DataURL.
withMetadata: false, // notify 'sharp' to copy original image metadata when creating new image.
withPreload: false, // if true, create preload image.
} as OptionType;Examples
- LQIP: low-quality image placeholders.
- Inspired by csswizardry.
- What is Preloading and base64URL?
- It's a way to improve perceived speed an image loads on a website. Basically, you show a blurry version of the image first, then show a low resolution image and then replace it with the full-quality image once it's downloaded. This makes the page feel faster and less jarring for the user.
withPreloadonly adds benefit when your dealing with very slow connections (slow 3g).
- base64 image URL Placeholder: The first LQIP is a very small, blurry image encoded directly into the webpage's code as a
base64 dataURL. This creates the initial blur effect you see while the actual image loads. - Low-Resolution Image: The second LQIP is a slightly higher-resolution image, about 1/3 the size of the final image (you can adjust this with the
preloadWidthoption). A specialpreloadtag for this image is printed to the console. You should then copy this tag and paste it into the<head>section of your HTML.
- It's a way to improve perceived speed an image loads on a website. Basically, you show a blurry version of the image first, then show a low resolution image and then replace it with the full-quality image once it's downloaded. This makes the page feel faster and less jarring for the user.
- How Preloading Works
- When the browser sees the
preloadtag in the<head>, it starts downloading the low-resolution image right away, even before it finishes reading the rest of the page. - Once this low-resolution image is downloaded, it's displayed as a placeholder until the full-resolution image is ready.
- Both LQIPs are applied as a
background-imagewithin a<style>tag.
- When the browser sees the
- aboveTheFold: boolean
- Default
false. Whentrue, turns on the following options:loading: 'eager', fetchPriority: 'high', withBlur: true.- If you want the 'preload' image, use the
withPreload: trueoption.
- Default
- backgroundSize: string
- Default
cover. Change thebackground-sizevalue for blur placeholder. - Controls how the blurred placeholder image is sized.
- Think of it like setting a background image to "cover" the entire area, "contain" it within the area, or "stretch" it to fit.
- This only works if you also turn on the
withBlur: trueoption. - For more details on how background-size works, check out this link: MDN background-size
- Default
- blurSize: number
- Default
16pixels. Number of pixels wide the placeholder image is resized to. - Determines the size of the small placeholder image used to create the blur effect.
- Larger blurSize, larger blurDataURL.
- The
blurDataURLis awebpimage encoded inbase64.
- Default
- decoding:string
- Default
auto. Options: sync | async | auto - hint to browser how it should decode content relative to other content.
- Note: difference in values make no noticeable difference in performance.
- https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding
- Default
- fetchPriority: string
- Default
auto. Options: "auto" | "high" | "low". - hints to the browser how it should prioritize fetching a resource relative to other resources.
- https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/fetchPriority
- Default
- loading: string
- Default
lazy. Options: lazy | eager. - hint to browser when to load image outside viewport.
- https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading
- Default
- preloadWidth: number
- Default
30% of fallbackWidth. - Preload image is a lower resolution image placeholder that can help show webpage when internet data is very slow.
- Default
- withBlur: boolean
- Default
false. Whentrue, base64DataURL will be inlined in the 'style' tags 'backgroundImage' attribute.
- Default
- withPreload: boolean
- Default
false. Whentrue, the preload image URL will be inlined in the 'style' tags 'backgroundImage' attribute. withPreloadonly adds benefit when your dealing with very slow connections (slow 3g).withPreload: truewill automatically setfetchPriority: 'high'.- Prints to console a
<link preload />tag. Add this tag to the HTML's<head>section.- This tag tells the browser to load the image early on, so it appears faster.
- This option is related to a technique called LQIP (Low-Quality Image Placeholder).
- Default
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{pixx('./images/lunar moon.jpg', {
aboveTheFold: true,
withPreload: true,
preloadWidth: 200,
backgroundSize: 'contain',
})}
</div>
);
}
// Returns 👇
// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{/* {pixx('./images/lunar moon.jpg', {
aboveTheFold: true,
withPreload: true,
preloadWidth: 200,
backgroundSize: 'contain',
})} */}
<picture>
<source
type="image/avif"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.avif 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.avif 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.avif 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.avif 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.avif 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.avif 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.avif 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.avif 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.avif 2560w"
/>
<source
type="image/webp"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.webp 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.webp 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.webp 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.webp 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.webp 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.webp 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.webp 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.webp 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.webp 2560w"
/>
<source
type="image/jpg"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.jpg 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.jpg 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.jpg 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.jpg 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.jpg 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.jpg 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.jpg 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.jpg 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.jpg 2560w"
/>
<img
src="pixx_images/lunar_moon.jpg/lunar_moon-fallback_w2560h1920.jpg"
style={{
backgroundImage:
'url("pixx_images/lunar_moon.jpg/lunar_moon-preload_w200h150.webp"), url("data:image/webp;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABUDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAYEBQf/xAAlEAABAwIFBQEBAAAAAAAAAAABAgMFAAQGBxETIRIxQVGhUnH/xAAVAQEBAAAAAAAAAAAAAAAAAAAFBP/EACQRAAECBAUFAAAAAAAAAAAAAAECAwAFETEEEyFhkRRBUeHw/9oADAMBAAIRAxEAPwBFy/y/EtHKkZFe1bA6JJ41P9Pim5GXcNfb7VrctOLZPQ4GlJUW1ejoeKguYbu5uMZUqQct0ISNWHQNtJH5SFafKponCUhYyz1xE3LrN0EFIcaf2+v3zz9FPqlGJKVlt5NfBGnN+BCuHm77KAjpqpNzoT6+7wn4yw3c4fmXLNQKgOUqHYjwaK0aRRMhaEybb1y6kaBa9pwgeuruaKpYlDpbGY4K7Wgd+bOJcIS2QN4//9k=")',
backgroundSize: 'contain',
}}
sizes="auto"
alt="pixx_image"
width="2560"
height="1920"
loading="eager"
decoding="auto"
fetchPriority="high"
/>
</picture>
</div>
);
}- jsx: boolean.
- Default
true. Image class attribute fixed for JSX. - Changes:
- | jsx: false (HTML) | jsx: true (JSX) | | ----------------- | --------------- | | class | className | | srcset | srcSet | | fetchpriority | fetchPriority | | background-image | backgroundImage | | background-size | backgroundSize |
- Default
- classes: string[]
- Default: []. static classes will not be added to the
cnfunction. - If you want to run your static classes through the
cnfunction (e.g. remove class clashes), add 'cn' in theclassesarray. - dynamic_classes: string[]
- Default []. Only JSX can use dynamic, HTML must be use JavaScript during runtime to change classes.
- Because pixx runs and injects the HTML before the page is loaded, variables in the page are out of 'scope' to the pixx function. The variables become available after the page is parsed during runtime. To notify pixx a class is a variable, add a
d:before the name. See example 👇. - Dynamic classes need the cn function imported.
npm i cncn.- Order matters. If classes clash, the last one wins.
- Default: []. static classes will not be added to the
- linting errors:
- Linters: Linters are tools that analyze code for potential errors, inconsistencies, and style issues. One common warning linters give is for "unused variables" – variables that are defined but never actually used in the code.
- The 'v:' Solution: Since the "d:" variables are strings and look unused to a linter, the linter will complain. The
v: [var1, var2, ...]option gives you a spot variables can be listed. - Internal Handling: The pixx function internally removes these "d:" variables before processing, ensuring they don't cause any conflicts or errors during execution.
- styles: string[]
- Default:
[]. - HTML: key:value pair of strings. (e.g. ['color: blue', 'line-height: 20', 'margin-top: 20px'])
- HTML cannot use variables. Must use JavaScript to change styles during runtime.
- JSX: key:value pair of strings. (e.g. ["color: 'blue'", "lineHeight: 20", "marginTop: '20px'", "marginBottom: size"])
- Notice all strings are quoted, numbers and variables are not quoted.
marginBottom: size// size is dynamic, it's still a string, but not quoted. See example 👇.- Cannot use
tailwindcssin styles.
- Default:
- v: unknown[]
- Default:
[].vis a placeholder for variables, so linter does not complain. When pixx runs, v is removed. - (e.g.
v: [var1, var2, cn])
- Default:
HTML Example
<!-- HTML -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
{
pixx('./images/img4.avif', {
jsx: false,
classes: ['one', 'two', 'three'],
styles: ['color: blue', 'line-height: 1.5', 'margin-top: 20px'], // html
log: true,
});
}
</script>
</body>
</html>
<!-- Returns 👇 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<!-- <script>
{
pixx('./images/img4.avif', {
jsx: false,
classes: ['one', 'two', 'three'],
styles: ['color: blue', 'line-height: 1.5', 'margin-top: 20px'], // html
log: true,
});
}
</script> -->
<picture>
<!-- ... -->
<img
src="pixx_images/img4.avif/img4-fallback_w626h351.jpg"
style="color: blue; line-height: 1.5; margin-top: 20px"
class="one"
two
three
sizes="auto"
alt="pixx_image"
width="626"
height="351"
loading="lazy"
decoding="auto"
fetchpriority="auto"
/>
</picture>
</body>
</html>JSX Example
// JSX Classes & Styles
import { pixx } from 'pixx';
import cn from 'cncn';
export default function App() {
const size = 1.5;
const classString = 'three';
return (
<div>
{pixx('./images/dynamic-class.avif', {
classes: ['one', 'cn', 'two', 'd:classString'], // dynamic classes.
styles: ["color: 'blue'", 'lineHeight: size', 'marginBottom: "20px"'], // jsx. 'size' is not quoted, so
v: [cn, classString, size],
log: true,
})}
</div>
);
}
// Returns 👇
// import { pixx } from 'pixx';
import cn from 'cncn';
export default function App() {
const size = 1.5;
const classString = 'three';
return (
<div>
{/* {pixx('./images/dynamic-class.avif', {
classes: ['one', 'cn', 'two', 'd:classString'],
styles: ["color: 'blue'", "lineHeight: size", 'marginBottom: "20px"'], // jsx
v: [cn, classString, size],
log: true,
})} */}
<picture>
{/* ... */}
<img
src="pixx_images/dynamic-class.avif/dynamic-class-fallback_w626h351.jpg"
style={{ color: 'blue', lineHeight: 1.5, marginBottom: '20px' }}
className={cn('one', 'two', classString)}
sizes="auto"
alt="pixx_image"
width="626"
height="351"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}- alt: string
- Default
pixx_image. The imgaltattribute.
- Default
- picTypes: enums('avif', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'webp')[]
- Default
['avif', 'webp', 'jpg']. - Images will be created as these types.
- Default
- title: string
- Default
''. Text to display as tooltip when hover over image.
- Default
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{pixx('./images/lunar moon.jpg', {
alt: 'picture of moon',
title: 'Moon Shot',
picTypes: ['avif', 'gif', 'tiff'],
})}
</div>
);
}
// Returns 👇
// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* lunar moon.jpg is 2560x1920 */}
{/* {pixx('./images/lunar moon.jpg', {
alt: 'picture of moon',
title: 'Moon Shot',
picTypes: ['avif', 'gif', 'tiff'],
})} */}
<picture>
<source
type="image/avif"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.avif 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.avif 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.avif 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.avif 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.avif 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.avif 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.avif 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.avif 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.avif 2560w"
/>
<source
type="image/tiff"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.tiff 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.tiff 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.tiff 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.tiff 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.tiff 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.tiff 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.tiff 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.tiff 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.tiff 2560w"
/>
<source
type="image/gif"
sizes="auto"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.gif 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.gif 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.gif 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.gif 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.gif 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.gif 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.gif 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.gif 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.gif 2560w"
/>
<img
src="pixx_images/lunar_moon.jpg/lunar_moon-fallback_w2560h1920.jpg"
sizes="auto"
alt="picture of moon"
width="2560"
height="1920"
title="Moon Shot"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}- media: string[]
- Default
[]. Array of media conditions and image names. - Art Direction only. Must provide two or more images. Media condition must match each image.
- Specify different images to be displayed based on the user's screen size or device orientation. This technique is often called art direction.
- A media query that describes a specific screen size or device orientation (e.g.,
(max-width: 768px)for smaller screens or(orientation: landscape)for landscape mode). - The last image provided in
image namesarray will used as the fallback image. - Art direction allows you to:
- Optimize for different screen sizes: You can use smaller images for mobile devices, saving bandwidth and improving loading times.
- Improve composition: You can crop or adjust images to look their best at different sizes and orientations.
- Provide a better user experience: By tailoring images to the user's device, you can create a more visually appealing and engaging website.
- Learn More:
- Default
- sizes
- Default
['100vw']. Array of media conditions and the viewport fill width. - The
sizesoption, which is used to provide hints to the browser about how much space an image will take up on the screen. This information helps the browser make better decisions about which image to load, especially when you have different sizes of the same image available (like in responsive images). - Each string has two parts:
- Media Condition: A CSS media query that describes a specific screen size or device characteristic (e.g. (max-width: 768px) for smaller screens).
- Media Descriptor: A CSS length value (e.g. 100vw, 30rem, or 500px) that tells the browser how much of the viewport width the image will occupy when that media condition is met. Note that percentages are not allowed here.
- How Browsers Use
sizes: The browser looks at the sizes media conditions you've provided and compares them to the user's current screen size. It then uses the corresponding viewport fill width to estimate the image's display size. This helps the browser choose the most appropriate image source from a srcset attribute (which lists different image sources). - Default Value: If no
sizes media conditionsmatch, the browser uses the default (last value) in thesizesarray as the default. The default value isauto, which means the browser will use the image width and height to determine viewport fill. - MDN sizes.
- Default
// Sizes Example
// First 'true' condition is taken.
// If viewport width is 500px or less, the image will take 75% of it.
// If viewport width is 800px or less, the image will take 50% of it.
// If viewport width is larger than 800px, the image will take 25% of it.
pixx('img.jpg', { sizes: ['(max-width: 500px) 75vw', '(max-width: 800px) 50vw', '25vw'] });
// Sizes & Media Example
// the fallback image will be the last image provided to pixx ('happy face.jpg').
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. lunar moon.jpg is 2560x1920. */}
{/* at least one media condition is required. */}
{pixx(['./images/lunar moon.jpg', './images/happy face.jpg'], {
media: ['(max-width: 400px) happy face.jpg', '(min-width: 401px) lunar moon.jpg'], // media condition imageName
sizes: ['(max-width: 400px) 100vw', '(min-width: 401px) 50vw', '100vw'], // last one is default size.
})}
</div>
);
}
// Returns 👇
// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. lunar moon.jpg is 2560x1920. */}
{/* at least one media condition is required. */}
{/* {pixx(['./images/lunar moon.jpg', './images/happy face.jpg'], {
media: ['(max-width: 400px) happy face.jpg', '(min-width: 401px) lunar moon.jpg'], // media condition imageName
sizes: ['(max-width: 400px) 100vw', '(min-width: 401px) 50vw', '100vw'], // last one is default size.
})} */}
<picture>
<source
type="image/avif"
media="(min-width: 401px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.avif 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.avif 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.avif 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.avif 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.avif 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.avif 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.avif 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.avif 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.avif 2560w"
/>
<source
type="image/webp"
media="(min-width: 401px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.webp 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.webp 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.webp 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.webp 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.webp 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.webp 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.webp 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.webp 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.webp 2560w"
/>
<source
type="image/jpg"
media="(min-width: 401px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/lunar_moon.jpg/lunar_moon_w300h225.jpg 300w, pixx_images/lunar_moon.jpg/lunar_moon_w600h450.jpg 600w, pixx_images/lunar_moon.jpg/lunar_moon_w900h675.jpg 900w, pixx_images/lunar_moon.jpg/lunar_moon_w1200h900.jpg 1200w, pixx_images/lunar_moon.jpg/lunar_moon_w1500h1125.jpg 1500w, pixx_images/lunar_moon.jpg/lunar_moon_w1800h1350.jpg 1800w, pixx_images/lunar_moon.jpg/lunar_moon_w2100h1575.jpg 2100w, pixx_images/lunar_moon.jpg/lunar_moon_w2400h1800.jpg 2400w, pixx_images/lunar_moon.jpg/lunar_moon_w2560h1920.jpg 2560w"
/>
<source
type="image/avif"
media="(max-width: 400px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.avif 300w, pixx_images/happy_face.jpg/happy_face_w600h300.avif 600w, pixx_images/happy_face.jpg/happy_face_w720h360.avif 720w"
/>
<source
type="image/webp"
media="(max-width: 400px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.webp 300w, pixx_images/happy_face.jpg/happy_face_w600h300.webp 600w, pixx_images/happy_face.jpg/happy_face_w720h360.webp 720w"
/>
<source
type="image/jpg"
media="(max-width: 400px)"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
srcSet="pixx_images/happy_face.jpg/happy_face_w300h150.jpg 300w, pixx_images/happy_face.jpg/happy_face_w600h300.jpg 600w, pixx_images/happy_face.jpg/happy_face_w720h360.jpg 720w"
/>
<img
src="pixx_images/happy_face.jpg/happy_face-fallback_w720h360.jpg"
sizes="(max-width: 400px) 100vw, (min-width: 401px) 50vw, 100vw"
alt="pixx_image"
width="720"
height="360"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}DefaultSizes, IncrementSize, Heights, and Widths
- These options give you control over the resizing process. You can either:
- Provide specific sizes using
widths[]orheights[]. - Let the tool automatically generate sizes at intervals using
incrementSize. - Prioritization: If you use
widths, those will take precedence overheights. Both widths and heights have higher priority thandefaultSizes.
- Provide specific sizes using
- defaultSizes:
- If
widthsorheightsare not provided, usesincrementSizeto create images smaller than width of original image. - (e.g. If image is 1000px wide and incrementSize is 300. Pixx will create images: 300, 600, 900, 1000 wide, keeping same aspect ratio).
- If
- heights: number[]
- Default
[]. Array of numbers representing desired height in pixels. - This option lets you specify an array of heights (in pixels) for the generated images.
- For example,
heights: [200, 400, 600]would create three versions of the image with those specific heights. - Important: The heights you provide cannot be larger than the original image's height. The tool won't upscale your images.
- Default
- incrementSize: number
- Default
300. Create images in steps of 300 pixels wide (e.g. 300px, 600px, 900px, etc.). - This option controls the automatic size increments when you don't provide specific
widthsorheights.
- Default
- widths: number[]
- Default
[]. Array of widths to create images. - This option is similar to
heights, but it lets you specify an array of widths (in pixels) for the generated images. - Example:
widths: [300, 500, 650, 900, 1200]would create images with those specific widths. - Prioritization:
widthshave the highest priority, followed byheights, and thendefaultSizes.
- Default
FallbackWidth & PreloadWidth
- fallbackWidth: number
- Default
original image width. Custom fallback image width in pixels. - The fallback image is specifically for older browsers that may not be able to handle the optimized images.
- The
fallbackWidthoption lets you specify the width of a fallback image in pixels. - The fallback image will always be a JPEG (
jpg) format. This is a widely supported format that works well in most browsers. Importantly, the fallbackWidth cannot be larger than the original image's width. - Relationship with
media(Art Direction):- Art Direction is displaying different images based on the 'truthy' media condition.
- The last image provided in
mediaarray will used as the fallback image.
- Default
- preloadWidth: number
- Default
30% of the fallbackWidth. - The
preloadWidthoverrides this behavior and allows you to have a customize thelow-resolutionimage size. withPreload: truemust be used to have a preload image.
- Default
- clean: boolean
- Default
false. Delete image folder and create new each pixx function. Useful to start fresh. - Use caution with frameworks. Server/Client Frameworks tend to run multiple times each page to parse necessary files. Each image WILL be remade multiple times from each pixx function. This will slow down the 'dev' environment tremendously!
- Default
- withAnimation: boolean.
- Default
false. Sharp image library will retain the image animation. (e.g.webporgifimages).
- Default
- withMetadata: boolean.
- Default
false. Sharp image library will copy original image metadata to newly created images.
- Default
pixx('img.jpg', { withAnimation: true, withMetadata: true, clean: true });- These options provide flexibility in managing image paths, especially when working with different operating systems, frameworks, or custom project structures. They help ensure that your images are stored and referenced correctly in your web application.
- linuxPaths: boolean
- Default
true. - This option is useful for developers who work on a Windows machine but deploy their website to a Linux server.
- Windows and Linux use different formats for file paths (e.g. "C:\images\myimage.jpg" vs. "/images/myimage.jpg").
- When linuxPaths is set to true (which is the default), the tool will automatically convert html image paths to the Linux format. This ensures that your images will work correctly when you deploy your site to a Linux server.
- Default
- omit: { remove?: string, add?: string }
- Default
{ remove: '', add: '' }. Object withremoveandaddproperties. - This option provides fine-grained control over how image paths are generated in your HTML.
- It allows you to:
remove: Remove a specific part of the image path.add: Add a custom string to the image path.- Example:
omit: { remove: 'pixx_images', add: './my-special-path' }would replace "pixx_images" with "./my-special-path". - Important: This option only modifies the image path in the HTML; it doesn't change where the actual image files are stored.
- Default
- newImagesDirectory: string
- Default
pic_images. - This option lets you specify the name of the directory where the optimized images will be saved.
- Default
- vite: boolean
- Default
false. - Shortcut for developers using the Vite build tool.
- When set to
true, it setsnewImagesDirectoryto 'public' and configures omit to correctly handle image paths within Vite projects. - Vite image directory must be in the public folder for images to be automatically copied over when building.
- When using the 'vite-plugin-pixx',
vite: trueis automatically set.
- Default
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. */}
{pixx('./images/happy face.jpg', {
newImagesDirectory: 'all-my-images',
omit: { remove: 'all-my-images', add: 'special-directory' },
})}
</div>
);
}
// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. */}
{/* {pixx('./images/happy face.jpg', {
newImagesDirectory: 'all-my-images',
omit: { remove: 'all-my-images', add: 'special-directory' },
})} */}
<picture>
<source
type="image/avif"
sizes="auto"
srcSet="special-directory/happy_face.jpg/happy_face_w300h150.avif 300w, special-directory/happy_face.jpg/happy_face_w600h300.avif 600w, special-directory/happy_face.jpg/happy_face_w720h360.avif 720w"
/>
<source
type="image/webp"
sizes="auto"
srcSet="special-directory/happy_face.jpg/happy_face_w300h150.webp 300w, special-directory/happy_face.jpg/happy_face_w600h300.webp 600w, special-directory/happy_face.jpg/happy_face_w720h360.webp 720w"
/>
<source
type="image/jpg"
sizes="auto"
srcSet="special-directory/happy_face.jpg/happy_face_w300h150.jpg 300w, special-directory/happy_face.jpg/happy_face_w600h300.jpg 600w, special-directory/happy_face.jpg/happy_face_w720h360.jpg 720w"
/>
<img
src="special-directory/happy_face.jpg/happy_face-fallback_w720h360.jpg"
sizes="auto"
alt="pixx_image"
width="720"
height="360"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}
// Vite Example
import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. */}
{pixx('./images/happy face.jpg', {
vite: true, // same as: newImagesDirectory = 'public'. omit = { remove = 'public/'}.
})}
</div>
);
}
// Returns 👇
// import { pixx } from 'pixx';
export default function App() {
return (
<div>
{/* happy face.jpg is 720x360. */}
{/* {pixx('./images/happy face.jpg', {
vite: true, // same as: newImagesDirectory = 'public'. omit = { remove = 'public/'}.
})} */}
<picture>
<source
type="image/avif"
sizes="auto"
srcSet="happy_face.jpg/happy_face_w300h150.avif 300w, happy_face.jpg/happy_face_w600h300.avif 600w, happy_face.jpg/happy_face_w720h360.avif 720w"
/>
<source
type="image/webp"
sizes="auto"
srcSet="happy_face.jpg/happy_face_w300h150.webp 300w, happy_face.jpg/happy_face_w600h300.webp 600w, happy_face.jpg/happy_face_w720h360.webp 720w"
/>
<source
type="image/jpg"
sizes="auto"
srcSet="happy_face.jpg/happy_face_w300h150.jpg 300w, happy_face.jpg/happy_face_w600h300.jpg 600w, happy_face.jpg/happy_face_w720h360.jpg 720w"
/>
<img
src="happy_face.jpg/happy_face-fallback_w720h360.jpg"
sizes="auto"
alt="pixx_image"
width="720"
height="360"
loading="lazy"
decoding="auto"
fetchPriority="auto"
/>
</picture>
</div>
);
}- log: boolean
- Default
false. Output build details to file with the image name. (e.g. image.jpg = image.jpg.log). - When set to
true, it provides extensive information, including:- State of the image creation process.
- Details about hidden image data (metadata), such as:
- EXIF: Information about the camera settings used to take the image (e.g., exposure, ISO, date/time).
- XMP: Extensible Metadata Platform, which can include various types of information like copyright, keywords, and descriptions.
- ICC: Color profiles that ensure consistent color representation across different devices.
- GPS: Geographical location where the image was taken.
- Default
- showProgressBar: boolean
- Default
true. This option controls whether a progress bar is displayed during the image creation process.
- Default
pixx('img.jpg', { log: true, progressBar: false });pixxFlow
- This tool acts like a helper that automatically finds the
pixxfunction in your files, runs it, and adds the results to your web page. - Static File Scraper: This tool scans your project files to find and process the
pixxfunction. It uses the NPM Glob library (a popular Node.js module) to search for files matching a specific pattern. - How it Works:
- Find pixx Functions: The tool searches your project files for instances of the
pixxfunction. - Execute pixx Code: When it finds a
pixxfunction, it executes the code within that function. - Comment Out: After execution, the tool comments out the original
pixxfunction in the file. This prevents it from being executed again. - Add HTML: The output generated by the
pixxfunction (which is typically HTML code) is added to the page.
- Find pixx Functions: The tool searches your project files for instances of the
- HTML Placement: To use this tool, you need to place a single
pixxfunction within a<script>tag in your HTML file.
- Options
- ignore: string[]
- Default
['node_modules/**', '**/pixx*']. - This option specifies an array of file patterns to exclude from processing.
- To ignore directories, append
/**to name. (e.g.node_modules/**). pixxFlowuses glob to ignore files.
- Default
- include: string[]
- Default
['**/*.html', '**/*.jsx', '**/*.tsx']. - This option specifies an array of file patterns to include in the processing.
pixxFlowuses glob to search for files.
- Default
- log: boolean
- Default
false. - This option controls whether debugging information is printed to the console.
- Default
- overwrite: boolean
- Default
false. - This option determines whether the tool overwrites the original file or creates a new file prefixed with
pixx-.- (e.g., myfile.jsx becomes pixx-myfile.jsx).
- If set to
true, the tool will overwrite the original file with the html output.
- Default
- ignore: string[]
// 1. Create a run file in root of directory. e.g. 'index.js'
// Add the following
import { pixxFlow } from 'pixx';
// simple
pixxFlow();
// or advanced
pixxFlow({
log: true,
include: ['**/*.html'],
ignore: ['node_modules/**', '**/pixx*'],
overwrite: false,
});
// 2. From your terminal, in the same directory as index.js file, run with node:
node index.jsPlugins
Vite-Plugin-Pixx
- Plugin to be used with Vite.
- pixxVitePlugin will intercept static pages, run
pixx, then return HTML to Vite server. - Pixx is not run on client, because it processes and transforms your code during development, leaving only the optimized output in HTML sent to client.
Pixxfunctions wil not be included in build, only the HTML.
- Options
- log: boolean
- Default
false. - This option controls whether debugging information is printed to the terminal.
- Default
- overwrite: boolean
- Default
false. - This option determines whether the tool overwrites the original file.
- If set to
true, the tool will overwrite the original file with HTML code and comment outpixxfunctions. Pixxfunction will not run again, once the code is commented out. This can speed up development when you have finalized images.
- Default
- isHTML: boolean
- comment out the
pixxfunction as HTML or JSX syntax. - (e.g. or {/_ JSX _/})
- comment out the
- log: boolean
// vite.config.js
import { defineConfig } from 'vite';
import { pixxVitePlugin } from 'pixx';
// https://vite.dev/config/
export default defineConfig({
plugins: [pixxVitePlugin({ log: true, overwrite: true })],
});