Anders Hattestad
Aug 14, 2012
visibility 15316
star star star star star
(2 votes)

Automatically change images in a responsive design to scale

A lot of new sites uses responsive design. The key feature with this of course that the web page scale to the current view port of the device a user is using.  Images and other elements are often set to width:100% in the css. The problem that we then have to solve is to return to the user a images that is in the correct size in pixels.

I have wrote a concept around this based on the current alloy template site.

First of all I want to change all images that are returned from a request. I wrote my self a module ChangeImageSource  that I can add in the master page like this.

MasterPage.master
<asp:ContentPlaceHolder ID="MainContentRegion" runat="server">
    <div id="MainBodyArea">
        <Itera:ChangeImageSource runat="server" ID="ChangeImageArea">
            <asp:ContentPlaceHolder ID="MainBodyRegion" runat="server">
                <div id="MainBody">
                    <AlloyTech:MainBody runat="server" />
                </div>
            </asp:ContentPlaceHolder>
        </Itera:ChangeImageSource>
    </div>
    <div id="SecondaryBodyArea">
        <Itera:ChangeImageSource runat="server" ID="ChangeImageSource1" AddBox="border">
            <asp:ContentPlaceHolder ID="SecondaryBodyRegion" runat="server">
                <div id="SecondaryBody">
                    <EPiServer:Property PropertyName="SecondaryBody" EnableViewState="false" runat="server" />
                </div>
            </asp:ContentPlaceHolder>
        </Itera:ChangeImageSource>
    </div>
</asp:ContentPlaceHolder>

This module replace every images inside its content with a reference to a empty images, and add the original image in a new attribute called orgsrc.

<img orgsrc="/PageFiles/5/Desert.jpg" alt="" 
src="/Itera.ResponsiveResize/ZeroSize.png" class="scaleImage">

The code that replace all images in a given tag is done like this using HtmlAgilityPack

protected override void Render(HtmlTextWriter writer)
{
    if (this.Page.Request["dontChangeImages"] == null)
    {
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        HtmlTextWriter htw = new HtmlTextWriter(sw);
        base.Render(htw);

        string content = sb.ToString();
        //writer.Write("content length=" + content.Length);
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(content);
        var images = doc.DocumentNode.SelectNodes("//img[@src]");
        if (images != null)
        {
            foreach (HtmlNode image in images)
            {
                HtmlAttribute src = image.Attributes["src"];

                image.Attributes.Add("orgsrc", src.Value);
                src.Value = "/Itera.ResponsiveResize/ZeroSize.png";
                if (image.Attributes["width"] != null)
                {
                    image.Attributes.Remove("width");
                }
                if (image.Attributes["height"] != null)
                {
                    image.Attributes.Remove("height");
                }
                if (image.Attributes["class"] == null)
                {
                    image.Attributes.Add("class", AddClass);
                }
                else
                {
                    image.Attributes["class"].Value = image.Attributes["class"].Value + " scaleImage";
                }
                if (!string.IsNullOrEmpty(AddBox))
                {
                    var newNode = HtmlNode.CreateNode("<div class='" + AddBox + "'>" + image.OuterHtml+ "</div>");

                    image.ParentNode.ReplaceChild(newNode, image);

                }
            }
        }
        writer.Write("<div id='" + UnikID + "'>");
        writer.Write(doc.DocumentNode.OuterHtml);
        writer.Write("</div>");
        writer.Write("<div id='Log" + UnikID + "'></div>");
               
    }
    else
    {
        base.Render(writer);
    }
}

Then the module add some JavaScript that after the page is loaded find all images in the current zone and uses JQuery to find the current width in pixels and change the image source to a reference to a scaled images with the correct width. And if the pages is resized it will change the images. To save some cpu, it will use a images that is round up to the next hundred. The actually resizing of the pictures can be done with a lot of different te4chinces , but this demo uses ImageResizer

$(document).ready(function () {
    $('#133d8cb8fb224834bbfdde298adbec25 img').each(function (i) {

        if (!$(this).attr('orgsrc')) {
            var img = $(this).attr('src');
            $(this).attr('orgsrc', img);
        }
        ResizeImageWith100Procent133d8cb8fb224834bbfdde298adbec25($(this));
    });
});

$(window).resize(function () {
    $('#log133d8cb8fb224834bbfdde298adbec25').append('<div>resize finished</div>');
    $('#133d8cb8fb224834bbfdde298adbec25 img').each(function (i) {
        if ($(this).attr('orgsrc')) {
            ResizeImageWith100Procent133d8cb8fb224834bbfdde298adbec25($(this));
        }
    });

});
function ResizeImageWith100Procent133d8cb8fb224834bbfdde298adbec25(obj)
{
    var orgsrc = obj.attr('orgsrc');
    var width = obj.width();

            width /= 100;
            width = Math.ceil(width);
            width *= 100;
            if (obj.attr('src').indexOf('width_' + width) == -1) {
                obj.attr('src',  orgsrc + '?width=' + width );
               
            }
}
image
<img orgsrc="/PageFiles/5/Desert.jpg" alt=""
src="/PageFiles/5/Desert.jpg?width=500" class="half100Procent scaleImage"> <img orgsrc="/PageFiles/5/product3Prev.png" alt="prevproduct1"
src="/PageFiles/5/product3Prev.png?width=200" class="border scaleImage">
image
image
<img orgsrc="/PageFiles/5/Desert.jpg" alt=""
src="/PageFiles/5/Desert.jpg?width=400" class="border scaleImage">
image
<img orgsrc="/PageFiles/5/product3Prev.png" alt="prevproduct1"
src="/PageFiles/5/product3Prev.png?width=400" class="border scaleImage">

