{"id":3405,"date":"2017-02-09T17:32:17","date_gmt":"2017-02-09T16:32:17","guid":{"rendered":"https:\/\/en.florianbrinkmann.de\/?p=3405"},"modified":"2020-02-09T10:59:56","modified_gmt":"2020-02-09T09:59:56","slug":"lazy-loading-images-in-a-masonry-grid","status":"publish","type":"post","link":"https:\/\/florianbrinkmann.com\/en\/lazy-loading-images-in-a-masonry-grid-3405\/","title":{"rendered":"Lazy loading images in a masonry grid"},"content":{"rendered":"<figure class=\"wp-block-image\"><noscript><img decoding=\"async\" width=\"1444\" height=\"718\" src=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt.jpg\" alt class=\"wp-image-3406\" srcset=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt.jpg 1444w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-402x200.jpg 402w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-300x149.jpg 300w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-768x382.jpg 768w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-806x401.jpg 806w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-600x298.jpg 600w\" sizes=\"(max-width: 1444px) 100vw, 1444px\"><\/noscript><img decoding=\"async\" width=\"1444\" height=\"718\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201444%20718%22%3E%3C%2Fsvg%3E\" alt class=\"wp-image-3406 lazyload\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201444%20718%22%3E%3C%2Fsvg%3E 1444w\" sizes=\"(max-width: 1444px) 100vw, 1444px\" data-srcset=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt.jpg 1444w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-402x200.jpg 402w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-300x149.jpg 300w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-768x382.jpg 768w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-806x401.jpg 806w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt-600x298.jpg 600w\" data-src=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-korrekt.jpg\"><\/figure>\n\n\n\n<p>With lazy loading, you only load images when they are in the visible area of the visitor. Combining this method with a masonry grid can cause problems because the images are not loaded yet when the position of the grid items is calculated. Here I show you how to solve that.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">The problem with lazy loading and masonry grids<\/h2>\n\n\n\n<p>A masonry grid script positions the grid items absolute after calculating the position for the items based on its width and height. But if the images are loaded after running the script because of lazy loading, the script returns wrong positions. The result can look something like that:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><noscript><img decoding=\"async\" width=\"1444\" height=\"718\" src=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch.jpg\" alt=\"A masonry grid with overlapping items because the images are lazy loaded.\" class=\"wp-image-3407\" srcset=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch.jpg 1444w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-402x200.jpg 402w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-300x149.jpg 300w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-768x382.jpg 768w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-806x401.jpg 806w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-600x298.jpg 600w\" sizes=\"(max-width: 1444px) 100vw, 1444px\"><\/noscript><img decoding=\"async\" width=\"1444\" height=\"718\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201444%20718%22%3E%3C%2Fsvg%3E\" alt=\"A masonry grid with overlapping items because the images are lazy loaded.\" class=\"wp-image-3407 lazyload\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201444%20718%22%3E%3C%2Fsvg%3E 1444w\" sizes=\"(max-width: 1444px) 100vw, 1444px\" data-srcset=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch.jpg 1444w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-402x200.jpg 402w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-300x149.jpg 300w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-768x382.jpg 768w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-806x401.jpg 806w, https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch-600x298.jpg 600w\" data-src=\"https:\/\/florianbrinkmann.com\/en\/wp-content\/uploads\/sites\/11\/2017\/02\/masonry-grid-falsch.jpg\"><\/figure>\n\n\n\n<p>Not what we want and expect, and we do not want to wait until all images are loaded to run the script. So what can we do?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The solution: width and height as inline styles<\/h2>\n\n\n\n<p>The grid item\u2019s markup looks like that:<\/p>\n\n\n<pre class=\"wp-block-code lang-markup\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">&lt;article <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span><\/span>=<span class=\"hljs-string\">\"col-4\"<\/span>&gt;\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">figure<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"lazyload\"<\/span> <span class=\"hljs-attr\">data-src<\/span>=<span class=\"hljs-string\">\"&#91;\u2026]\"<\/span> <span class=\"hljs-attr\">data-srcset<\/span>=<span class=\"hljs-string\">\"&#91;\u2026]\"<\/span> <span class=\"hljs-attr\">data-sizes<\/span>=<span class=\"hljs-string\">\"&#91;\u2026]\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">noscript<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"&#91;\u2026]\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">noscript<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">figure<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Zigarettenwerbung<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"category\"<\/span>&gt;<\/span>&#91;\u2026]<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"date\"<\/span>&gt;<\/span>&#91;\u2026]<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"team\"<\/span>&gt;<\/span>&#91;\u2026]<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The solution for our problem is to add the width and height of the image to the <code class=\"lang-markup\">figure<\/code> element. So the masonry script will consider the space of the not-yet-loaded images correctly while calculating the positions. How you get the width and height depends on how you generate the grid. I used WordPress and the plugin <em>Advanced Custom Fields<\/em> to create the grid from the screenshot, and get the width and height from the image object.<\/p>\n\n\n\n<p>To avoid issues with this solution and responsive design, you should destroy the masonry grid if the grid\u2019s wrapper is not wide enough for the widest grid image. Otherwise, the calculated position is not going to be correct (but I am sure there is a solution for that too \ud83d\ude42 ).<\/p>\n\n\n\n<p>You can see the grid implementation live on <a href=\"https:\/\/dennisbrinkmann.de\/\">dennisbrinkmann.de<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With lazy loading, you only load images when they are in the visible area of the visitor. Combining this method with a masonry grid can cause problems because the images are not loaded yet when the position of the grid items is calculated. Here I show you how to solve that.<\/p>\n","protected":false},"author":1,"featured_media":3406,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wpf_show_in_dewp_planet_feed":false,"flobn_post_versions":"","webmentions_disabled_pings":false,"webmentions_disabled":false,"lazy_load_responsive_images_disabled":false,"footnotes":""},"categories":[6],"tags":[],"class_list":["post-3405","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development"],"wp-worthy-pixel":{"ignored":false,"public":"97e24d24ebb746b1b27632be43f9db96","server":"vg01.met.vgwort.de","url":"https:\/\/vg01.met.vgwort.de\/na\/97e24d24ebb746b1b27632be43f9db96"},"wp-worthy-type":"normal","_links":{"self":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/3405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/comments?post=3405"}],"version-history":[{"count":2,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/3405\/revisions"}],"predecessor-version":[{"id":5916,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/3405\/revisions\/5916"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/media\/3406"}],"wp:attachment":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/media?parent=3405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/categories?post=3405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/tags?post=3405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}