我正在尝试以下列方式布局多个列。我正在使用Wordpress但编辑PHP,HTML,CSS等。
这是HTML。想象一下A B C作为代码块,没有固定的高度和百分比宽度,如图所示。
<div class="flex wrap">
<div class="main">A</div>
<div class="optional">B</div>
<div class="main2">C</div>
</div>
只要我使用flexbox,我就可以使用视口来改变flex的顺序。但是现在我无法获得所需的桌面布局。
我可以使用第二列的嵌套div的列(bootstrap)来创建桌面布局,但是移动布局将是BAC或ACB而不是ABC。
这是我的CSS:
.flex.wrap {
flex-wrap: wrap;
}
.flex {
display: flex!important; /* to override display:block */
}
.main {
order: 2;
flex: 0 75%;
}
.optional {
order: 1;
flex: 0 25%;
}
.main2 {
order: 3;
flex: 0 75%
}
我做了我的研究,并且看到了许多这样的问题,但没有任何满足我需要的满意答案。
我不必使用弹性盒子,我也不需要纯css解决方案 - 只要它可以在大多数现代浏览器和移动设备上使用。我只需要一些有用的东西。所以我对任何建议持开放态度。
我也可以在两个代码块上使用display: none
,但这会使代码增加67行,我认为不应该这样做。
即使有一个可能像下面这样工作的php解决方案,它也可能有用。
If (code that determines mobile viewport) echo html
else
echo nothing
另一个相同的代码,我想要桌面版本。我知道这不是优雅的,但最后我关心的是结果,包括表现而不是其他任何东西。
非常感谢任何帮助。
答案 0 :(得分:2)
由于您无法设置固定的高度,因此Flexbox无法单独执行此操作,因此要么将其与定位或脚本结合使用,要么使用CSS Grid(尽管浏览器支持少于Flexbox)。 / p>
以下是使用定位的示例,并使用原始代码示例中的类进行更新,以便更容易理解。
html, body {
margin: 0;
}
.wrapper {
position: relative;
}
.flex {
display: flex;
flex-direction: column;
}
.flex > div {
border: 1px solid;
box-sizing: border-box;
}
/* for desktop */
@media screen and (min-width: 600px) {
.flex > .optional {
position: absolute;
left: 0;
top: 0;
width: 25%;
height: 100%;
}
.flex .main,
.flex .main2 {
margin-left: 25%; /* match the width of the "optinal" */
}
}
&#13;
<div class="wrapper">
<div class="flex">
<div class="main">A</div>
<div class="optional">B</div>
<div class="main2">C</div>
</div>
</div>
&#13;
<强> 更新 强>
在某些情况下,人们根本无法使用绝对定位,例如当左右列(桌面模式)都可以超越另一列时。
以下是使用小脚本的版本,该脚本模仿媒体查询并将optional
元素移入和移出flex
容器。
它还会切换body
上的一个类,在这种情况下为mobileview
,它在CSS中用于切换wrapper
作为flex容器,并在optional
上设置适当的属性{1}}当它是wrapper
而不是flex
的弹性项目子时。{/ p>
使用脚本中的minwidth = 600
变量,可以控制布局应切换的宽度。
以下是fiddle demo也可以使用
(function(d, w, timeout) {
/* custom variables */
var flexcontainer = '.flex',
flexitem = '.optional',
minwidth = 600, /* if null, then when viewport is portrait */
classname = 'mobileview';
/* here happens the magic */
function resizeing() {
if ((minwidth && (minwidth < w.innerWidth)) ||
(!minwidth && (w.innerHeight < w.innerWidth))) {
if (!(d.body.classList.contains(classname))) {
/* move it outside the main flexcontainer */
d.body.classList.add(classname);
var fca = qSA(flexcontainer);
for (var i = 0; i < fca.length; i++) {
fca[i].parentNode.appendChild(qS(flexitem, fca[i]))
}
}
} else {
if (d.body.classList.contains(classname)) {
/* move it back inside the main flexcontainer */
d.body.classList.remove(classname)
var fca = qSA(flexcontainer);
for (var i = 0; i < fca.length; i++) {
fca[i].appendChild(qS(flexitem, fca[i].parentNode))
}
}
}
}
/* run at page load init resize */
w.addEventListener("load", function() {
resizeing();
}, false);
/* grab when viewport resize */
w.addEventListener("resize", function() {
if (!timeout) {
timeout = setTimeout(function() {
timeout = null;
resizeing();
}, 66);
}
}, false);
/* helper variables */
var qSA = function(s, el) {
return (el) ? el.querySelectorAll(s) :
d.querySelectorAll(s)
},
qS = function(s, el) {
return (el) ? el.querySelector(s) :
d.querySelector(s)
};
}(document, window));
&#13;
html, body {
margin: 0;
}
.wrapper .flex {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.wrapper .flex > div {
flex-grow: 1;
border: 1px solid;
box-sizing: border-box;
}
.wrapper .flex .optional {
order: 1;
}
.wrapper .flex .main2 {
order: 2;
}
/* for desktop */
.mobileview .wrapper {
display: flex;
}
.mobileview .wrapper .optional {
flex-basis: 25%;
order: -1;
border: 1px solid;
box-sizing: border-box;
}
&#13;
<div class="wrapper">
<div class="flex">
<div class="main">A</div>
<div class="optional">
B as a lot more content<br>
B as a lot more content<br>
B as a lot more content<br>
B as a lot more content<br>
B as a lot more content<br>
</div>
<div class="main2">C</div>
</div>
</div>
<h5>More than one container and other text etc.</h5>
<div class="wrapper">
<div class="flex">
<div class="main">
A as a lot more content<br>
A as a lot more content<br>
A as a lot more content<br>
A as a lot more content<br>
A as a lot more content<br>
</div>
<div class="optional">B</div>
<div class="main2">C</div>
</div>
</div>
&#13;
答案 1 :(得分:2)
更多信息用于提供有效答案此时。
您可以从flex
切换到grid
,其中
grid
允许设置行和&amp;列,订购也可以跨越的元素,flex
允许重新排序:实施例
body {
display: grid;
grid-template-columns: 25% 1fr;
grid-gap: 10px
}
.opt {
grid-column: 1;
grid-row: 1 / span 2;
background: gold
}
div {
background: turquoise
}
@media all and (max-width: 360px) {/* set here width where you need to switch layout */
body {
display: flex;
flex-flow: column
}
.a {
order: -2
}
.opt {
order: -1
}
div {
margin: 5px 10px
}
}
<div class="a">A of any height</div>
<div class="c">C of any height</div>
<div class="opt">B of any height</div>
如果网格看起来很有趣:https://css-tricks.com/snippets/css/complete-guide-grid/
答案 2 :(得分:1)
实现此布局的最有效方法是使用 CSS网格布局:
.container {
display: grid;
grid-template-columns: 25% 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 5px;
grid-template-areas: " B A "
" B C ";
}
.A { grid-area: A; }
.B { grid-area: B; }
.C { grid-area: C; }
@media ( max-width: 800px ) {
.container {
grid-template-columns: 1fr;
grid-template-areas: "A" "B" "C";
}
}
/* non-essential styles; for demo only */
.container { height: 200px; }
.A { background-color: aqua; }
.B { background-color: gold; }
.C { background-color: lightgreen; }
.container > div { display: flex; align-items: center; justify-content: center; }
<div class="container">
<div class="A">A</div>
<div class="B">B</div>
<div class="C">C</div>
</div>
以下是它的工作原理:
grid-template-columns
中的值数确定了列数。 grid-template-rows
的相同概念。grid-template-areas
属性允许您使用ASCII视觉艺术排列布局。将网格区域名称(为每个元素定义)放置在您希望它们出现的位置。fr
单位告诉列/行消耗可用空间。它类似于flex-grow
。 此外,原始HTML结构没有变化。它保持尽可能简单。并且不需要使用order
属性。
CSS网格的浏览器支持
以下是完整图片:http://caniuse.com/#search=grid
Flexbox问题
如果您可以在容器上设置固定高度,则可以使用flexbox 实现所需的桌面布局。
使用flex-flow: column wrap
,这将允许一个项目占用第一列中的所有空间。然后,第二个和第三个项目可以包装并共享第二列中的空间。您可以使用order
属性重新排列每个项目的位置。
但是,如上所述,容器上的固定高度是必要的,因为否则项目没有断点并且不会换行。
在行方向上,无法使用flexbox进行桌面布局,因为您要求项目包装在同一行中的另一个项目下。换句话说,“B”确定行的高度,然后您希望“C”包裹在该行的“A”下。这不是flexbox的工作方式。
以下是一个更完整的解释: