灵活布局:这可能吗?

Jon*_*sta 6 css flexbox

编辑\n请记住,每个单元格可以有不同的宽度和高度。这与这篇文章不同:CSS-only masonry layout,请参阅参考图片的指导线:

\n

在此输入图像描述

\n

由放置在虚拟 5\xc3\x975 基本网格中的引导线和图块组成的大约 19 列和 17 行在两个轴上重叠。

\n

我想要介于网格和弹性布局之间的东西。网格受到单元格大小的限制,而 flex 更强大,但(据我所知)仅限于方向。我想要不同的单元格大小,其中每 5 个单元格的宽度总和相同,并且 5 个列的总和高度相同。就像下图一样。

\n

有没有办法使用 CSS 实现类似的布局?

\n

在此输入图像描述

\n

这是我到目前为止所得到的一切:

\n

HTML:

\n
<div class="calendar">\n  <div class="day day1">1</div>\n  <div class="day day2">2</div>\n  <div class="day day3">3</div>\n  <div class="day day4">4</div>\n  <div class="day day5">5</div>\n  <div class="day day6">6</div>\n  <div class="day day7">7</div>\n  <div class="day day8">8</div>\n  <div class="day day9">9</div>\n  <div class="day day10">10</div>\n  <div class="day day11">11</div>\n  <div class="day day12">12</div>\n  <div class="day day13">13</div>\n  <div class="day day14">14</div>\n  <div class="day day15">15</div>\n  <div class="day day16">16</div>\n  <div class="day day17">17</div>\n  <div class="day day18">18</div>\n  <div class="day day19">19</div>\n  <div class="day day20">20</div>\n  <div class="day day21">21</div>\n  <div class="day day22">22</div>\n  <div class="day day23">23</div>\n  <div class="day day24">24</div>\n  <div class="day day25">25</div>\n</div>\n
Run Code Online (Sandbox Code Playgroud)\n

CSS:

