Deliver Assets Like a Pro

Contribute to user experience quality through great performance thanks to well-optimized assets
css for designers design dev collaboration dev driven centric design

A misconception persists, that performance is only about backend programming/devops. Nothing could be more wrong. Performance starts with good planning and ends with the right, well-optimized assets.

Since it became a deciding factor for usabilityuser experience, search engines, keeping certain standards for assets delivery is a must.

Introduction

Before diving into assets delivery do’s and dont’s, please consider that part of the dev work is being done in the IDE or terminal like environments, where keyboard is used predominantly, and sometimes user interface is nothing more than a command line.

Don’t use spaces

Though most OS can handle file names with spaces, browsers do not. Most browsers encode space as %20, creating problem with linking, or using such URLs.

Don’t use special characters

For the same reason, omit special charaters others than hyphens, underscores and at sign. Adding a special character could prevent file from rendering properly in the browser or to not load at all.

Though periods are not off limits, it is not recommendable to not use them, since they differentiate a file name from a file extension.

Use lowercase letters

Most web server OS are case sensitive, and filename.jpeg, could be a totally different file then Filename.jpeg. Keep that in mind.

Keep filenames short

Even uhough an URL can have as much as 2,000 characters, having a very long filename, can make them inoperable in the longer run.

Make filenames descriptive

When delivering a design, you should always assume, that a developer who will be implementing the design, is detached from the bigger picture, and needs to be guided. The more intuitive and descriptive your filenames will be, the easier and faster his/her work shall be.

Consider these examples:

T56ghI9bx_final_v2_rev_johonny.jpeg
about_us-hero_banner@2x.jpeg

Example #2 clearly tries to guide developer where exactly the file should go, and also shows its pixel density, in other words its name is informing developer, that this file is retina-ready.

Use hyphens and underscores

Let’s go back to our example:

about_us-hero_banner@2x.jpeg

This is next level of complexity within realm of creating filenames.

Please, take a closer look, the showcased above filename has both underscores (_) as well as hyphens (-).

They are both placed purposefully.

Underscores are a join character, meaning that two words connceted with them will be considered by any system as one word, like about_us or hero_banner.

Hypens for instance, are a separation (punctuation) character, meaning that two words connected with them will be considered by any system as two separate words, like file-name or johnny-doe.

You can test it out yourself. Try to highlight the words inside the filename. In order to do so, please double-click on the first part of the filename, and you’ll be able to highlight first individual word – about_us – of this compound filename.

about_us-hero_banner-no_filter@2x.jpeg

Thanks to such differentiation, a developer should know, what is the exact purpose of the file, and where exactly it should go and finally how it should be treated.

On top of that, this punctuation thingy, makes a bulk-actions like highlighting, renaming or any other actions easier in the IDE/command-line environment.

Finally, separating words within the filename by using hypens enables and deepens search engine optimization.

Add file dimensions

Once again, let’s go back to our example, but this time let’s add another feature – file dimensions in pixels:

about_us-hero_banner-1920x768@2x.jpeg

Adding file dimensions is very useful to recognize, which file is should be rendered/processed by the browser. With addition of pixel density (@1x @2x suffixes), developer can easily build media queries or decide on image-set() functions, which are a cornerstones of responsive web design.

Add versioning if applicable

It is also a good practice to add a versioning suffix, if it helps recognizing the purpose of the file. Like in case of dark mode or language versions.

Dark mode has gained a lot of traction recently. Like Apple, for instance, has added dark mode to its iOS and MacOS operating systems. Windows and Google are not far behind.

Hence it has gradually became a standard in giving better user experience.

Same for the internationalization of products or apps. Having different language versions of the interface becomes a necessity.

about_us-hero_banner-dark-en-1920x768@2x.jpeg
about_us-hero_banner-light-de-1920x768@2x.jpeg

With such compound filenames a developer will immediately know, how to work a particular asset.

Optimizing file size

Every single image optimization article would state it, that keeping your files well-optimized and compressed is a best practice. Both because of the performance as well as search engine optimization.

Yet, optimization process is way too often overlooked. So how to approach the problem?

You can use special software, like ImageOptim on Mac, Pinga or Pingo on Windows or Squoosh on both. With these tools, asset size reduction should be substantial, yet quality of the images should be untouched or lowered to point that is not visible to an eye of a non-designer.

Let me give you an example of what kind of saving are we talking about.

A standard, a not very busy JPEG photo, saved with standard sRGB profile in Photoshop, should weight approx. 1.5-1.8MB. After optimizing the asset, the filesize should drop to approx. 200-300kB. In the end, creating a situation, where browser could render up to 9x times more images like that in the same time, rather one without optimizing it.

I’m going to repeat that so it sinks better – 9x times.

Adaptive Media Loading

