An image can make a page easier to understand, or it can become the slowest request on the page, shift content around and add nothing for people who cannot see it. I do not leave that choice until the end as if it were a decorative export step.
This portfolio serves project screenshots at several widths. The Apuntes ICO source, for example, is almost 2,000 pixels wide, but a project card does not always download that file. The component offers 640, 768, 960 and 1280 pixel variants through srcset, then tells the browser how much room the image will occupy with sizes. That was a frontend decision, not a cosmetic fix after chasing a score.
There is no single format or file size that works for every image. There is, however, a useful order for making the decision before publishing.
I start with the job the image has to do
Before opening a compression tool, I ask one simple question. What would be lost if this image did not load?
A professional portrait can build trust on a services page. A screenshot can show an interface that would take too long to describe. A background texture may change nothing when it disappears. Treating all three as the same kind of asset leads to bad decisions about alt text, loading priority and the weight each one deserves.
On this site’s project cards, the image sits inside a link that is hidden from screen readers, while the project title immediately follows as the real link. The thumbnail is a visual preview, not the only way to discover the project. That is why it has alt="". Repeating “image of Apuntes ICO” before the title would add noise, not information.
That is not a rule for every screenshot. On an individual project page, the large image is part of the explanation. At the moment its alt text is assembled as “Screenshot: [title]”. It is a valid baseline, but it does not explain what the screenshot lets someone see. If it shows a module search or an offline state, a more specific alternative would be more useful. That is something I would improve as I document each case study in more depth.
File weight is decided before export
Converting a very large image to WebP does not fix everything. If the source has an unnecessary crop, far more resolution than its slot needs, or tiny text nobody can read on a phone, the problem started earlier.
I first look at the space the image will occupy. A two-column thumbnail does not need the same source as a hero that fills most of a wide screen. Project cards in this site tell the browser their approximate width with this rule:
sizes="(min-width: 1200px) 552px,
(min-width: 768px) calc(50vw - 2.75rem),
calc(100vw - 2.5rem)"Those values are not decoration. They let the browser choose a sensible srcset candidate instead of downloading the biggest image just in case. If sizes claims an image fills the viewport when it actually sits in half a column, the optimisation is only half done.
I also check the mobile version. A wide desktop screenshot can be relevant to a case study and still be unreadable as a card. Sometimes the right move is a different crop, not shrinking the same file until it becomes tiny. That is a content and design choice before it is a format choice.
WebP and AVIF do not replace judgement
I use WebP for the portfolio screenshots because it works well for this kind of asset and keeps the static files straightforward. I would not turn that into a universal rule.
AVIF can save more bytes for some images, particularly photography, but I would check perceived quality and the support the real audience needs. SVG is a better fit for a logo or vector icon that should not be rasterised. PNG still makes sense when lossless output or transparency is needed, though I would not reach for it automatically for a photograph. JPEG can be a practical output when broad compatibility matters and the publishing pipeline is already set up for it.
Choosing a format is not about memorising a table. It means looking at the image at the size people will actually see. Heavy compression can make text inside a screenshot blurry. Turning an icon into WebP can make it larger than the original SVG. Serving a photo as PNG can spend bytes nobody will notice.
When I need to support different formats, I would use <picture> with alternatives and a final img. I would not add that layer to every image just because it sounds more advanced, though. If the current system already produces small WebP variants and looks good on real devices, another change may have more impact.
Reserving space stops the page from jumping
Image loading is not only about time. When the browser does not know how much space an image needs, it can paint text and buttons first, then move them once the image arrives. That is frustrating, especially when someone was about to tap something.
That is why images in the project system receive width and height from their real dimensions. CSS can still make them fluid, while those attributes give the browser the ratio it needs to reserve space. web.dev’s CLS guide identifies images without dimensions as a common layout-shift cause and recommends declaring dimensions or reserving space with aspect-ratio.
I would not copy dimensions by eye. If a file is 1911 by 1032, those values should accompany variants with the same crop. If mobile uses a differently proportioned image, it is another asset and needs its own reserved space.
loading="lazy" does not belong on the important image
Lazy loading is useful for images further down the page that a visitor may never reach. The portfolio cards use it because many thumbnails are below the fold. Delaying those requests avoids fetching every image at once.
I would not do that to the main image on a project page. That cover uses loading="eager" and fetchpriority="high" because it is part of what the visitor sees first. Marking it as lazy can delay the very resource that makes the page feel loaded.
The boundary is not “everything at the top” or “everything that looks nice”. I open the page on mobile and desktop, find the important visual element and check when the browser requests it. An image hidden behind a very large header is not automatically a priority just because it appears early in the HTML.
Alt text describes a function, not a keyword
Alt text often enters an SEO conversation too soon. Before it has anything to do with search, it needs to help someone who cannot see the image or has chosen not to load it.
Useful alt text changes with context. If an infographic contains a figure missing from the paragraph, that figure needs to be present in nearby text or in the alternative. If a photo supports a story without adding necessary information, a short description is enough. If the image is decorative, alt="" lets a screen reader skip it.
MDN’s reference for the img element describes alt text as a textual replacement when an image cannot be displayed. That is why phrases such as “image of”, file names and keyword lists do not solve the problem. Neither does an exhaustive description of every pixel.
For a case study, I would prefer “Apuntes ICO search screen with results grouped by module” over “Apuntes ICO screenshot”. It explains what the image demonstrates and fits the text around it. For a card where the name, summary and link already do that work, I would keep alt="".
SEO needs context, not filler
Google can discover images through many signals, but I would not turn alt into a keyword field. The file name, nearby copy, a figcaption when it adds context, the page where the image appears, and the quality of the asset work together more naturally than a forced phrase.
For a project image, I want the URL and surrounding content to establish what the project is, which problem it addressed and what the screen shows. That is more coherent than trying to rank an isolated screenshot with ten terms crammed into its attribute.
I also separate the image used when a page is shared on social media from images inside an article. The first needs the right crop and dimensions for a social card. The second needs to match the reading flow and content width. Reusing one file for everything is convenient, but it is not always the best choice.
The review ends in production
Before accepting an image, I open the published page with a simulated mobile connection and inspect the Network panel. I check which file the browser selected, its weight, whether a larger variant than necessary was requested, and whether loading causes any shifts.
Then I try the page without images or with a screen reader. Not to claim an accessibility audit, but to check whether the content keeps its meaning. If removing an image removes the only explanation of an interface, the text needs to carry that information. If a decorative thumbnail gets announced three times, the noise needs removing.
The goal is not a perfect gallery or shrinking every file as far as possible. It is serving every image for a reason. That connects performance, accessibility and SEO through a visible decision that affects every visit. In my review before publishing a website, I cover the other checks I make when a project leaves my local machine.