\n
.day {\n  margin: 10px;\n  color: white;\n}\n\n.calendar {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  align-content: flex-start;\n  width: 586px;\n  height: 586px;\n  border: solid 1px;\n}\n\n.day1 {\n  width: 87px;\n  height: 97px;\n  background: lightblue;\n}\n\n.day2 {\n  width: 151px;\n  height: 86px;\n  background: orange;\n}\n\n.day3 {\n  width: 86px;\n  height: 86px;\n  background: lightcoral;\n}\n\n.day4 {\n  width: 76px;\n  height: 118px;\n  background: lightgray;\n}\n\n.day5 {\n  width: 86px;\n  height: 86px;\n  background: lightblue;\n}\n\n.day6 {\n  width: 87px;\n  height: 86px;\n  background: lightsteelblue;\n}\n\n.day7 {\n  width: 108px;\n  height: 97px;\n  background: lightblue;\n}\n\n.day8 {\n  width: 129px;\n  height: 97px;\n  background: lightsteelblue;\n}\n\n.day9 {\n  width: 76px;\n  height: 65px;\n  background: orange;\n}\n\n.day10 {\n  width: 86px;\n  height: 128px;\n  background: cyan;\n}\n\n.day11 {\n  width: 75px;\n  height: 75px;\n  background: lightcoral;\n}\n\n.day12 {\n  width: 99px;\n  height: 96px;\n  background: lightgray;\n}\n\n.day13 {\n  width: 87px;\n  height: 96px;\n  background: lightcyan;\n}\n\n.day14 {\n  width: 139px;\n  height: 96px;\n  background: orange;\n}\n\n.day15 {\n  width: 86px;\n  height: 65px;\n  background: lightcoral;\n}\n\n.day16 {\n  width: 75px;\n  height: 118px;\n  background: orange;\n}\n\n.day17 {\n  width: 88px;\n  height: 97px;\n  background: lightcoral;\n}\n\n.day18 {\n  width: 161px;\n  height: 97px;\n  background: cyan;\n}\n\n.day19 {\n  width: 98px;\n  height: 118px;\n  background: lightgreen;\n}\n\n.day20 {\n  width: 64px;\n  height: 97px;\n  background: lightgray;\n}\n\n.day21 {\n  width: 108px;\n  height: 97px;\n  background: lightsteelblue;\n}\n\n.day22 {\n  width: 150px;\n  height: 97px;\n  background: lightblue;\n}\n\n.day23 {\n  width: 65px;\n  height: 97px;\n  background: lightgray;\n}\n\n.day24 {\n  width: 98px;\n  height: 75px;\n  background: orange;\n}\n\n.day25 {\n  width: 65px;\n  height: 97px;\n  background: lightblue;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

https://codepen.io/jonathascosta/pen/yLzPPxz

\n

myf*_*myf 1

“正确”的答案

\n

否。包裹的弹性项目仅分布在单个(主轴)轴上。没有自动机制告诉包装项目,它在先前或后续运行(上方或下方的行)中的辅助轴上的同级项目与某些边界重叠,因此应该影响不同行中的项目。由于您的设计涉及两个轴上的重叠,因此无法定义项目的尺寸/变换,也无法让弹性盒布局单独进行数学运算以产生所需的平衡分布。

\n

技术上正确的答案

\n

是的。但仅限于精确的“手工制作”风格。

\n

如上所述,您必须手动为辅助轴上的所有“离网”重叠设置额外的属性。这意味着对于辅助,一行中的每个“扩展”项目必须具有手动“压缩”对应项在相邻行中手动“压缩”对应项。当然,只有当包裹完全按照设计进行时,这才有效。

\n

让我们看一下简化的设计示例:

\n
aaaaaaa..b..cccc\naaaaaaa..b..cccc\naaaaaaa..b..cccc\n............cccc\ndddd..eeee..cccc\n......eeee......\ngggg..eeee..ffff\ngggg............\ngggg..h..iiiiiii\ngggg..h..iiiiiii\ngggg..h..iiiiiii\n
Run Code Online (Sandbox Code Playgroud)\n

a和区域以区域和i为代价横向扩展。同样适用于-和-hbcfdg对,只是垂直方向。正如我们所看到的,两个轴上都发生重叠。假设我们需要四个重叠中的每一个都具有唯一的大小。

\n

使用自定义属性设置宽度/高度“重叠”和相应的辅助轴(垂直)调整的 POC 可以是:

\n

\r\n
\r\n
aaaaaaa..b..cccc\naaaaaaa..b..cccc\naaaaaaa..b..cccc\n............cccc\ndddd..eeee..cccc\n......eeee......\ngggg..eeee..ffff\ngggg............\ngggg..h..iiiiiii\ngggg..h..iiiiiii\ngggg..h..iiiiiii\n
Run Code Online (Sandbox Code Playgroud)\r\n
section {\n --base: 9em; /* width & height */\n --add: calc(var(--base) / 8); /* "unit" for overlap adjustments */\n --gap: calc(var(--base) / 20);\n --cols: 3; /* example HTML works with 3 only */\n --dim: calc( ( var(--cols) * var(--base) ) + ( ( var(--cols) - 1 ) * var(--gap) ) );\n width: var(--dim);\n height: var(--dim);\n gap: var(--gap);\n\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n}\narticle {\n width: calc( var(--base) + ( var(--add) * var(--wdt, 0) ) );\n margin-bottom: calc( var(--add) * var(--hgh,0) * -1 ); /* expanded items will "pull" next row back */\n position: relative;\n top: calc( var(--add) * var(--top,0) * 1 );\n height: calc( var(--base) + ( var(--add) * var(--hgh,0) ) );\n}\n\n/*\nIllustrative\n*/\nsection {\n outline: #F0F6 solid; outline-offset: -2px;\n}\narticle {\n outline: #0FF6 solid; outline-offset: -2px;\n background-color: rgba(0,0,0,0.2);\n align-items: center;\n display: flex;\n justify-content: center;\n flex-direction: column;\n counter-increment: a;\n word-break: break-word;\n text-align: center;\n}\narticle::before { content: counter(a, lower-alpha); }\narticle::after { content: attr(style); }\n:root { background: dimgray; color: snow; }\n:link { color: aqua; } :visited { color: lime; }
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

这具有相当好的灵活性,可以将任何值设置为重叠。

\n

他们说“使用网格”

\n

对于我们相当复杂的示例设计(以“3 \xc3\x97 3”为基础)的网格布局将涉及至少 5 \xc3\x97 5 网格定义:

\n

\r\n
\r\n
<section>\n <article style="--wdt: +1;"></article>\n <article style="--wdt: -1;"></article>\n <article style="--hgh: +2;"></article>\n\n <article style="--hgh: -4"></article>\n <article style="/* defaults */"></article>\n <article style="--hgh: -2; --top: +2"></article>\n\n <article style="--hgh: +4; --top: -4;"></article>\n <article style="--wdt: -3;"></article>\n <article style="--wdt: +3;"></article>\n</section>
Run Code Online (Sandbox Code Playgroud)\r\n
section {\n grid-template: \n"a a b b c" 60fr\n"d e e e c" 10fr\n"d e e e f" 20fr\n"g e e e f" 30fr\n"g h h i i" 60fr\n/60fr\n   05fr\n     20fr\n       35fr\n         60fr;\n --base: 9em; /* item width & height */\n --gap: calc(var(--base) / 20);\n --cols: 3; /* example HTML works with 3 only */\n --dim: calc( ( var(--cols) * var(--base) ) + ( ( var(--cols) - 1 ) * var(--gap) ) );\n width: var(--dim);\n height: var(--dim);\n gap: var(--gap);\n outline: #F0F6 solid; outline-offset: -2px;\n display: grid;\n}\n\n/*\nIllustrative\n*/\narticle {\n outline: #0FF6 solid;\n outline-offset: -2px;\n background-color: rgba(0,0,0,.3);\n align-items: center;\n display: flex;\n justify-content: center;\n flex-direction: column;\n counter-increment: a;\n word-break: break-word;\n text-align: center;\n}\narticle::before {\n content: counter(a, lower-alpha);\n}\narticle::after {\n content: attr(style);\n}\n:root { background: dimgray; color: snow; }\n:link { color: aqua; } :visited { color: lime; }
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

这种方法的缺点是列-行对上的每个重叠实例都需要额外的列-行定义。问题 (5 \xc3\x97 5) 的具体设计至少需要 19 \xc3\x97 17 网格定义。

\n
\n

请注意,这两个 POC 都是合成的,并且涉及相当现代的内容gapFlex-box。现实世界的使用很可能比这更复杂。

\n
\n

优雅的网格方法

\n

简单的刚性网格和仅用边距完成的不规则调整。

\n

这种方法取自这个问题的其他答案,所有的荣誉都在那里。

\n

我不知道margin网格项目可以做到这一点;添加示例只是为了完整性。使用与第一个弹性框示例类似的逻辑:

\n

\r\n
\r\n
<section class="grid">\n <article style="grid-area: a"></article>\n <article style="grid-area: b"></article>\n <article style="grid-area: c;"></article>\n\n <article style="grid-area: d;"></article>\n <article style="grid-area: e;"></article>\n <article style="grid-area: f;"></article>\n\n <article style="grid-area: g;"></article>\n <article style="grid-area: h;"></article>\n <article style="grid-area: i;"></article>\n</section>
Run Code Online (Sandbox Code Playgroud)\r\n
section {\n --base: 9em; /* item width & height */\n --add: calc(var(--base) / 8); /* "unit" for overlap adjustments */\n --gap: calc(var(--base) / 20);\n --cols: 3; /* example HTML works with 3 only */\n --dim: calc( ( var(--cols) * var(--base) ) + ( ( var(--cols) - 1 ) * var(--gap) ) );\n width: var(--dim);\n height: var(--dim);\n gap: var(--gap);\n display: grid;\n grid-auto-rows: 1fr;\n grid-template-columns: repeat(var(--cols), 1fr);\n}\narticle {\n margin-top: calc( var(--top,0) * var(--add) * -1 );\n margin-right: calc( var(--right,0) * var(--add) * -1 );\n margin-bottom: calc( var(--bottom,0) * var(--add) * -1 );\n margin-left: calc( var(--left,0) * var(--add) * -1 );\n}\n/*\nIllustrative\n*/\nsection {\n outline: #F0F6 solid; outline-offset: -2px;\n}\narticle {\n outline: #0FF6 solid;\n outline-offset: -2px;\n background-color: rgba(0,0,0,.3);\n align-items: center;\n display: flex;\n justify-content: center;\n flex-direction: column;\n counter-increment: a;\n word-break: break-word;\n text-align: center;\n}\narticle::before {\n content: counter(a, lower-alpha);\n}\narticle::after {\n content: attr(style);\n}\n:root { background: dimgray; color: snow; }\n:link { color: aqua; } :visited { color: lime; }
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

我认为这是最优雅、最通用的方式,并且很好地利用了刚性网格进行设计。手动“数字提升”仍然令人畏惧 - 特别是当需要移动行的“其余”或更糟糕的整个“表”时 - 但即便如此,它似乎是最直观的。再次感谢 Laaouatni Anas 将其带到这里。

\n
\n

务实的老派方法:“abspos”

\n

对于真正狂野的刚性不规则设计,请考虑绝对定位。当代码模式中可以容纳一些规则时,所示的弹性盒和第一种网格方法可能对使用有意义。否则,对所有内容使用简单的绝对定位和手动尺寸或使用第二个网格的类似方法可能是同样可行的方法。听起来很糟糕 - 将项目进一步向下或向右重新定位会很痛苦 - 但如果这被证明是此特定任务的最佳解决方案,我不会感到惊讶。

\n
\n