Most certainly, it is not designer’s task to decide upon the architecture of a website, but it is designer’s duty to deliver best possible user experience.

Adaptive media loading is a web performance pattern, where sites, not just only respond to rendering based on screen size – they adapt based on actual device hardware.

In a world with widely varying device capabilities, a one-size-fits-all experience may not always work. There are many use cases for such solutions.

While conditionally serving different resources based on device capabilities, might be a valuable strategy. First you have to know, that it is an option.

Let me give you an example.

Think about background-video or a hero-section rendered for a user with slow connection – is a recipe for disaster. With adaptive media loading, it’s possible to not serve a ‘heavy’ video or image at all and swap it with 80kB JPEG substitute. Which in the end, seems to be a better idea, than tanking someone’s browser and not delivering the experience at all.

The Network Information API automatically classifies the users into four buckets – 4G, 3G, 2G, and slow 2G – where 4G is the fastest and 2G is the slowest.

// returns '4g', '3g', '2g' or 'slow-2g'
var effectiveType = NetworkInformation.effectiveType;

Thanks to such solution, you can start determining the network speeds that the users are experiencing and divide them into user experience buckets.

In React framework, this effect can be achieved with client hints on the server and react-adaptive-hooks on the client.

image-set() function

The image-set() CSS function, is a method of letting the browser pick the most appropriate image from a given set, primarily for high pixel density screens. So in principle, very similar thing as adaptive loading, but with CSS.

image-set() function delivers the most appropriate image resolution for a user’s device based on its specs.

Check out an example:

.section-hero--about-us {
    background-image: -webkit-image-set(
        url(about_us-hero_banner-dark-en-1920x768@1x.jpeg") 1x,
        url("about_us-hero_banner-dark-en-1920x768@2x.jpeg") 2x);
    background-image: image-set(
        url(about_us-hero_banner-dark-en-1920x768@1x.jpeg") 1x,
        url("about_us-hero_banner-dark-en-1920x768@2x.jpeg") 2x);
}

Go to CSS Functions section to learn more about it.

Consider using WebP & AVIF filetypes

WebP

The WebP saga has finally ending  when Apple finally added support for WebP in Safari 14. So, after many years of discussions and debates – as of September 2020 – WebP is supported in all modern browsers.

WebP is a modern image format, that provides superior lossless and lossy compression for images on the web, created by Google in September 2010 (yes, we waited 10 years).

It has to be pointed out that, from a designer’s perspective, Sketch is natively supporting WebP. Moreover, WebP assets can be exported from Photoshop using a WebP plugin for Adobe Photoshop or through other options. If you want to dive deeper into this topic, check the Google Developers Documentation.

AVIF

AVIF is image format derived from the keyframes of AVI video format, released on February 2019. It supports lossy and lossless compression, animation, lossy alpha channel, and can handle sharp lines, and even more importantly, can handle solid colors.

It is so well-thought through, that in some cases, assets in AVIF format can perform (size-wise) even better than large SVGs (sic!). More importantly, it seems AVIF‘s saga will be shorter then WebP‘s, since Safari will support it in its 16.1 version. Thus, the only not supported browser, will remain… the Microsoft Edge.

Use cases

It’s imporatant to remember, that both WebP and AVIF files can be served with the <picture> element and a JPEG fallback if needed.

<picture>
    <source srcset="img/image.webp" type="image/webp">
    <source srcset="img/image.jpg" type="image/jpeg"> 
    <img src="img/image.jpg" alt="It works!">
</picture>

or within image-set() function.

.container {
    background-image: image-set(
        "image.avif" type("image/avif"),
        "image.jpg" type("image/jpeg")
    );
}

And remember, you can also apply @media conditions if needed.

<picture>
<source
    sizes="(max-width: 1000px) 100vw, 1000px"
    srcset="
        /image-1920x1080@1x.avif 1920w,
        /image-1280x720@1x.avif  1280w,
        /image-640x360@1x.avif    640w,
        /image-320x180@1x.avif    320w"
    type="image/avif"
/>
<source
    sizes="(max-width: 1000px) 100vw, 1000px"
    srcset="
        /image-1920x1080@1x.webp 1920w,
        /image-1280x720@1x.webp  1280w,
        /image-640x360@1x.webp    640w,
        /image-320x180@1x.webp    320w"
    type="image/webp"
/>
<source
    sizes="(max-width: 1000px) 100vw, 1000px"
    srcset="
        /image-1920x1080@1x.jpeg 1920w,
        /image-1280x720@1x.jpeg  1280w,
        /image-640x360@1x.jpeg    640w,
        /image-320x180@1x.jpeg    320w"
    type="image/jpeg"
/>
    <img src="fallback-image.jpeg" alt="It works!">
</picture>
No one is always right

I use feedback to improve UI Crux Platform. If you noticed a mistake, please report it.