#Hand-optimized images and Cumulative Layout Shift

5 messages · Page 1 of 1 (latest)

torpid basin
#

Hi - thanks for an amazing product.

I'm a newcomer and have about a thousand screenshots I need to import into a group of 9 sites I'm building. The screenshots respond very well to lossless compression. For example, I'll paste a 1309 x 982 image below that I can compress down to 18 KB using lossless compression.

With 1000 images, I'd like to avoid having to input the height and width manually to avoid cumulative layout shift. Is there a way to use the Image component but have it not modify the image file? For example, could I hack the Default Image Service so it doesn't modify the image file?

My current best idea is to import the images and then use the properties of the imported images to avoid cumulative layout shift. Here's my best draft so far:

import FidelityBalance from './img/outline/FidelityBalance.png';

<img src={FidelityBalance.src} width={FidelityBalance.width} height={FidelityBalance.height} loading="lazy" decoding="async" alt="The balance sheet of Fidelity Fiduciary Bank.">
#

Above is an example of the type of graphics I'm dealing with. It is 1309 x 982 and was converted via Google's webp tool using ./cwebp.exe -mt -lossless -q 100 -z 8 epicpen_2024-02-06_20-31-51.png -o sharex.webp It's now only 18 KB! I'm concerned that further format conversion by Sharp would only lower the quality and raise the file size.

#

I'm just wondering what people think best practices would be. If the above idea of using properties of imported images is solid, I'm hoping I could pack it up into a component to keep my MDX files more readable. It would be predicated on my ability to figure out dynamically imported images, though.

torpid basin
#

Hi wonderful support team. I'm back at my desk and working on this again. I'm going to try to code the component mentioned above. I'll likely be slow, though, as I'm a econ/finance teacher as indicated by my examples, above, and only started teaching myself JavaScript in November. If anyone has any tips, I'd love to hear them!

torpid basin
#

Got it to work. Interestingly, you handle dynamic imports differently with the <img> tag than with the <Image> component. Vite's import.meta.glob function returns a promise. The <Image> component accepts the promise, but the <img> tag requires an "await" on it.

Both are illustrated in the following demo code:

---
import type { ImageMetadata } from 'astro';
import { Image } from 'astro:assets';
interface Props {
   path: string;
   alt: string;
}

const { path, alt} = Astro.props;
const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/*.{jpeg,jpg,png,gif}');
if (!images[path]) throw new Error(`"${imagePath}" does not exist in glob: "src/assets/*.{jpeg,jpg,png,gif}"`);

const picPromise = images[path]();
const picWait = await images[path]();
const picDef = picWait.default
console.log(picWait);
---

<h2>Using &lt;img> with dymamic image imports </h2>

<img src={picDef.src} width={picDef.width} height={picDef.height} alt={alt} />

<h2>Using &lt;Image> with dymamic image imports </h2>

<Image src={picPromise} alt={alt} />