布局取决于元素数量

时间:2019-02-20 19:35:06

标签: html css flexbox alignment css-grid

我有一个可包含2、3或4个元素的包装器(我事先不知道,因为每个元素都会呈现自己,具体取决于API响应)。

如果有3个(或更少),我希望它们像这样堆叠:

3 elements layout

没什么大不了的。但是当它们有4个时,我需要其他布局:

4 elements layout

到目前为止,我认为CSS Grid将是解决之道,而我尝试了:

/* Just to add some interaction to the demo */

const w = document.getElementById("wrapper");
let x;

function toggle(event) {

  const d = document.getElementById("D");
  return d 
    ? 
      x = d.cloneNode() && w.removeChild(d) 
    : w.appendChild(x);
}
#wrapper {
  width: 100%;
  max-width: 500px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
}



.item {
  grid-column-start: span 2
}

.item:nth-last-child(1),
.item:nth-last-child(2) {
  grid-column-start: auto;
}


/* Non-relevant CSS here: */

button {
  margin: 20px auto;
  font-size: 16px;
  padding: 3px 6px;
  border-radius: 6px;
}

#A { background: #7984f7 }
#B { background: #cb8af8 }
#C { background: #8cd4fb }
#D { background: #97f8d8 }

.item {
  border-radius: 6px;
  padding: 10px 0;
  font-family: sans-serif;
  font-weight: bold;
  color: white;
  text-align: center;
}
<div id="wrapper">
  <div id="A" class="item">A</div>
  <div id="B" class="item">B</div>
  <div id="C" class="item">C</div>
  <div id="D" class="item">D</div>
</div>

<button onclick="toggle()">Click me!</button>

但是它不适用于3个元素...实际上,我已经尝试了很多事情(所有CSS Grid相关),并且可能有一个更简单的解决方案,我现在看不到...任何帮助非常感谢!

5 个答案:

答案 0 :(得分:3)

我建议使用flexbox。对于给定的三种可能性,请在下面的代码段中使用此简单的CSS。

基本上,您使这些项目连续显示,但如果不合适,则使用包装。您使前两个元素占据所有宽度,以便每行只有一个。对于第3个和第4个,将它们的flex-basis(初始宽度)设置为较小,并在有空间的情况下使其增长(flex-grow:1)。

HashMap
.examples{
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}
.container{
  width: 200px;
  border: 1px solid red;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
}
.box{
  height: 50px;
  background-color: blue;
  margin: 5px;
  border-radius: 5px;
  flex-basis: 200px;
}
.box:nth-child(3), .box:nth-child(4){
  flex-basis: 50px;
  flex-grow: 1;
}

解决方案也在这里:JSFiddle

答案 1 :(得分:2)

使用CSS网格:

  1. 默认在两列中显示所有项目
  2. 在单列中显示项目1和2
  3. 仅在最后一项显示项目3时才在单列显示

副作用是,如果项目多于4个,则其他项目将显示在两列中。

/* Just to add some interaction to the demo */

const w = document.getElementById("wrapper");
let x;

function toggle(event) {

  const d = document.getElementById("D");
  return d 
    ? 
      x = d.cloneNode() && w.removeChild(d) 
    : w.appendChild(x);
}
#wrapper {
  width: 100%;
  max-width: 500px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
}



.item {
  grid-column-start: auto;
}

.item:nth-child(1),
.item:nth-child(2),
.item:nth-child(3):last-child {
  grid-column-start: span 2;
}


/* Non-relevant CSS here: */

button {
  margin: 20px auto;
  font-size: 16px;
  padding: 3px 6px;
  border-radius: 6px;
}

#A { background: #7984f7 }
#B { background: #cb8af8 }
#C { background: #8cd4fb }
#D { background: #97f8d8 }

.item {
  border-radius: 6px;
  padding: 10px 0;
  font-family: sans-serif;
  font-weight: bold;
  color: white;
  text-align: center;
}
<div id="wrapper">
  <div id="A" class="item">A</div>
  <div id="B" class="item">B</div>
  <div id="C" class="item">C</div>
  <div id="D" class="item">D</div>
</div>

<button onclick="toggle()">Click me!</button>

答案 2 :(得分:2)

