Make WordPress Core

Opened 5 years ago

Last modified 5 years ago

#46885 assigned enhancement

Improvements/Issues with srcsets, additions to wp_calculate_image_srcset

Reported by: pinktank's profile pinktank Owned by: joemcgill's profile joemcgill
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 5.1
Component: Media Keywords:
Focuses: Cc:

Description

Hello All,
I had a few issues that I've also found references to online without fixes. From the most basic to (slightly) more complicated.

1) Include a way to not include the original src in srcset. When you are developing a theme there are many reasons you don't want to the original src. The most obvious is that the original src can be uncompressed/unoptimized for better derivatives, or simply because editors upload whatever they have. You could also be using a lq-placeholder replacement method where you load a low resolution image in the src for better UX and would like that to go first in the srcset load order.

2) There is something strange with the way the srcset is ordered. In a current setup I'm getting original first(for ios 8 bug), followed by 360 wide, 180 wide, 720wide, 1280wide. Not sure why the 360 is swapped with 180.

2) Accept an array of named image sizes to create custom srcsets instead of generating all registered image sizes.

Thanks.

Change History (5)

#1 @joemcgill
5 years ago

Hi @pinktank,

Welcome to Trac and thanks for sharing your ideas of what you'd like to see improved!

Let me try to respond to each of these requests separately.

1. Include a way to not include the original src in srcset.

This could currently be accomplished by adding a filter to the wp_calculate_image_srcset hook, which is documented here. That filter has access to the src URL, so you could loop through the source list and unset the orginal source from the list at that point, before the srcset attribute is created.

2. There is something strange with the way the srcset is ordered.

This is actually intentional behavior. Browsers do not pay any attention to the order of sources in a srcset list. However, when this feature was shipped, we chose to list the original src first in order to work around a bug in iOS 8 which caused the first source to always be selected. See: https://core.trac.wordpress.org/ticket/35030.

3. Accept an array of named image sizes to create custom srcsets

To limit the sources available in a srcset attribute, this could also be accomplished via the wp_calculate_image_srcset, by passing the source list through some kind of white list, though I would recommend against this, as it's advantageous to include as many options for browsers as is reasonable. However, if the goal here is to reduce the number of files that are created when an image is uploaded, that is something that happens separately from the srcset generation and is something we would want to handle with more use cases in mind.

#2 follow-up: @pinktank
5 years ago

Hi @joemcgill,
Thanks for responding so quickly.
1. I did see the filter but my php and understanding of core is not up to snuff to write that loop (I parsed the output string with the comma as a needle instead as a temporary hack o_o).

I suspected that others would find helpful adding a $src_first parameter to the the function. It would just plug into line 1175 as if($is_src && $src_first). You could plug it in earlier to skip a conditional but this seemed more semantically correct.

A more graceful option would be to have the largest derivative first instead of the original src. This would still address the ios8 bug while providing a properly compressed image for better loading times and not freak out pagespeed.

Alternatively somebody could add a filter snippet to the documentation, that maybe me

2. As I mentioned in the paranthesis, I know why the src comes first, I didn't understand why the second smallest came before the the smallest in 360,180,720 rather than 180,360,720.

3. I had mentioned this for the off cases where people use filters with certain sizing options to change the image and for those who want to load 2N versions only to avoid pixel 1px shift due to rounding issues. The wp_image_matches_ratio is –thankfully– forgiving of 1px but some applications could use exact doubles. Again though this was the most edge-case of my recommendations, not a pressing issue.

cheers

Last edited 5 years ago by pinktank (previous) (diff)

#3 in reply to: ↑ 2 @joemcgill
5 years ago

  • Owner set to joemcgill
  • Status changed from new to assigned

Replying to pinktank:

Hi @joemcgill,
Thanks for responding so quickly.

You're very welcome :)

1. I did see the filter but my php and understanding of core is not up to snuff to write that loop (I parsed the output string with the comma as a needle instead as a temporary hack o_o).

Alternatively somebody could add a filter snippet to the documentation.

I think that adding an example for this to the documentation website is a great idea.

2. As I mentioned in the paranthesis, I know why the src comes first, I didn't understand why the second smallest came before the the smallest in 360,180,720 rather than 180,360,720.

Apologies for missing your parenthetical comment. I'd say it is definitely unexpected that you would be seeing the rest of the sources listed out of order, but as I mentioned, it shouldn't make any difference to browsers, so is not something we would probably prioritize fixing at the moment.

3. I had mentioned this for the off cases where people use filters with certain sizing options to change the image and for those who want to load 2N versions only to avoid pixel 1px shift due to rounding issues. The wp_image_matches_ratio is –thankfully– forgiving of 1px but some applications could use exact doubles. Again though this was the most edge-case of my recommendations, not a pressing issue.

We already have #32437 that covers the potential duplication issue, if I'm understanding correctly. Otherwise, it's still a bit unclear to me what use cases you are trying to solve for with the third item.

#4 @pinktank
5 years ago

If you don't mind helping with the ??? in the code below, I can add it to the documentation as a comment.

*oops, I borked a double loop for some reason

// Parse through array to unset the original src
foreach($sources as $element_width => $element_source) {
        if($element_source == ???){
            unset($sources[$element_width]);
        } 
}
// Move largest derivative to first position.
$largest_img_key = max(array_keys($sources));
$sources = array( $largest_img_key => $sources[$largest_img_key]) + $sources;

On number 3, what I mean is if you have an image that is off by one px in image ratio due to rounding, this causes the image to jiggle in resizes and get blurry in conditions where the aspect ratio is determined by the original width/height. If a developer could disable the 1px error margin or specify which specific image sizes they want to use, they can choose to only show images that are resized in multiples of 2, say 180w 360w 720w to avoid potential 1px shifts in the dom. I suppose this can again be handled by a loop per above though via white listing, could even be done by checking the modulo of original src / resized src.

Version 2, edited 5 years ago by pinktank (previous) (next) (diff)

#5 @pinktank
5 years ago

I gave it a shot, no idea if this is anywhere near correct because I am not that great with php.


function filter_wp_calculate_image_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id ) { 
        // Parse through array to unset the original src
        foreach($sources as $element_width => $element_source) {
                if($element_source == $image_src ){
                    unset($sources[$element_width]);
                } 
        }
        
        // Move largest derivative to first position.
        $largest_img_key = max(array_keys($sources));
        $sources = array( $largest_img_key => $sources[$largest_img_key]) + $sources; 
        
        //Return modified sources
        return $sources; 
}; 
         
// add the filter 
add_filter( 'wp_calculate_image_srcset', 'filter_wp_calculate_image_srcset', 10, 5 ); 

Last edited 5 years ago by pinktank (previous) (diff)
Note: See TracTickets for help on using tickets.