AJAX loaded images not displaying properly in Safari

Viewed 2374

So I'm using AJAX to load the content from each page and inject it into the current page. Everything is working great on Chrome, Firefox, Internet Explorer (as much as it can haha), and the content loads fine on Safari, aside from two curious parts.

  1. Images loaded via AJAX are getting a height of 0
  2. Images loaded via AJAX are losing their object-fit property.

Issue 1: Image height 0

I'll be using this page for reference: http://insight.insightcreative.info/about

If you open the page up in Safari everything should be displaying great, but now if you click the About link to reload the page using AJAX loading, the images on the page will break.

What I'm finding is happening is that the image heights are getting set to 0 when they are loaded in by AJAX.

Here is an example of an image on the page that gets broken after being loaded by AJAX

<img data-aos-anchor-placement="bottom-bottom" data-aos-offset="100" src="/img/agency/clients/affinity-medical-group.jpg" alt="Affinity"
srcset="
/img/agency/clients/affinity-medical-group-2400.jpg 2400w,
/img/agency/clients/affinity-medical-group-1800.jpg 1800w,
/img/agency/clients/affinity-medical-group-1200.jpg 1200w,
/img/agency/clients/affinity-medical-group-900.jpg 900w,
/img/agency/clients/affinity-medical-group-600.jpg 600w,
/img/agency/clients/affinity-medical-group-400.jpg 400w" />

Why is it that the page will render properly if it is an initially loaded page (or a hard refresh), but when the content is loaded by AJAX it doesn't apply the height properly?


Issue 2: Object-fit not working

I'll be using this page for reference: http://insight.insightcreative.info/work

If you open the page in Safari, everything should be displaying great, but now if you click the Work link to reload the page using AJAX loading, the images on the page will not display with object-fit.

If you inspect the page, you'll find all the same CSS settings are being applied to the images, including the object-fit property, but for some reason they no longer are respecting their properties. Instead the images are stretching to fill the container.

Why is it that the page will render properly if it is an initially loaded page (or a hard refresh), but when the content is loaded by AJAX it doesn't adhere to the object-fit property anymore?


Both of these issues only seem to be occuring in Safari, and I'm guessing it has something to do with the way Safari handles the image properties when loaded through AJAX.

Is there a way I could try force Safari to properly re-apply these settings after the page is loaded through AJAX? Or is there a coding god out there that know's how to handle these issues with Safari?


EDIT 1:

I wrote a function to change the CSS of my page after the AJAX loaded so that it would rewrite the properties for my images. I intentionally change the object-fit to fill then back to cover in an attempt to completely reset the style.

function checkImages() {
  var images = $('img');
  for (var i = 0; i <= images.length; i++){
    var result = $(images[i]).css("object-fit");
    if (result == 'cover'){
      $(images[i]).css("object-fit","fill");
      $(images[i]).css("object-fit","cover");
      $(images[i]).css("display","block");
      $(images[i]).css("position","relative");
      $(images[i]).css("max-width","100%");
      $(images[i]).css("max-height","100%");
    }
  }
}

I confirmed this code works by intentionally changing some of these settings so that they would drastically reflect in the browser. I found that even changing the settings after the page has loaded all content that I still cannot seem to fix the issue (in regards to styling).

However, this did lead me to try something else. By removing the srcset attribute completely from my image, it will then render properly even with AJAX load. So essentially, for some reason, by using srcset it only allows the page to display properly if it is hard loaded, but won't display properly if loaded by AJAX. I'm not sure if this is in correlation with the fact that Safari also will only load the first image it sees in srcset and ignores the rest, but I think the issues lies in how Safari is handling srcset.

SOLUTION: Barba.js

Without going into crazy detail I managed to fix the issue. Before I was using my own written script for loading in the content of each page. After testing Barba.js I found that the images did not have any issues on Safari. So I loaded in Barba.js and then rewrote all of my JS so that it functioned correctly with that PJAX library. So somehow the way I was loading the pages before was causing this issue, but only with Safari.

Below is a snippet of the code I was using to load AJAX before

//Function that loads in the new content
var load = function(url) {

//Fadeout leaving page transition
$('#content').velocity("fadeOut", {
  visibility: 'visible',
  display: 'block',
  complete: function() {

    //Load new content
    $("#content").load(url + " #content");

  }
});

};

//Action to perform on link click
$(document).on('click', 'a', function(e) {

//Sets variables to be used for url and page name
var $this = $(this),
  url = $this.attr("href"),
  title = $this.text();
loading = true;

//Makes entries into browser history
if (url.indexOf(document.domain) > -1 || url.indexOf(':') === -1) {
  history.pushState({
    url: url + '/',
    title: title
  }, title, url);
  $('#container').mixItUp('destroy');
  $('a').on('click.myDisable', function() {
    return false;
  });
  load(url);
  if (url === '/') {
    document.title = "Insight Creative, Inc.";
  } else {
    document.title = title + " - Insight Creative, Inc.";
  }

  return false;
}
});
3 Answers

I was also experiencing the Safari bug outlined in Issue 1 but instead of rebuilding my app on Barba.js chose to rewrite the safariResize function using the imagesLoaded script. Here is my function in case someone else finds it useful:

var safariResize = function() {
    // Targetting collapsed images in pjax loading box (safari bug)
    var imgLoad = imagesLoaded( $('.site-container > .site-inner img') );
    imgLoad.on( 'progress', function( instance, image ) {
        if(image.isLoaded && image.img.height == 0){
            var naturalH = image.img.naturalHeight,
            naturalW = image.img.naturalWidth;
            if( image.img.parentElement.clientWidth < naturalW ){
                var ratio = naturalH / naturalW;
                naturalW = image.img.parentElement.clientWidth;
                naturalH = naturalW * ratio;
            }
            image.img.setAttribute("style","width: "+naturalW+"px; height: "+naturalH+"px;");
        }
    });
};
Related