相对于彼此垂直移位的列排列元素

时间:2018-12-16 03:33:24

标签: css css3 css-grid

我正在寻找一种实现这种效果的方法:

在移动版式上,元素在列中一个接一个地放置:

enter image description here

但是,在桌面布局中,元素放置在两列中,一列中包含奇数元素,另一列中包含偶数元素。列相对于彼此垂直移动:

enter image description here

我想知道是否只有CSS方式才能实现此定位。如果只有一种说法,例如nth-child(n+1)将跨越第1和2行,而`nth-child(2n)将跨越第2和3行,以此类推,那么CSS网格将变得非常接近。但是我不确定CSS网格是否可以做到这一点。您也许知道这样做的方法吗?

更新:我猜想这是我所想到的非常粗略的CSS近似值,使用内联代码块:https://codepen.io/anon/pen/JwXVox。我欢迎更好的技术。

3 个答案:

答案 0 :(得分:2)

大概,您知道如何制作移动版本,以及如何使用@media来区分不同的屏幕尺寸。

我不完全理解“跨行1和2”的意思,但是您不必使用网格布局。好的老式内联块在这里可以正常工作。您的近似近似值是粗糙的,仅是因为您的余量值是粗略估计的,而不是因为您使用的技术不足以执行您想要的操作。

这就是我放置.grid-element元素的位置(它对我来说看起来很漂亮;也许它与您想要的足够接近,可以对其进行微调):

  1. 所有元素:上边距为0,左/右边距为1%,下边距为10px。
  2. 第二个元素(右列中的第一个元素):顶边距为50px。
  3. 除第一个元素外的所有奇数元素:-50px的上边距。

您可以尝试使用不同的边距值来查看其效果。但基本上,一旦将它们并排设置,就将第二个向下推。这样可以正确定位第二个和第一个元素,但随后的所有元素也都会下降。因此,我们希望将负数的偶数备份增加。但是,我们不想提高第一个,因为它从未被降低。因此,我们使用nth-child(2n+3)(即,每个第二个元素以三个开头)选择器将其排除。这等效于使用nth-child(odd):not(:first-child)

function fillGrid() {
  const container = document.querySelector('.container');
  const times = [...new Array(10)];
  times.forEach(() => {
    const element = document.createElement('div');
    element.classList.add('grid-element');
    container.appendChild(element);
  });
}

fillGrid()
.container {
  width: 60%;
  margin: auto;
  background: papayawhip;
  padding-bottom: 60px;
}

.grid-element {
  display: inline-block;
  height: 50px;
  background: green;
  vertical-align: middle;
  width: 48%;
  margin: 0 1% 10px;
}

.grid-element:nth-child(2) {
  margin-top: 60px;
}

.grid-element:nth-child(2n+3) {
  margin-top: -60px;
}
<div class="container">
</div>

编辑:使用CSS网格获得相同的结果

在评论中我们进行了交谈之后,我尝试了position:grid,以查看是否可以找到一种方法。我必须添加一行javascript(或编写一堆相当繁琐的CSS)才能完成此操作,但效果似乎不错。

我只是将行高设置为25%,然后在您的javascript中添加一行,以使每行加粗两行,并从上一个元素开始将其向下一行。

function fillGrid() {
  const container = document.querySelector('.container');
  const times = [...new Array(10)];
  times.forEach((e, index) => {
    const element = document.createElement('div');
    element.classList.add('grid-element');
    //added the line below to size and position the elements
    element.setAttribute("style", "grid-row-start: " + (index + 1) + "; grid-row-end: " + (index + 3) + ";");
    element.textContent = index + 1; //also put a number in each box
    container.appendChild(element);
  });
}

fillGrid()
.container {
  display: grid;
  grid-gap: 5px;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 25px;
  width: 60%;
  margin: auto;
  background: papayawhip;
}

.grid-element {
  background: green;
  color: white;
}
<div class="container">
</div>

答案 1 :(得分:2)

您可以使用 Flexbox calc() 功能:nth-child()选择器,{{1} } 伪类,当然还有:not() 查询

@media
.flex {
  display: flex; /* displays flex-items (children) inline */
  flex-wrap: wrap; /* enables their wrapping */
}

.flex > div {
  flex-basis: calc(50% - 10px); /* initial width set to 50% of the parent's - left & right margins */
  height: 100px;
  margin: 0 5px; /* preferably top & bottom margins set to zero to keep calculations simple */
  border: 1px solid;
  box-sizing: border-box; /* because of the borders, also recommended in general */
}

.flex > div:nth-child(2){
  margin-top: 55px; /* half of divs height + half of the desired gap between them; modification affects all but the first div */
}

.flex > div:nth-child(odd):not(:first-child){
  margin-top: -45px; /* - half of divs height + half of the desired gap between them, so in this case the gap is 10px (2 x 5px); modification affects all but the first odd div (if ofc. modification is "")  */
}

.flex > div:nth-child(even):not(:nth-child(2)){
  margin-top: 10px; /* gap size; modification affects all but the first three divs */
}

@media (max-width: 600px){
  .flex {flex-direction: column} /* stacks flex-items vertically */
  .flex > div {flex-basis: auto} /* initial width set to default or 100% */
  .flex > div:not(:first-child) {margin-top: 10px !important}
}

答案 2 :(得分:1)

一种float方法

.container {
  width: 250px;
  margin: 0 auto;
}

.item {
  width: 100px;
  height: 100px;
  border: 1px solid black;
  margin-top: calc(100px/3);
}

.item:first-child {
  margin-top: 0;
}


@media (min-width: 400px) {
  .item:nth-child(even) {
    float: right;
    margin-top: calc(-100px/3);
  }
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>