Skip to content

Instantly share code, notes, and snippets.

@williammalo williammalo/README.md forked from 140bytes/LICENSE.txt
Last active Mar 1, 2019

Embed
What would you like to do?
Responsive image loading in 199bytes (minification help needed)

This function loops through all images on the page, and serves the appropriately sized image file from a list in a data attribute.

example link: http://total.maloweb.com/responsive

example html:

<img src="default.png" data-widths="400,600,800,1023" data-srcsuffix="-foo.png">

example javascript:

onload=onresize=function(){
    respImg("data-widths","data-srcsuffix")
}

example filenames:

400-foo.png
600-foo.png
800-foo.png
1023-foo.png
function(x,y, //x:attribute name for widths, y:attribute name for suffix
a,c,d,b,e,f,g){ //placeholders
for(d in f=document.images)if(a=f[d],g=a.getAttribute(x)){ //for every image with a width list
b=g.split(","); //split width list into array
for(c=b.length;c--;) //for every width
if(e=b[0],b[c]<a.offsetWidth){ //set lowest width as default(e), when the loop encounters a width smaller than the image:
e=b[c+1]||b[c];break} //set e to one width higher, or the highest width available
a.src=e+a.getAttribute(y) //set src attribute to the right width
}
}
function(x,y,a,c,d,b,e,f,g){for(d in f=document.images)if(a=f[d],g=a.getAttribute(x)){b=g.split(",");for(c=b.length;c--;)if(e=b[0],b[c]<a.offsetWidth){e=b[c+1]||b[c];break}a.src=e+a.getAttribute(y)}}
{
"name": "respImg",
"description": "Responsive image loading",
"keywords": [
"responsive",
"conditional",
"image",
"loading"
]
}
<!DOCTYPE html>
<title>Foo</title>
<a href="http://total.maloweb.com/responsive">click link for example</a>
@atk

This comment has been minimized.

Copy link

atk commented Jul 10, 2012

First minification attempt (untested for correct working, only tested for errors, 165bytes):

function(x,y,a,d,e,f,g){for(d in f=document.images)a=f[d],e=a.offsetWidth,(a[g='getAttribute']&&a[g](x)||g).replace(/\d+/g,function(c){+c<e&&(a.src=c+a[g](y),e=0)})}
@atk

This comment has been minimized.

Copy link

atk commented Jul 10, 2012

Reused variable (163bytes):

function(x,y,d,e,f,g){for(d in f=document.images)d=f[d],e=d.offsetWidth,(d[g='getAttribute']&&d[g](x)||g).replace(/\d+/g,function(c){+c<e&&(d.src=c+d[g](y),e=0)})}
@atk

This comment has been minimized.

Copy link

atk commented Jul 10, 2012

Reused e for testing if f[d] is actually image element (instead of testing for d.getAttribute, 160bytes):

function(x,y,d,e,f,g){for(d in f=document.images)d=f[d],e=d.offsetWidth,(e&&d[g='getAttribute'](x)||g).replace(/\d+/g,function(c){+c<e&&(d.src=c+d[g](y),e=0)})}

Now I'm out of ideas how to minimize this further.

@williammalo

This comment has been minimized.

Copy link
Owner Author

williammalo commented Jul 10, 2012

@atk your functions don't work, they load the lowest resolution image...

@atk

This comment has been minimized.

Copy link

atk commented Jul 10, 2012

Oh, forgot to tell you that you'll have to reverse the order of resolutions in the data attribute. My fault.

@williammalo

This comment has been minimized.

Copy link
Owner Author

williammalo commented Jul 10, 2012

@atk I used your tips to make my function a bit smaller 189bytes

function(x,y,a,c,d,e,f,g){for(d in f=document.images)if(d=f[d],g=d[a="getAttribute"](x)){g=g.split(",");for(c=g.length;c--;)if(e=g[0],g[c]<d.offsetWidth)e=g[c+1]||g[c],c=0;d.src=e+d[a](y)}}

your's still doesn't work if I reverse the widths, it always shows one resolution lower.

