From aca1cb98bd887aab2d319e2ab81eccdd9d392bea Mon Sep 17 00:00:00 2001 From: Lex Lim Date: Mon, 25 Nov 2024 11:13:10 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DMasonry=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E5=BC=8F=E5=B8=83=E5=B1=80=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension.json | 2 +- includes/MasonryItemWidget.php | 12 +- includes/MasonryWidget.php | 51 ++-- modules/masonry/ext.isekai.masonry.base.js | 49 +++- modules/masonry/ext.isekai.masonry.css | 315 +++++++++++++++++++++ modules/masonry/ext.isekai.masonry.less | 80 ------ src/masonry/ext.isekai.masonry.js | 1 + src/masonry/ext.isekai.masonry.less | 52 ++++ 8 files changed, 441 insertions(+), 121 deletions(-) create mode 100644 modules/masonry/ext.isekai.masonry.css delete mode 100644 modules/masonry/ext.isekai.masonry.less create mode 100644 src/masonry/ext.isekai.masonry.less diff --git a/extension.json b/extension.json index f4dc2b8..40c2082 100644 --- a/extension.json +++ b/extension.json @@ -230,7 +230,7 @@ "masonry/ext.isekai.masonry.base.js" ], "styles": [ - "masonry/ext.isekai.masonry.less" + "masonry/ext.isekai.masonry.css" ], "targets": [ "desktop", diff --git a/includes/MasonryItemWidget.php b/includes/MasonryItemWidget.php index 22025dc..79f7912 100644 --- a/includes/MasonryItemWidget.php +++ b/includes/MasonryItemWidget.php @@ -26,7 +26,7 @@ class MasonryItemWidget { if (isset($params['col'])) { $value = $params['col']; - $col = $value === 'full' ? $maxCol : min($maxCol, intval($value)); + $col = $value === 'full' ? $maxCol : min(12, intval($value)); $className[] = 'col-' . $col; } else { $className[] = 'col-1'; @@ -34,31 +34,31 @@ class MasonryItemWidget { if (isset($params['xs-col'])) { $value = $params['xs-col']; - $col = $value === 'full' ? $maxCol : min($maxCol, intval($value)); + $col = $value === 'full' ? $maxCol : min(12, intval($value)); $className[] = 'col-xs-' . $col; } if (isset($params['sm-col'])) { $value = $params['sm-col']; - $col = $value === 'full' ? $maxCol : min($maxCol, intval($value)); + $col = $value === 'full' ? $maxCol : min(12, intval($value)); $className[] = 'col-sm-' . $col; } if (isset($params['md-col'])) { $value = $params['md-col']; - $col = $value === 'full' ? $maxCol : min($maxCol, intval($value)); + $col = $value === 'full' ? $maxCol : min(12, intval($value)); $className[] = 'col-md-' . $col; } if (isset($params['lg-col'])) { $value = $params['lg-col']; - $col = $value === 'full' ? $maxCol : min($maxCol, intval($value)); + $col = $value === 'full' ? $maxCol : min(12, intval($value)); $className[] = 'col-lg-' . $col; } if (isset($params['xl-col'])) { $value = $params['xl-col']; - $col = $value === 'full' ? $maxCol : min($maxCol, intval($value)); + $col = $value === 'full' ? $maxCol : min(12, intval($value)); $className[] = 'col-xl-' . $col; } diff --git a/includes/MasonryWidget.php b/includes/MasonryWidget.php index 76a9f8c..bb8c797 100644 --- a/includes/MasonryWidget.php +++ b/includes/MasonryWidget.php @@ -4,6 +4,13 @@ namespace Isekai\Widgets; use Html; class MasonryWidget { + public static $breakpoints = [ + 'xs' => 576, + 'sm' => 768, + 'md' => 992, + 'lg' => 1200, + 'xl' => 1400, + ]; public static $paramsStack = []; /** @@ -21,30 +28,25 @@ class MasonryWidget { $gutter = max(0, $params['gutter']); $maxCol = max(1, $params['cols']); $colWidth = round(100 / $maxCol, 6); - $css = << 576, - 'sm' => 768, - 'md' => 992, - 'lg' => 1200, - 'xl' => 1400, - ]; + $css = ".isekai-masonry.max-col-{$maxCol} { --masonry-col-width: {$colWidth}%; --masonry-gutter: {$gutter}px; }"; + + if (isset($params['xs-cols'])) { + $maxCol = max(1, $params['xs-cols']); + $colWidth = round(100 / $maxCol, 6); + $css = ".isekai-masonry.max-col-xs-{$maxCol} { --masonry-col-width: {$colWidth}%; --masonry-gutter: {$gutter}px; }"; + } - foreach ($breakpoints as $breakpoint => $width) { + foreach (self::$breakpoints as $breakpoint => $width) { $paramKey = "{$breakpoint}-cols"; if (!isset($params[$paramKey])) { continue; } - $maxCol = max(1, $params[$paramKey]); + $value = intval($params[$paramKey]); + $maxCol = max(1, $value); $colWidth = round(100 / $maxCol, 6); - $css .= <<getOutput()->addModules(['ext.isekai.masonry']); $params['cols'] = intval($params['cols'] ?? 2); - $params['xs-cols'] = intval($params['xs-cols'] ?? 1); - $params['sm-cols'] = intval($params['sm-cols'] ?? 1); - $params['md-cols'] = intval($params['md-cols'] ?? 2); - $params['lg-cols'] = intval($params['lg-cols'] ?? 2); - $params['xl-cols'] = intval($params['xl-cols'] ?? 3); $params['gutter'] = intval($params['gutter'] ?? 10); $className = [ 'isekai-masonry', "max-col-{$params['cols']}", - "max-col-xs-{$params['xs-cols']}", - "max-col-sm-{$params['sm-cols']}", - "max-col-md-{$params['md-cols']}", - "max-col-lg-{$params['lg-cols']}", - "max-col-xl-{$params['xl-cols']}", ]; + foreach (self::$breakpoints as $breakpoint => $_) { + $paramKey = "{$breakpoint}-cols"; + if (isset($params[$paramKey])) { + $className[] = "max-col-{$breakpoint}-{$params[$paramKey]}"; + } + } + self::$paramsStack[] = $params; $content = $parser->recursiveTagParseFully($text, $frame); array_pop(self::$paramsStack); diff --git a/modules/masonry/ext.isekai.masonry.base.js b/modules/masonry/ext.isekai.masonry.base.js index 7d8aa56..8e09a73 100644 --- a/modules/masonry/ext.isekai.masonry.base.js +++ b/modules/masonry/ext.isekai.masonry.base.js @@ -18,14 +18,8 @@ function debounce(func, wait, immediate) { }; } -$(function () { - let masonry = new isekai.lib.Masonry('.isekai-masonry', { - itemSelector: '.isekai-masonry-item', - columnWidth: '.isekai-masonry-sizer', - gutter: '.isekai-masonry-gutter-sizer', - percentPosition: true - }); - +function observeResize(masonry) { + console.log('ResizeObserver supported'); let resizeObserver = new ResizeObserver(debounce(function () { console.log('masonry resize'); masonry.layout(); @@ -35,4 +29,43 @@ $(function () { items.forEach(function (item) { resizeObserver.observe(item); }); +} + +function observeResizeFallback(masonry) { + console.log('ResizeObserver not supported, using fallback'); + let itemHeights = []; + let items = document.querySelectorAll('.isekai-masonry-item'); + items.forEach(function (item) { + itemHeights.push(item.clientHeight); + }); + + setInterval(function () { + let isResized = false; + items.forEach(function (item, index) { + if (item.clientHeight !== itemHeights[index]) { + isResized = true; + itemHeights[index] = item.clientHeight; + } + }); + + if (isResized) { + console.log('masonry resize'); + masonry.layout(); + } + }, 1000); +} + +$(function () { + let masonry = new isekai.lib.Masonry('.isekai-masonry', { + itemSelector: '.isekai-masonry-item', + columnWidth: '.isekai-masonry-sizer', + gutter: '.isekai-masonry-gutter-sizer', + percentPosition: true + }); + + if (typeof ResizeObserver !== 'undefined') { + observeResize(masonry); + } else { + observeResizeFallback(masonry); + } }); \ No newline at end of file diff --git a/modules/masonry/ext.isekai.masonry.css b/modules/masonry/ext.isekai.masonry.css new file mode 100644 index 0000000..66c7b7e --- /dev/null +++ b/modules/masonry/ext.isekai.masonry.css @@ -0,0 +1,315 @@ +.isekai-masonry { + display: block; + width: 100%; + --masonry-col-width: 50%; +} +.isekai-masonry .isekai-masonry-gutter-sizer { + width: 0; + width: var(--masonry-gutter); +} +.isekai-masonry .isekai-masonry-sizer { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); +} +.isekai-masonry .isekai-masonry-item { + margin-bottom: var(--masonry-gutter); +} +.isekai-masonry .col-1 { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); +} +.isekai-masonry .col-2 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-3 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-4 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-5 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-6 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-7 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-8 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-9 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-10 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-11 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px)); +} +.isekai-masonry .col-12 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px)); +} +@media (min-width: 576px) { + .isekai-masonry .col-xs-1 { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); + } + .isekai-masonry .col-xs-2 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-3 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-4 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-5 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-6 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-7 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-8 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-9 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-10 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-11 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xs-12 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px)); + } +} +@media (min-width: 768px) { + .isekai-masonry .col-sm-1 { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); + } + .isekai-masonry .col-sm-2 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-3 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-4 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-5 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-6 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-7 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-8 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-9 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-10 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-11 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-sm-12 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px)); + } +} +@media (min-width: 992px) { + .isekai-masonry .col-md-1 { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); + } + .isekai-masonry .col-md-2 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-3 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-4 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-5 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-6 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-7 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-8 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-9 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-10 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-11 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-md-12 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px)); + } +} +@media (min-width: 1200px) { + .isekai-masonry .col-lg-1 { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); + } + .isekai-masonry .col-lg-2 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-3 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-4 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-5 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-6 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-7 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-8 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-9 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-10 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-11 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-lg-12 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px)); + } +} +@media (min-width: 1400px) { + .isekai-masonry .col-xl-1 { + width: 100%; + width: calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px); + } + .isekai-masonry .col-xl-2 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-3 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-4 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-5 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-6 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-7 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-8 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-9 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-10 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-11 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px)); + } + .isekai-masonry .col-xl-12 { + width: 100%; + width: min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px)); + } +} + diff --git a/modules/masonry/ext.isekai.masonry.less b/modules/masonry/ext.isekai.masonry.less deleted file mode 100644 index a5b483f..0000000 --- a/modules/masonry/ext.isekai.masonry.less +++ /dev/null @@ -1,80 +0,0 @@ -.isekai-masonry { - display: block; - width: 100%; - --masonry-col-width: 50%; - - .isekai-masonry-gutter-sizer { - width: 0; - width: ~"var(--masonry-gutter)"; - } - - .isekai-masonry-sizer { - width: 100%; - width: ~"calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px)"; - } - - .isekai-masonry-item { - margin-bottom: ~"var(--masonry-gutter)"; - } - - // Column width tools - .col-1 { - width: 100%; // Fallback - width: ~"calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px)"; - } - - .col-2 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 2 - var(--masonry-gutter) - 1px))"; - } - - .col-3 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 3 - var(--masonry-gutter) - 1px))"; - } - - .col-4 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 4 - var(--masonry-gutter) - 1px))"; - } - - .col-5 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 5 - var(--masonry-gutter) - 1px))"; - } - - .col-6 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 6 - var(--masonry-gutter) - 1px))"; - } - - .col-7 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 7 - var(--masonry-gutter) - 1px))"; - } - - .col-8 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 8 - var(--masonry-gutter) - 1px))"; - } - - .col-9 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 9 - var(--masonry-gutter) - 1px))"; - } - - .col-10 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 10 - var(--masonry-gutter) - 1px))"; - } - - .col-11 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 11 - var(--masonry-gutter) - 1px))"; - } - - .col-12 { - width: 100%; - width: ~"min(100%, calc(var(--masonry-col-width) * 12 - var(--masonry-gutter) - 1px))"; - } -} \ No newline at end of file diff --git a/src/masonry/ext.isekai.masonry.js b/src/masonry/ext.isekai.masonry.js index e8ea8a2..48e1076 100644 --- a/src/masonry/ext.isekai.masonry.js +++ b/src/masonry/ext.isekai.masonry.js @@ -1,3 +1,4 @@ +import './ext.isekai.masonry.less'; import Masonry from "masonry-layout"; import { registerModule } from "../moduleRegister"; diff --git a/src/masonry/ext.isekai.masonry.less b/src/masonry/ext.isekai.masonry.less new file mode 100644 index 0000000..db6e9e8 --- /dev/null +++ b/src/masonry/ext.isekai.masonry.less @@ -0,0 +1,52 @@ +@breakpoints: { + xs: 576px; + sm: 768px; + md: 992px; + lg: 1200px; + xl: 1400px; +}; + +.make-masonry-grids(@breakpoint: 0) { + @prefix: if(iskeyword(@breakpoint), ~"@{breakpoint}-", ); + + .col-@{prefix}1 { + width: 100%; // Fallback + width: ~"calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px)"; + } + + each(range(2, 12, 1), { + .col-@{prefix}@{value} { + width: 100%; + width: ~"min(100%, calc(var(--masonry-col-width) * @{value} - var(--masonry-gutter) - 1px))"; + } + }); +} + +.isekai-masonry { + display: block; + width: 100%; + --masonry-col-width: 50%; + + .isekai-masonry-gutter-sizer { + width: 0; + width: ~"var(--masonry-gutter)"; + } + + .isekai-masonry-sizer { + width: 100%; + width: ~"calc(var(--masonry-col-width) - var(--masonry-gutter) - 1px)"; + } + + .isekai-masonry-item { + margin-bottom: ~"var(--masonry-gutter)"; + } + + // Column width tools + .make-masonry-grids(); + + each(@breakpoints, { + @media (min-width: @value) { + .make-masonry-grids(@key); + } + }); +} \ No newline at end of file