您可以使用:nth-child(n+4)选择第三个​​孩子之后的元素,并使用:nth-child(n+3)选择第二个孩子之后的元素并进行联想:< / p>

.item:nth-child(n+4):nth-last-child(1),
.item:nth-child(n+3):nth-last-child(2) {
  grid-column-start: auto;
}

现在,您具有要搜索的网格配置-适用于任意个数量的item元素-请参见下面的演示

/* Just to add some interaction to the demo */
const w = document.getElementById("wrapper");
let x;
function toggle(event) {
  const d = document.getElementById("D");
  return d ?
    x = d.cloneNode() && w.removeChild(d) :
    w.appendChild(x);
}
#wrapper {
  width: 100%;
  max-width: 500px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
}
.item {
  grid-column-start: span 2;
}
/* CHANGED THIS */
.item:nth-child(n+4):nth-last-child(1),
.item:nth-child(n+3):nth-last-child(2) {
  grid-column-start: auto;
}
/* Non-relevant CSS here: */
button {
  margin: 20px auto;
  font-size: 16px;
  padding: 3px 6px;
  border-radius: 6px;
}
#A {
  background: #7984f7
}
#B {
  background: #cb8af8
}
#C {
  background: #8cd4fb
}
#D {
  background: #97f8d8
}
.item {
  border-radius: 6px;
  padding: 10px 0;
  font-family: sans-serif;
  font-weight: bold;
  color: white;
  text-align: center;
}
<div id="wrapper">
  <div id="A" class="item">A</div>
  <div id="B" class="item">B</div>
  <div id="C" class="item">C</div>
  <div id="D" class="item">D</div>
</div>
<button onclick="toggle()">Click me!</button>

答案 3 :(得分:1)

这是一个有效的技巧。

第三个孩子也是倒数第二个孩子,并且第四个孩子的grid-column-start设置为auto。

.item:nth-child(3):nth-last-child(2),
.item:nth-child(4) {
  grid-column-start: auto;
}

如果您希望将第4位以上的所有孩子都分成两列,请稍作调整。

.item:nth-child(3):nth-last-child(2),
.item:nth-child(n+4) {
  grid-column-start: auto;
}

/* Just to add some interaction to the demo */

const w = document.getElementById("wrapper");
let x;

function toggle(event) {

  const d = document.getElementById("D");
  return d 
    ? 
      x = d.cloneNode() && w.removeChild(d) 
    : w.appendChild(x);
}
#wrapper {
  width: 100%;
  max-width: 500px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
}



.item {
  grid-column-start: span 2
}

.item:nth-child(3):nth-last-child(2),
.item:nth-child(n+4) {
  grid-column-start: auto;
}


/* Non-relevant CSS here: */

button {
  margin: 20px auto;
  font-size: 16px;
  padding: 3px 6px;
  border-radius: 6px;
}

#A { background: #7984f7 }
#B { background: #cb8af8 }
#C { background: #8cd4fb }
#D { background: #97f8d8 }

.item {
  border-radius: 6px;
  padding: 10px 0;
  font-family: sans-serif;
  font-weight: bold;
  color: white;
  text-align: center;
}
<div id="wrapper">
  <div id="A" class="item">A</div>
  <div id="B" class="item">B</div>
  <div id="C" class="item">C</div>
  <div id="D" class="item">D</div>
</div>

<button onclick="toggle()">Click me!</button>

答案 4 :(得分:1)

或者,您可以使用flexbox做类似的事情,而不是使用网格设置。 我个人发现flexbox在使事情变得敏感而又不会以难看的方式破坏方面,是一种更加有用/强大的工具。添加响应样式来进行相应修改很容易。

您可以执行以下操作:

#wrapper {
  width: 100%;
  max-width: 500px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.item:first-of-type {
  width: 100%;
}
.item:nth-of-type(2) {
  width: 100%;
}
.item:nth-of-type(3):last-of-type {
  width: 100%;
}
.item:nth-of-type(3) {
  width: 50%;
}
.item:nth-of-type(4) {
  width: 50%;
}

这样,如果您有第5或第6(或类似)项,并且希望它们的宽度根据元素数量而变化,则可以在此处执行类似的操作。如果看我的演示,如果删除第4个项目,则作为最后一个元素的第3个项目将具有100%的宽度。

CodePen rough example