I have only now discovered one issue lazy-loading images using anchors in a node which don't jump to the correct location while images are not loaded yet.

When I click a hyperlink to the anchor further down on the page, since it hasn't loaded images in between yet, it goes down much further.
After all the images are loaded and I click the hyperlink again it jumps to the correct location.

Wondering if there could be a workaround for this?
I would think that the offset (pre-load threshold) will only help to a certain extent, but not on long pages till the bottom, as it would defeat the purpose of lazyloading them.

Perhaps to have placeholders with same dimensions loaded instead?

Comments

markusd1984 created an issue. See original summary.

markusd1984’s picture

Issue summary: View changes
markusd1984’s picture

Issue summary: View changes
osman’s picture

@markusd1984, I cannot reproduce the issue. Can you share an example URL for review?

also, could you check whether image width and height attributes still exist? I'm guessing the issue could be related with that.

If the theme or any other module strips the width and height attributes, the dimension of those images will be 1x1 pixels (via default placeholder image). When they eventually load, their dimension will change to loaded image's dimensions, hence the vertical shifting as they become visible.

markusd1984’s picture

@osman my site is local only but I checked before the image is loaded it still contains width & height, see below:

<img alt="" height="596" width="1200" class="b-lazy" data-src="https://drupalserver/sites/default/files/images/test.png" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">

once i scroll down and they are loaded, the only change is the class to "b-lazy b-loaded"

This is what I have for the anchor:

<a href="#anchor1" target="_self">Link to anchor</a> 

<a id="anchor1" name="anchor1"></a>
markusd1984’s picture

I did some more testing with a basic page of multiple pictures and 3 anchors.

Interestingly from the first load, any of the anchor's scrolls down and consistently all overshoot by about 250 pixels.

After the full page is loaded they work as intended to stop at the anchor.
With the module disabled or even just with text it works fine, hence I doubt it's theme related but the effect with lazy loading.
Any thoughts?

osman’s picture

Status: Active » Postponed (maintainer needs more info)

@markusd1984 if you could provide more information, a screencast perhaps, then I can look into this. At this point I can't be sure whether it's an issue with this module, or with the Blazy JavaScript library, or with your theme CSS/JS.

markusd1984’s picture

@osman thanks I send you a connection request on LinkedIn and will share a screen recording.

When I load the page and scroll down to the anchor and back up to click the link pointing to that anchor then it works perfectly.
Not sure how the theme could affect this, it looks more like it's consistently off by 317 px for each anchor (clicking anchor 2 or 3 etc.)

Once I scroll to the bottom all anchors work fine. I can also see when i inspect the elements that at page load all images that have not been loaded yet have their height's dimensions and the overall div height for the content doesn't change either.

screen recording: https://imgur.com/a/HlQowBA

dragan_bp’s picture

Hey @markusd1984 . I've had the same issue, and the issue is related to blazy js library.

Take a look at this solution, it worked for me:

// When the user clicks on an anchor with a class name "someClassName"...
$('body').on('click', 'a.someClassName', function(e) {

    // Get the hash. In this example, "#myDestinationAnchor".
    var targetSelector = this.hash;
    var $target = $(targetSelector);

    // Animate the scroll to the destination...
    $('html, body').animate(
        {
            scrollTop: $target.offset().top // Scroll to this location.
        }, {
            // Set the duration long enough to allow time
            // to lazy load the elements.
            duration: 2000,

            // At each animation step, check whether the target has moved.
            step: function( now, fx ) {

                // Where is the target now located on the page?
                // i.e. its location will change as images etc. are lazy loaded
                var newOffset = $target.offset().top;

                // If where we were originally planning to scroll to is not
                // the same as the new offset (newOffset) then change where
                // the animation is scrolling to (fx.end).
                if(fx.end !== newOffset)
                    fx.end = newOffset;
            }
        }
    );
});

osman’s picture

As of bea26cd, bLazy public functions are accessible via Drupal.lazy namespace. Check out updated documentation on project page and on README.md.

@markusd1984, perhaps you can now trigger a Drupal.lazy.revalidate(); call, at certain events to accomplish your goal.

markusd1984’s picture

@dragan_bp thanks for sharing, but for this jquery to work, the anchor feature (I'm using ckeditor) would have to be modified to use someClassName. How did you solve this (or are you manually coding your anchors) ?

@osman Thanks, great to see you're improving the module, I just updated to the latest dev and I tried to trigger it via the success: function(ele) callback (by adding a new options variable for "success" in the admin UI with "function(ele) {Drupal.lazy.revalidate();}" ), however after the image is lazy loaded I'm getting a console error that

c.success is not a function

It seems I can't use the success callback (i even tried a simple test console output as success function without avail), am I doing this wrong or is the module not supporting this?

UPDATE: Just tried tried it manually instead of using options, then success is working, problem was using the variable it's putting the variable in "", anyway i tried with the code above but the revalidate call didn't help unfortunately with re-calculating the space while jumping to the anchor that has images along the way being lazy loaded.

jim22’s picture

Is there any way to disable an entire content type? I see the ability to disable individual pages and url patterns, but I have a content type that doesn't have a unique url pattern to target.

I am having the same issue with anchor links scrolling to incorrect target.offset due to the images being loaded during scroll.

jim22’s picture

In case anyone else runs into this issue, I solved by forcing blazy to load certain images even when not visible.

Force loading image even when not visible #110
https://github.com/dinbror/blazy/issues/110

	var imagesToLoad = document.querySelectorAll('.force-lazy-load');
	var blazy = new Blazy();
	blazy.load(imagesToLoad);
drupaldope’s picture

I have the same problem using the latest version with Drupal 9.

See this forum discussion:
https://www.drupal.org/forum/support/post-installation/2021-10-27/adding...

drupaldope’s picture

Version: 7.x-1.x-dev » 8.x-3.10
drupaldope’s picture

Update: enabling the default GIF base 64 placeholder makes the problem go away.