What you need to do is to unzip the file and add the dll’s from the project to your bin folder, and

change the web.config to use ImageResizer.

Then you need to add the web control in the master page

 

Have added a working web.config and a working master.page from the

alloy project along with the zip of the project

Download here

Aug 14, 2012

Comments

Frederik Vig
Frederik Vig Aug 14, 2012 08:44 PM

Won't this result in a lot of unnecessary requests to the server? First for the the empty image and then again after you replace it with JS with the new image. Also this won't work without JS and search engines won't be able to index the images.

Not an easy problem to solve responsive images :)

Anders Hattestad
Anders Hattestad Aug 14, 2012 08:56 PM

The empty picture could be resolved using css and a bas64 encoded images.
It will of course not work without JS :)

Its also just a consept, and one could return the normal images first, than change it after

Aug 14, 2012 11:26 PM

There really isn't a good solution for responsive images at the moment. Waiting for CSS Bandwidth Media Queries.

Anders Hattestad
Anders Hattestad Aug 14, 2012 11:42 PM

Not sure I really agree with you on this Alexander. This consept shows that you can replace images after they are loaded based on css % sizes.
What more to the mix will CSS Bandwith Media Queries add?

Johan Kronberg
Johan Kronberg Aug 15, 2012 11:40 AM

I like! But the src-attributes in markup should contain the smallest version.

Anders Hattestad
Anders Hattestad Aug 15, 2012 12:13 PM

That is of course easy to do :)

One could use a small images that will be displayed enlarged, and after page load the images will be replaced with an correct image

Anders Hattestad
Anders Hattestad Aug 17, 2012 09:42 AM

For futher reference
W3C Launches Responsive Images Community
http://filamentgroup.com/lab/w3c_responsive_imgs_group/
http://www.w3.org/community/respimg/
https://github.com/scottjehl/picturefill
https://github.com/filamentgroup/Responsive-Images

Which responsive images solution should you use?
http://css-tricks.com/which-responsive-images-solution-should-you-use/

Responsive IMGs — Part 1
http://blog.cloudfour.com/responsive-imgs/

Responsive IMGs Part 2 — In-depth Look at Techniques
http://blog.cloudfour.com/responsive-imgs-part-2/

Aug 20, 2012 02:26 PM

Just one thing about the javascript. Its better to use a event listener on window.load instead of document.ready since document.ready fires when html is loaded, not content.

Aug 20, 2012 02:49 PM

Data-attributes are perfect for storing URLs to images with different resolutions (until there is a real/native implementation, of course): http://jsfiddle.net/pellebjerkestrand/B2C46/

The src attribute can be filled with the smallest image or, if you for example put the viewport width in a cookie, the most appropriate image for the view.

error Please login to comment.
Latest blogs
Exploring Asset Lifecycle Management Approaches for Bynder and Optimizely SaaS CMS

Note: This is Part 3 of our Bynder integration series. For setup and filtering prerequisites, see Part 1  and  Part 2 . Introduction In my previous...

Vipin Banka | Jul 5, 2026

Unlock AI-Ready Experiences with Optimizely

Over the past few months, almost every customer conversation has shifted from SEO to AI readiness. The questions are no longer just: “How do we......

Madhu | Jul 5, 2026 |

Planning Your Bynder DAM and Optimizely SaaS CMS Integration the Right Way: Avoiding Asset Sprawl and Unnecessary Synchronization

Note: This is Part 2 of our Bynder integration series. If you missed the Part 1, check out " Implementing the Bynder DAM Connector with Optimizely...

Vipin Banka | Jul 4, 2026

Implementing the Bynder DAM Connector with Optimizely SaaS CMS: Lessons Learned

What I learned while integrating Bynder DAM with Optimizely SaaS CMS, exploring Optimizely Graph, and building a headless frontend experience....

Vipin Banka | Jul 3, 2026

Optimizely London developer meetup 2026: a round up

Well, what can I say? Last night we wrapped up! Yet another London Developer Meetup, hosted at the superb Lightwell venue And this is also a...

Scott Reed | Jul 3, 2026

AvantiBit Custom Settings for Optimizely CMS

AvantiBit Custom Settings is a free, Apache-2.0 Optimizely CMS add-on for typed, site- and language-aware configuration that stays out of content...

Enes Bajramovic | Jul 3, 2026 |