如何使用弹性框重新排序 div?
Posted
技术标签:
【中文标题】如何使用弹性框重新排序 div?【英文标题】:How to reorder divs using flex box? 【发布时间】:2018-02-03 15:08:28 【问题描述】:我试图为我的 DOM 保持一个 seo 友好和语义结构,而不是重复整个元素以将它们显示在不同的位置。
我的布局基于display: flex
项目。我尝试实现以下目标:
需要了解的重要事项:
我不想根据窗口宽度显示/隐藏 div(以避免不必要的重复) 所有 div 都没有已知或固定的高度 在台式机上 div 应该垂直居中,而右列构建一个标签组(表现得像一个 div) 布局需要至少支持 IE11+是否有唯一的 css 解决方案来实现这一点?
如果没有,使用 javascript 将绿色的 div 剪下并将其内容粘贴到粉红色的 div 中会很容易。但是我确实担心使用它的性能和“闪烁”,尽管调整浏览器的大小会使它变得更加复杂。我是否让这变得不必要的复杂?
这里是一个显示工作解决方案但使用 javascript 的小提琴:
CODEPEN DEMO
【问题讨论】:
Flexbox 有一个order
属性正是为了这个目的。如果您希望 html 中的第二个 div 显示在顶部,您可以在 CSS 中为该 div 执行 order: 1
。
基本上,这对于 flexbox 来说是非常困难,如果不是不可能的话。许多浏览器不支持任何必需的属性。 CSS Grid 可能是一个选项。
@cjl750 感谢您的提示。如果您仔细阅读或查看演示(我在其中使用过),您会发现这并不能解决问题,但可以作为解决问题的开始。
@Paulie_D 关于 CSS 网格的一个问题是,它们经常使用 float
s。使用浮点数很容易实现,而您需要将一个对象定义为“更高”的对象。如果我不能做到这一点,我认为很难找到一个有效的浮动解决方案......而不是我猜的 javascript。
CSS Grid 与float
没有任何关系。这是一种完全不同的布局方法......因此大写“G”。
【参考方案1】:
一般来说,您不能单独使用 Flexbox 来做到这一点,尽管可能会根据每个给定的情况做出妥协。
单独使用 Flexbox,使用固定高度,就可以做到这一点
*
box-sizing: border-box;
body, html
margin: 0;
.flex
width: 90%;
margin: 5vh auto;
height: 90vh;
background: rgba(0, 0, 0, 0.05);
display: flex;
flex-flow: column wrap;
.flex div
flex: 1;
width: 50%;
.flex div:nth-child(2)
order: -1;
.flex::before
content: '';
height: 100%;
@media (max-width:768px)
.flex div
width: auto;
.flex::before
display: none;
.flex div:nth-child(2)
order: 0;
/* styling */
.flex-child
color: white;
font-size: 2em;
font-weight: bold;
.flex-child:nth-child(1)
background: #e6007e;
.flex-child:nth-child(2)
background: #f4997c;
.flex-child:nth-child(3)
background: #86c06b;
<div class="flex">
<div class="flex-child">
<div>Top/Right</div>
</div>
<div class="flex-child">
<div>Center/Left</div>
</div>
<div class="flex-child">
<div>Bottom/Right</div>
</div>
</div>
在这种情况下,不允许固定高度,您可以将 Flexbox 和 float
结合使用。
通过使用 Flexbox 为移动设备设置它,您首先在标记中添加 center 项,然后使用 order
在 top 和 底部。
通过媒体查询,您只需将 flex 容器 设为块元素并使用float
将 left 定位在左侧,right 向右。
*
box-sizing: border-box;
body, html
margin: 0;
.flex
max-width: 1024px;
width: 90%;
margin: 5vh auto;
height: 90vh;
background: rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
.flex-child
color: white;
font-size: 2em;
font-weight: bold;
padding: 5%;
flex-basis: 33.333%;
display: flex;
align-items: center;
.flex-child:nth-child(1)
background: #e6007e;
order: 1;
.flex-child:nth-child(2)
background: #f4997c;
.flex-child:nth-child(3)
background: #86c06b;
order: 2;
@media (min-width: 768px)
.flex
display: block;
.flex-child
width: 50%;
.flex-child:nth-child(1)
float: left;
height: 100%;
.flex-child:nth-child(2),
.flex-child:nth-child(3)
float: right;
height: 50%;
<div class="flex">
<div class="flex-child">
<div>Center/Left</div>
</div>
<div class="flex-child">
<div>Top/Right</div>
</div>
<div class="flex-child">
<div>Bottom/Right</div>
</div>
</div>
更新
这是另一个结合 Flexbox 和position: absolute
的版本,它也可以在桌面模式
已更新,添加了一个脚本来控制,因此绝对定位的元素不会比正确的项目大,如果是这样,请调整 flex 容器的高度。
请注意,该脚本绝不是优化的,它只是显示在某些情况下如何修复
(function()
window.addEventListener("resize", resizeThrottler, false);
var fp = document.querySelector('.flex');
var fi = fp.querySelector('.flex-child:nth-child(1)');
var resizeTimeout;
function resizeThrottler()
// ignore resize events as long as an actualResizeHandler execution is in the queue
if ( !resizeTimeout )
resizeTimeout = setTimeout(function()
resizeTimeout = null;
actualResizeHandler();
// The actualResizeHandler will execute at a rate of 15fps
, 66);
function actualResizeHandler()
// handle the resize event
if (fp.offsetHeight <= fi.offsetHeight)
fp.style.cssText = 'height: '+fi.offsetHeight+'px';
else
fp.style.cssText = 'height: auto';
window.addEventListener('load', function()
actualResizeHandler();
)
());
*
box-sizing: border-box;
body, html
margin: 0;
.flex
position: relative;
max-width: 1024px;
width: 90%;
margin: 5vh auto;
height: 90vh;
background: rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
.flex-child
color: white;
font-size: 2em;
font-weight: bold;
padding: 5%;
.flex-child:nth-child(1)
order: 1;
.flex-child:nth-child(3)
order: 2;
.flex-child:nth-child(1) div
background: #e6007e;
.flex-child:nth-child(2) div
background: #f4997c;
.flex-child:nth-child(3) div
background: #86c06b;
@media (min-width: 768px)
.flex
justify-content: center;
.flex-child
width: 50%;
.flex-child:nth-child(1)
position: absolute;
top: 50%;
transform: translateY(-50%);
.flex-child:nth-child(n+2)
margin-left: 50%;
<div class="flex">
<div class="flex-child">
<div>Center/Left<br>with more<br>content<br>than any<br>of the<br>other items<br>other items<br>other items<br>other items<br>other items</div>
</div>
<div class="flex-child">
<div>Top/Right<br>with more<br>content</div>
</div>
<div class="flex-child">
<div>Bottom/Right<br>with more</div>
</div>
</div>
使用脚本还可以在元素之间重新排序/移动项目。
堆栈sn-p
您还可以将其与媒体查询结合使用,并使用它对元素进行实际的重新排序
$( document ).ready(function()
$(window).resize(function()
if ($( window ).width() < 600 )
$(".one").insertBefore("#b");
else
$(".one").insertBefore(".two");
);
);
.outer, #flex, #flex2
display: flex;
flex-direction: column;
#a
order: 4;
background: #ccc;
#b
order: 1;
background: #aaa;
#c
order: 3;
background: #d33;
.one
order: 2;
background: #aaa;
.two
order: 5;
background: #aaa;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer">
<div id="flex">
<div id="a">A</div>
<div id="b">B</div>
<div id="c">C</div>
</div>
<div id="flex2">
<div class="one">Show me 2nd</div>
<div class="two">Show me 5th</div>
</div>
</div>
更新 2(已回复 at another question 但后来移至此处)
如果我们谈论较小的项目,例如标题或较小的菜单,则可以执行许多网站平台提供商(例如“squarespace”、“weebly”、“wordpress”等)所做的事情。他们的模板包含不同的标记结构,其中一个项目有时存在两次,一个在桌面上可见,另一个在移动设备上可见。
此外,如此之小,在性能方面几乎没有什么问题(而且我个人认为这没有什么问题,而不是重复的 CSS 规则,每个屏幕尺寸都有一个规则,并且很乐意这样做而不是介绍脚本)。
Fiddle demo
堆栈sn-p
.container
display: flex;
.container > div
width: 50%;
.container div:nth-child(-n+2)
border: dashed;
padding: 10px;
.container > div:nth-child(1)
display: none; /* hide outer "Flower" */
@media (max-width:768px)
.container
flex-direction: column;
.container div
width: auto;
.container div:nth-child(1)
display: block; /* show outer "Flower" */
.container div:nth-child(3) div:nth-child(1)
display: none; /* hide inner "Flower" */
<div class="container">
<div>Flower</div>
<div>Tree</div>
<div>
<div>Flower</div>
<div>Bee</div>
</div>
</div>
【讨论】:
感谢您的回答和时间。虽然此代码在固定高度 (50%
) 下工作,但它在未知高度下无法完成相同的工作。这就是使用float
作为解决方案的问题。在我的情况下,在没有已知高度的情况下将其垂直居中的部分很重要。
@MarianRick 我更新了它以桌面模式为中心...顺便说一句,你投反对票了吗??
再次感谢。正如我试图在图像中暗示的那样,它不是关于将每个 div 的内容集中在右列中。这是关于将两个 div “作为一个标签团队”居中。这样它们就表现为一个单独的 div,它与左 div 垂直对齐。这就是为什么在粉色 div 上方和绿色 div 下方有空白区域。你明白我的意思还是我应该创建一个例子?
是的。不是为了伤害或冒犯您,而是为了保存本网站内容的质量。目前,您的解决方案解决了问题中提出的另一个问题。当然,如果它针对问题中所述的确切问题,我会更改它。在这个 codepen 中有一个使用 javascript 的工作演示。我开始质疑,如果没有 js 是否可能:codepen.io/marianrick/pen/wqxVOg?editors=1010
@MarianRick 好吧,当有人积极地帮助你时,投反对票是一种不好的方式来表达感谢你帮助我。当我停止询问和改进,给你留下一个我能理解的无效解决方案时......不过,当有人以任何方式帮助你时,我发现很难理解反对票......以上是关于如何使用弹性框重新排序 div?的主要内容,如果未能解决你的问题,请参考以下文章