@atk

This comment has been minimized.

Copy link

atk commented Jul 10, 2012

OK, will have to look into this later. This will probably require to revert the resolution numbers to the former order. Do I get it right in that case that it should always be the resolution 1 notch above (and not below, like it is now) the current one?

Update: made a mix of both of our codes (168bytes):

function(x,y,d,e,f,g,h){for(d in f=document.images)for(e in h=((d=f[d])[g='getAttribute']&&(d[g](x)||'').split(',')))if(h[e]<d.offsetWidth){d.src=h[e+1]+d[g](y);break}}

Another update: rethought my regex version (161bytes):

function(x,y,d,e,f,g){for(d in f=document.images)d=f[d],e=d.offsetWidth,(e&&d[g='getAttribute'](x)||g).replace(/\d+/g,function(c){c>e&&(d.src=c+d[g](y),e=1/0)})}

Last update (depending on the former one): sneaky abuse of string value comparison (159bytes):

function(x,y,d,e,f,g){for(d in f=document.images)d=f[d],e=d.offsetWidth,(e&&d[g='getAttribute'](x)||g).replace(/\d+/g,function(c){c>e&&(d.src=c+d[g](y),e=g)})}
@williammalo

This comment has been minimized.

Copy link
Owner Author

williammalo commented Jul 10, 2012

@atk it doesn't work at all now... it either returns "undefined-suffix.png" or "NaN"

@atk

This comment has been minimized.

Copy link

atk commented Jul 10, 2012

I'll have a look into the problem later.

@atk

This comment has been minimized.

Copy link

atk commented Jul 11, 2012

OK, got this now. Forgot that there was no resolution beyond the last one. 176bytes now:

function(x,y,d,e,f,g,h){for(d in f=document.images)for(e in h=((d=f[d])[g='getAttribute']&&(d[g](x)||'').split(',')))if(h[e]<d.offsetWidth){d.src=(h[e+1]||h[e])+d[g](y);break}}
@atk

This comment has been minimized.

Copy link

atk commented Jul 11, 2012

Currently, I am trying to get rid of split, because it's too long. Not sure if this will work, but it goes around the lines of:

function(x,y,d,e,f,g,h,i){for(d in f=document.images)for(d=f[d],e=d.offsetWidth,h=/d+/g;i<e&&(i=h.exec(e&&d[g='getAttribute'](x)||g)[0]||i););i&&(d.src=i+d[g](y))}
@williammalo

This comment has been minimized.

Copy link
Owner Author

williammalo commented Jul 11, 2012

@atk the latest two don't work as well...

@atk

This comment has been minimized.

Copy link

atk commented Jul 12, 2012

I'll have to copy your test page so I could test myself...

@maettig

This comment has been minimized.

Copy link

maettig commented Jul 17, 2012

Can you drop the prefix and simply use "default.png", "400-default.png" and so on as filenames?

@williammalo

This comment has been minimized.

Copy link
Owner Author

williammalo commented Jul 17, 2012

@maettig
Sure?

@maettig

This comment has been minimized.

Copy link

maettig commented Jul 17, 2012

Just a suggestion. I don't know if this is what you want. Simply write <img src="default.png" data-widths="400,600,800,1023"> and use a.src=e+'-'+a.src instead of a.src=e+a.getAttribute(y).

@williammalo

This comment has been minimized.

Copy link
Owner Author

williammalo commented Jul 17, 2012

@maettig
Thats a brilliant idea! I'll implement it when I have the time!
Edit:
I just remembered why I didn't do this.
The browser loads the default automatically.
So to prevent loading a useless image, you have to either put no src attribute, or make the src a data url of a one pixel gif or something.

@shinsenter

This comment has been minimized.

Copy link

shinsenter commented Mar 1, 2019

My idea 136 bytes: (posted from my phone, not tested)

function respImg(s,u,d,l){document.images.map(a=>{d=a.dataset,for(l=d[s].split(',');l.length||a.offsetWidth>w=l.shift();)a.src=w+d[u]})}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.