自动剪裁多行 flexbox
Posted
技术标签:
【中文标题】自动剪裁多行 flexbox【英文标题】:Autoclipping multi-line flexbox 【发布时间】:2022-01-22 21:51:08 【问题描述】:我需要在一张漂亮的表格中展示 8-9 张卡片,每行有 2-4 行和 2-4 个元素。所有行都有相同数量的元素。
即根据容器元素的宽度,用户应该看到以太 8 或 9 卡:
C1 C2 C3 C4
C5 C6 C7 C8
或
C1 C2 C3
C4 C5 C6
C7 C8 C9
或
C1 C2
C3 C4
C5 C6
C7 C8
如果没有媒体查询,我该怎么做?
最自然的方式似乎是带有flex-wrap: wrap
的flexbox,但是如何解释flexbox 如果它只包含一个元素,我需要隐藏一行?有只有css的解决方案吗?我可以用 javascript 检测一个包装的 flexbox 有多少行吗?
【问题讨论】:
媒体查询有什么问题,它们是响应式设计的基本组件/ @Paulie_D,媒体查询将无法预测,因为 flexbox 容器可以占据页面的任意部分。您在这里需要容器查询,而不是媒体查询,但容器查询不是当前 CSS 的一部分。 【参考方案1】:Flexbox 结合flex-wrap: wrap
和媒体查询可以是一个很好的解决方案。
您可以设置多个断点并为不同的屏幕尺寸创建不同的行为。这可以是(除了设置flex-basis
)也可以用display: none
隐藏最后一个元素
使用移动优先的方法,您可以这样做:
.wrapper
display: flex;
flex-wrap: wrap;
.wrapper div
flex-basis: 50%;
.wrapper div:last-child
display: none;
@media (min-width: 600px)
.wrapper div
flex-basis: 33.33%;
.wrapper div:last-child
display: block;
@media (min-width: 992px)
.wrapper div
flex-basis: 25%;
.wrapper div:last-child
display: none;
<div class="wrapper">
<div>C1</div>
<div>C2</div>
<div>C3</div>
<div>C4</div>
<div>C5</div>
<div>C6</div>
<div>C7</div>
<div>C8</div>
<div>C9</div>
</div>
【讨论】:
太棒了。这是艺术 很抱歉,我特意问了一句“没有媒体查询我该怎么做?”。如果您的包装器占用页面的任意部分,媒体查询将无法正常工作。 对不起,我被错字弄糊涂了(“没有”是一起写的)......无论如何我不知道你的确切实现,但是使用MQ你也可以控制包装器的宽度(取决于视口宽度)并确保它按预期工作。这还不够吗? @TomasKorinek,你是什么意思?我需要我的容器元素是它们已经是的宽度,独立于它们的内部内容,包括表格的这个解决方案。 Card table 必须完全适合我放入的元素,并且这些元素的宽度和它对媒体查询的依赖已经确定。 再来一次:卡表布局必须依赖于包含卡表的元素的宽度,而不是页面的宽度。这就是我要解决的问题。【参考方案2】:最好的办法是使用容器查询,但不幸的是,到 2021 年它们现在还没有得到广泛支持。除此之外,我不知道没有媒体查询的这个确切问题的纯 CSS 解决方案。
我仍然相信媒体查询是一个很好的解决方案(如果您能够找到视口宽度和容器宽度之间的关系),但由于您坚持不使用它们,您唯一的方法是使用一些 javascript (虽然布局依赖于 JS 可能不是一个好主意)。
一种方法是使用已经制作的库之一(例如EQCSS),但如果您想拥有自己的解决方案,您可以模拟容器查询,例如这样。
$(function()
updateWrapper(); // call on page load
$(window).on('resize', function()
updateWrapper(); // update on window resize
);
);
function updateWrapper()
var innerWrapper = $('.wrapper > div'); // get inner wrapper
innerWrapper.removeClass(); // remove previously set class
var elWidth = $('.wrapper').width(); // get container width
if(elWidth < 600) // set class according to container width
innerWrapper.addClass('mobile');
else if (elWidth >= 600 && elWidth < 992)
innerWrapper.addClass('tablet');
else
innerWrapper.addClass('desktop');
.wrapper
/* width: 400px; // use any value here */
background: lightgray;
.wrapper > div
display: flex;
flex-wrap: wrap;
.mobile div
flex-basis: 50%;
.mobile div:last-child
display: none;
.tablet div
flex-basis: 33.33%;
.tablet div:last-child
display: block;
.desktop div
flex-basis: 25%;
.desktop div:last-child
display: none;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div>
<div>C1</div>
<div>C2</div>
<div>C3</div>
<div>C4</div>
<div>C5</div>
<div>C6</div>
<div>C7</div>
<div>C8</div>
<div>C9</div>
</div>
</div>
【讨论】:
【参考方案3】:由于您决定在 JavaScrpt 中观察行数,因此使用 javascript 很容易完成布局(无论如何,您最终将使用 JavaScript,所以我认为这不值得一笑)。 如果没有,则使用媒体查询来控制元素的显示,并使用 grid 代替 flexbox,这样:
文档结构:
.container
#card1.card
#card2.card
...
#card8.card
#card9.card
.container
display: grid;
grid-template: 1fr 1fr 1fr / 1fr 1fr 1fr;
@media all and (min-width: 600px)
.container
grid-template: 1fr 1fr 1fr 1fr / 1fr 1fr;
.card:last-child
display: none;
等其他人...
【讨论】:
对不起,我特意问了一句“没有媒体查询怎么办?”。以上是关于自动剪裁多行 flexbox的主要内容,如果未能解决你的问题,请参考以下文章