Reputation: 275
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.
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?
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?
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
.
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;
}
});
Upvotes: 3
Views: 2740
Reputation: 81
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;");
}
});
};
Upvotes: 0
Reputation: 275
So I managed to solve the bigger of the two issues, which was the images not displaying because of 0 height. For some reason, when loading an image with srcset
through AJAX Safari was removing the auto height and making it 0px.
I wrote a function that waits till all the images are loaded (because otherwise naturalHeight
was returning 0) then it changes the height to be a height that retains the same aspect ratio of the original image. I also made it so that it only targets images that don't have object-fit: cover
applied to them as these were the images that were giving me problems, otherwise it would have messed up the object-fit
images.
function safariResize() {
console.log("Running safariResize");
// This variable starts at 1 because the logo (always on the page) is image 0
var loaded = 1;
$('img').on('load',function(){
loaded++;
images = $('img');
if (loaded == $('img').length){
for (var i = 1; i < images.length; i++){
if ($(images[i]).css("object-fit") != 'cover'){
var naturalH = images[i].naturalHeight;
var naturalW = images[i].naturalWidth;
var ratio = naturalH / naturalW;
var newRatio = (images[i].width / naturalW);
var newH = naturalH * newRatio;
$(images[i]).css("height", newH + "px");
}
}
}
});
}
Then I call this function after my AJAX load inside an if statement to make sure it only fires on Safari
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
safariResize();
} else if (navigator.userAgent.indexOf('iPad') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
safariResize();
}
I don't believe I'll be able to solve the object-fit issue, which only happens on the desktop version of Safari (works fine on iPad). Let me know if you find an easier way to solve this problem, as this was quite a process for me to fix.
Upvotes: 0
Reputation: 2038
Check following on your image css
You might be assuming that css rules applied to components stay as they were on initial load but you might have to reapply some of these after ajax has finished loading specially if you had some javascript running to manage these rules. Some browsers might be able to apply them. I need to find that post online but for now if you can look into above and its not solving your issue then let me know here. To isolate img issue you can create a test page with single image and share a link and remove as much of other items from that page as possible. Maybe just basic header and footer to isolate other issues.
Upvotes: 0