{"tag":"layout","articles":{"projects\/columnist":{"key":"projects\/columnist","type":"article","published":true,"meta":{"createdAt":"2019-08-26T15:07:32+02:00","publishedAt":"2019-08-26T17:48:00+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/columnist.avris.it\/","displayUrl":"Demo"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Columnist","displayUrl":null},{"icon":"globe-europe","colour":"secondary","url":"https:\/\/www.npmjs.com\/package\/avris-columnist","displayUrl":null}],"category":"projects","subcategory":null,"slug":"columnist"},"content":{"en":{"slug":"columnist","title":"Columnist \u2013 Simple and lightweight multi-column design","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.29473684211\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMklEQVRIicWVQXPTMBCFv5WtNMRNmik\/iekU\/iX3\/hdOHGE40XOZkDSurF0OshzHiZ0OdIZ3sawn62mfdteiqkYPIoLZ0dSr599iTTkk+otjVB4ffxKaSOGEEBqiKqvVkpn3IML729uTzf8FMnSoj5fwQhMiaooTAQQA7z3en8TyJg6JnWNbbLdb6n1NVMV7T9SICGDJSTNwTpjNrri+ri5G\/xqUE+cBIDQNaoqaUlUVmLURCiLZsfJs1H+DSYf+B04ToYfPX+DhaxrfLiAq7AKECJ6aj80DALOZxzlHjJEQGgB+fP9GXe8pipLFYs5m8xuAT\/d33N996DTMrHMaBg4NyUvzfR7o1uT1\/e9eu6Y8J5jfVXU0N8aqJXOqOso550aDm8yh0DTkrrDdbqmqipTOqboy97zbIa5gPr+CHpfWGk9Pv1iv1x3ny\/FMmexDUZUx2okQNZ7nnEvukjvXMVcWxelBxjp1H6nXJOuf93vezecHThzJ26Gktd+mhtVmzpTMEcqpZG2VAdCo3ThDRLI+na5JulI5fxARGS0QEbncGE0Sv1gsunFWz\/Ef6UrmDggh4L1vN2SyiV50KMVrdP+M3gmS9nDeeodJv5fd7pmbmzLPTLaQySqLMRJHkrpwMso5EZp4vuyLYrrKJq9MzbC2WjabDavlsqscFdclfF3XFKWnLFJ\/MXHdhWYvDirj\/asNprV\/5IkIiLBcrtLuR8kqmAll6TEdFrkcHu0eTGjl8R8MrVmKlGbrrwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.29473684211\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022488.58947368421\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMklEQVRIicWVQXPTMBCFv5WtNMRNmik\/iekU\/iX3\/hdOHGE40XOZkDSurF0OshzHiZ0OdIZ3sawn62mfdteiqkYPIoLZ0dSr599iTTkk+otjVB4ffxKaSOGEEBqiKqvVkpn3IML729uTzf8FMnSoj5fwQhMiaooTAQQA7z3en8TyJg6JnWNbbLdb6n1NVMV7T9SICGDJSTNwTpjNrri+ri5G\/xqUE+cBIDQNaoqaUlUVmLURCiLZsfJs1H+DSYf+B04ToYfPX+DhaxrfLiAq7AKECJ6aj80DALOZxzlHjJEQGgB+fP9GXe8pipLFYs5m8xuAT\/d33N996DTMrHMaBg4NyUvzfR7o1uT1\/e9eu6Y8J5jfVXU0N8aqJXOqOso550aDm8yh0DTkrrDdbqmqipTOqboy97zbIa5gPr+CHpfWGk9Pv1iv1x3ny\/FMmexDUZUx2okQNZ7nnEvukjvXMVcWxelBxjp1H6nXJOuf93vezecHThzJ26Gktd+mhtVmzpTMEcqpZG2VAdCo3ThDRLI+na5JulI5fxARGS0QEbncGE0Sv1gsunFWz\/Ef6UrmDggh4L1vN2SyiV50KMVrdP+M3gmS9nDeeodJv5fd7pmbmzLPTLaQySqLMRJHkrpwMso5EZp4vuyLYrrKJq9MzbC2WjabDavlsqscFdclfF3XFKWnLFJ\/MXHdhWYvDirj\/asNprV\/5IkIiLBcrtLuR8kqmAll6TEdFrkcHu0eTGjl8R8MrVmKlGbrrwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022488.58947368421\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ETake a look at this graphic:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022475.49103330487\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAElEQVRIiZVV207jMBA9M3ZWon0Csd\/B\/\/8E8MAPIMGudgtFglawJJ7ZB8d3h4ZRk9rj4zP2GTtDIqLT5ADCSSMQmAlO5DQYABNDoVDVVXhrDBgAnAhEtHh2u6fG50Qgqo3\/4\/0Du6d941cVSIf74eFX4\/N4hQ2rq3ex2WwbHxF1seM4YrvZdJTo47fbHnaeISI6ThMoz9nLi\/8\/P2\/4iQiTc4D6cIqUbU0wKAGWOSq6hCFNvh+D9QoNNgrl7XgAXl+Bn5fNDpyIZ4JGojqcYo6W2RImsXizIQ2FnZ0B+z3QG0PuDhoVo42vpenNmxfUzeXFBXA8Agt5Vsw6R72z\/IVAlCUz9yNvt\/x9heJGlsYo\/Pw5CPQd+GAt6hiqWvjyfl+hFDbeBiJK7RPfFapavRi1L\/S\/VggodhLbRPF65ZkhoLx21fw8+PcUensDDodFheI7HoXqUitiunP+guNbCj0+Avf3wNVVoxATwTKVMiRE0WPmRqGwqKXMkIjov8+xpFL1D3NDxobhJtclq80YA1GByrpaNgwWKSKFXRNAhNu7u9SfH+1hQXjeP+P3n78lnvJvTYm\/vrn1IxUPkCm0xogIxjCmlQpZk0rHGoulIwRbtSgAvBLrb+PyeelZUcT8Sfd3eRYw1ppQfJkZxpjm9qT55eY+RYpDnDC+vpGW1ew\/BCdqPrjZC2cAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022475.49103330487\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EOur main job is to make the empty space marked with the red arrow disappear. If we can calculate its height, we can give the tile right below it a negative \u003Ccode\u003Emargin-top\u003C\/code\u003E to compensate for the height of the empty space.\u003C\/p\u003E\n\u003Cp\u003EAnd we can! All we need is to make sure that the column only has one child element. The difference between the height of the column and of that child is what we need to compensate for.\u003C\/p\u003E\n\u003Cp\u003EWe can find the tile right below from it (\u003Ccode\u003Ei + numberOfColumns\u003C\/code\u003E), give it \u003Ccode\u003Emargin-top: -${diff}px\u003C\/code\u003E et voil\u00e0!\u003C\/p\u003E\n\u003Ch3\u003ELimitations\u003C\/h3\u003E\n\u003Cp\u003EMy script does not do any maths fancier than this. If your first column contains a very tall tile A and a small tile B, and your second column only contains a small tile C, it would look nicer, if B were moved to the second column. My script doesn\u2019t do that. That\u2019s the price of simplicity.\u003C\/p\u003E\n\u003Ch3\u003EFuture work\u003C\/h3\u003E\n\u003Cp\u003ECurrent implementation relies a \u003Ccode\u003EsetInterval\u003C\/code\u003E that reapplies the layout every 300 ms. Firstly, because a couple of iterations are needed to get the final layout, and secondly, because the DOM and window can change.\u003C\/p\u003E\n\u003Cp\u003EObviously, I can get rid of both those problems. Applying the layout in a loop or in some smarter way, adding event listeners, etc.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s a job for the next free evening \/ weekend.\u003C\/p\u003E\n\u003Cp\u003EAnyways, check out the links below and enjoy \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["column","design","javascript","layout","library","masonry","multi-column","npm"],"hasMore":true,"image":"https:\/\/avris.it\/image\/columnist_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.14736842105\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.14736842105\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ETake a look at this graphic:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist-how_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022118.87275832622\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EOur main job is to make the empty space marked with the red arrow disappear. If we can calculate its height, we can give the tile right below it a negative \u003Ccode\u003Emargin-top\u003C\/code\u003E to compensate for the height of the empty space.\u003C\/p\u003E\n\u003Cp\u003EAnd we can! All we need is to make sure that the column only has one child element. The difference between the height of the column and of that child is what we need to compensate for.\u003C\/p\u003E\n\u003Cp\u003EWe can find the tile right below from it (\u003Ccode\u003Ei + numberOfColumns\u003C\/code\u003E), give it \u003Ccode\u003Emargin-top: -${diff}px\u003C\/code\u003E et voil\u00e0!\u003C\/p\u003E\n\u003Ch3\u003ELimitations\u003C\/h3\u003E\n\u003Cp\u003EMy script does not do any maths fancier than this. If your first column contains a very tall tile A and a small tile B, and your second column only contains a small tile C, it would look nicer, if B were moved to the second column. My script doesn\u2019t do that. That\u2019s the price of simplicity.\u003C\/p\u003E\n\u003Ch3\u003EFuture work\u003C\/h3\u003E\n\u003Cp\u003ECurrent implementation relies a \u003Ccode\u003EsetInterval\u003C\/code\u003E that reapplies the layout every 300 ms. Firstly, because a couple of iterations are needed to get the final layout, and secondly, because the DOM and window can change.\u003C\/p\u003E\n\u003Cp\u003EObviously, I can get rid of both those problems. Applying the layout in a loop or in some smarter way, adding event listeners, etc.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s a job for the next free evening \/ weekend.\u003C\/p\u003E\n\u003Cp\u003EAnyways, check out the links below and enjoy \ud83d\ude09\u003C\/p\u003E","words":331,"readTime":2,"lang":"en"}}}}}