Tag: css

  • Responsive Background Images Part 2: Harnessing element() For The Future

    In the first part, Responsive Background Images With or Without image-set(): The Proven Way looked at the current way to make background images responsive. It is not without it’s down sides. I will discuss these and present a new way to use an img tag, or any tag, as a responsive – and even dynamic and animated – background for any element.

    image-set() Con: Existing Content Management System Blocks/Extensions

    Block elements and extensions as well as built-in features within existing Content Management Systems (CMS) are all designed to use previous and current generation CSS. Image-set() is not meant as a translation of the img tag’s srcset and sizes attributes. Media queries balloon out the size of CSS and are difficult to update and control. Extending existing blocks and extensions don’t always catch every case and many third-party-developed extensions may not even be modifiable.

    Many people will continue to use the existing elements and blocks they are familiar with. This means many existing sections won’t be able to make use of new ways to make backgrounds responsive.

    Responsive Background Images In The Future: The element() Function

    A new CSS function will allow developers to use an old and familiar pattern to easily provide background images that respond and update to size of the viewport of container. Additionally, this function allows the use of more than just images. Animations, dynamically updating content and videos can also be rendered as the background of an element.

    The element() CSS function allows you to use any element on the page as the background of any other element. That means images that response responsively to the viewport or container queries. That also means any element with any content – text, images/canvas, video, or dynamically updated and animated content.

    This function also allows developers to bypass existing CSS generations and implement an entirely new background image using an img tag, even a tag that already exists within the site – such as a featured or headline image.

    element() Browser Support: Just Beginning

    As of August 2024, the only browser that supports the element() function is Firefox. Why so little support? This is a new function, part of the CSS Images Modules Level 4, and there are still some issues to be addressed. Other browsers will start supporting it as the issues are ironed out.

    Here is an example (as of August 2024, this will only work in Firefox):

    Close-up photo of various sticky notes showing various web layout designs next to some pens with a keyboard to the right, above them. They are on a dark brown wooden desk.
    HTML
    <div id="element-background-test"></div>
    <figure id="element-background-test-image-wrapper">
      <img id="element-background-test-image" ... />
    </figure>
    <style>
    #element-background-test {
        background: -moz-element(#element-background-test-image) no-repeat;
        background: element(#element-background-test-image) no-repeat;
        background-position: center center;
        background-size: cover;
        min-height: 80vh;
        border: 4px solid black;
    }
    #element-background-test-image-wrapper {
        height: 0;
        overflow: hidden;
    }
    </style>

    Granted, this is rather winded, but not as much as when using CSS media queries. The img tag can more easily be generated by most CMSes while I have not seen any that generate media queries.

    You can mimic this today, in all browsers, using a stack.

    Check back here for a link to part 3.

  • Responsive Background Images With or Without image-set(): The Proven Way

    Responsive Background Images With or Without image-set(): The Proven Way

    Do a search for “responsive background images” on the web. Go on and do the search, I’ll wait.

    Oh, you’re back. Notice anything strange? For example, nobody can decide on what this means, how to do it, or even how to do it easily? You’re not alone. Fact is, the vast majority of sites have incorrect answers for generating responsive background images the way the img tag with srcset and sizes attributes work. This post puts it all to rest with the definitive answer a few mention as an “option” rather than the answer. Let’s start with a definition.

    What are responsive background images?

    There is some clear confusion over what exactly constitutes a responsive background image. Many declare them, simply, as the act of using a background image and that they are inherently responsive. Others define them as the filling of a given space by setting the background-size property to cover or contain. This inconsistency makes the entire idea confusing; They define the background styling an HTML element but not making the background responsive.

    Responsive background images are to background images what the srcset and sizes attributes are to the img tag. Mozilla’s web development docs define that as

    images that work well on devices with widely differing screen sizes, resolutions, and other such features

    MDN

    In other words – just adding a background image to an element or even having it fill a given space does not constitute a responsive background image… but it does contribute to it.

    Image-Set() Is For Pixel Density & Type Support, Not Responsiveness

    Many posts will erroneously tell you to use image-set() to make background images responsive. This is misleading at best. image-set() was not meant to be used to provide different images at differing device screen widths. It is meant to provide different images based on the pixel density of the device. I already know what some are going to say…

    But pixel density does fit with device size!

    Unfortunately, you would be wrong. Using pixel density (such as DPI or 1x, 2x, 3x, etc) as a way to target a mobile device vs a tablet vs a desktop won’t work. While most mobile phones do use higher pixel density than most desktop monitors, others do as well. A number of tablets also have higher pixel density and Apple’s high DPI Retina display is (or was) available on their desktop machines as well. Just because the vast majority of the rest of the industry did not go in that direction does not mean you should simply assume only certain devices make use.

    What does this all mean? Using image-set() by itself as a way to define device-specific images is not likely to get the results you expect and does not mean your background images are responsive. The following code will not hit the majority of cases you would expect to hit when setting different sized images for mobile devices, tablets, and desktops:

    CSS
    // Don't use this to target mobile, tablet, or desktop devices
    .some-element {
      background-image: image-set(
        url("/path/to/regular-image.webp") 1x,
        url("/path/to/regular-image.2x.webp") 2x
      );
    }

    Responsive Background Images Revealed: The Proven & Tested Solution

    While various articles and StackOverflow (SO) question answers may tell you to multiple background-image properties (possibly using some JavaScript-set class), use image-set() by itself, or some other JavaScript (JS) to swap-out images, DON’T. They all have huge downsides. Everything from loading multiple versions of image, which uses even more bandwidth and loading a single image, to delaying the loading of images to increasing the amount of blocking scripts unnecessarily. There is a much better, pure CSS way to handle responsive background images.

    The tested and proven way is to use media queries. Yep, I said it. You may not like it, but as of 2024, it’s the primary way to generate responsive background images that target different device widths the your breakpoints and img tags do. Here is the tested and proven solution, JS involved:

    CSS
    /* Use your own breakpoints or, better yet, generate
       this dynamically within your CMS (such as through
       an extension/plugin or theme):
     */
    
    // Mobile first! Up to 767px:
    .some-element {
      background-image: url("/path/to/image-767.webp");
    }
    
    // Tablet (768px to 1023px)
    @media (min-width: 768px) {
      .some-element {
        background-image: url("/path/to/image-1023.webp");
      }
    }
    
    // Smaller laptops and tablet in landscape (1024px to 1279px)
    @media (min-width: 1024px) {
      .some-element {
        background-image: url("/path/to/image-1279.webp");
      }
    }
    
    // Standard laptops and desktops FULL HD (1280px and up)
    @media (min-width: 1280px) {
      .some-element {
        background-image: url("/path/to/image-2048.webp");
      }
    }
    
    // You could include more queries if you are targeting
    // 2K, 4K, 8K screens, etc.

    The code above will allow your site to display responsive background images to varying device sizes while reducing bandwidth for smaller devices. You can even use art direction. For instance, if your desktop layout has the element only needed in 500px wide background, you can set your larger display to only download the smaller size image. It is the img tag equivalent of:

    HTML
    <img
        src="/path/to/image-767.webp"
        srcset="/path/to/image-768.webp 767w, /path/to/image-1024.webp 1023w, /path/to/image-1280.webp 1279w, /path/to/image-2048.webp 1280w"
        sizes="100vw">

    You can even use image-set() in addition to the media queries to target both device sizes as well as devices with higher pixel density/DPI/PPI. Performance analyzers like Lighthouse’s Pagespeed Insights will also thank you for taking the responsive route for background images.

    Below is an example:

    Responsive Background Images: Alternative Ways

    In part 2 you learn a new way to achieve responsive background images without using the potentially three, four, five or more media queries.

  • IMG Sizes Attribute Explained: Boosting Image Optimization

    IMG Sizes Attribute Explained: Boosting Image Optimization

    Your template’s design layout often has images that do not fill the entire width of all devices your visitors may be using. CSS’s grid layouts and flexbox layouts allow even greater control over the design of websites. Using img sizes attribute to hint to the browser the maximum size the image will render at allows developers to reduce bandwidth and fit images to their design rather than the device’s width.

    A number of articles discussing this idea, or at least something similar to it, talk about art direction but this idea is different. Most suggest wrapping the img element with a picture element with customized source elements. This allows you do do things like replace the image based on the device size, but requires duplicating the image URL in order to use it to simply define a maximum image size for the design based on device width. This is overkill for simple control of the image resolution.

    Content Management Systems (CMS) and blog software including Drupal modules, WordPress and it’s popular plugins have a default of using the device width. They have no understanding of the design’s layout. This is problematic as not all images would benefit from it and some, like icons and logos, may end up causing browsers to download the wrong resolution and leads to images that are either too large or too small for the space the image fills. For most CMSes, the best solution is to simply define them all to be based on the width of the device since it’s extremely rare that images placed on the site would exceed that resolution.

    For example, here is an image grid where the img sizes attribute is set to 100px:

    You can see the images are all low resolution, even on a desktop display. Now let’s set the img sizes attribute to 100vw (100% the viewport width):

    You can see that the images are now crisp and easy to view… but there’s still a problem. They are downloading very large images even though their width is 33% of the screen… minus the padding as well. The browser is downloading images far larger than it needs to. This uses more bandwidth than needed and is slow on mobile devices with slower wireless internet connections.

    Customize The IMG sizes Attribute For Each Image Element

    Each image element tag needs the sizes attribute added (or replaced) with the customized version. In some cases this can be tedious, but there are things you can do to make the process a little easier on yourself.

    Preset, Named img sizes Attribute Values

    One way to achieve this is to create a way to store predefined sizes attributes. Make it easier by giving them unique, simple names. For instance, consider a design that has a section that will show up to 5 columns on a 2K or greater screen, 4 columns on a 1920px desktop screen, 2 columns on a tablet, and a single column mobile phones. Here is an example: (max-width: 640px) 100vw, (max-width: 1024px) 50vw, (max-width: 1920px) 25vw, 20vw.

    You could call this value “5-column” with the value set to what you would like the img sizes attribute to be, and embed that into all of the img sizes attribute. Instead of trying to remember the value of sizes or copying and pasting it over and over again, you simply tell it to include the 5-column named value. This also has the additional benefit of being able to change many images’ sizes attribute at the same time if that section of the design were to change in the future.

    Additional img sizes Considerations

    Lightbox & Other Full-screen Modal Image/Gallery Scripts

    These scripts take an existing image and “blow it up” to display it full-screen. This is to make images that may be hard to see large enough that the viewer can recognize subjects and possibly text within the image. However, altering the img sizes attribute can potentially be problematic. For instance, your desktop design calls for a 300 pixel (px) wide display and the lightbox script full-screens that image. They appear horribly artifacted/pixelated when displayed at 300px wide on a 1920px wide screen. It would appear even worse on a 2K or 4K monitor. You want to make sure the img tag used by the enlargement script does not simply copy the sizes attribute you have assigned on the site.

    How to ensure browsers will download the full-screen version of images when they are enlarged? This is a tricky answer. There are a number of different lightbox and modal image enlargement scripts. Some are forks of existing scripts but and many are independently developed and lack the same features. In general, you want to make sure to have a custom sizes attribute available in this case. I don’t see any of the major scripts’ documentation showing any data-sizes attribute or similar, so you will likely need to hook the modal’s open event and swap out the sizes attribute yourself.