将所有div堆叠到容器的顶部,而不在下面留出空间

时间:2019-03-29 01:52:08

标签: javascript css css3 flexbox

我正在制作一个相册,该相册可以加载多张高度不同的照片,并且需要将它们堆叠在容器的顶部,就像这样:

enter image description here

为此,我将容器的显示属性设置为使用align-item进行弯曲:flex-start和将子项设置为inline-flex,如下所示:

HTML

  <div class="album1">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
  </div>

SCSS

  .album1 {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    div {
      display: inline-flex;
      width: calc(100% / 3);
      height: 100px;
      background-color: red;
      box-sizing: border-box;
      border: 1px solid black;
      justify-content: center;  
      align-items: center;
      &:nth-child(3n+2) {
        height: 200px;
      }
    }
  }

(请注意,我仅为示例设置了div的高度)

我的行为就是这样。

enter image description here

我实际上是在寻找纯CSS解决方案,但是我也可以使用JS解决方案。

6 个答案:

答案 0 :(得分:1)

免责声明 这里的解决方案在于概念和CSS实现,与是否使用angular,jquery,vanilla js或vue无关。

如果您想让CSS处理所有内容,我想您想在3个单独的列中呈现数据。您必须将数据分成3个几乎相等的数组-我说这几乎是因为图像的数量并不总是可以被3整除的,所以一两个数组可能缺少或多余的项目。一旦拥有3个阵列,您就可以将每个阵列中的图像渲染到单独的列中,而不是逐行显示。这里以jsfiddle为例。

我对vue不熟悉,所以我使用react作为库:https://jsfiddle.net/ahmadabdul3/sh8wjmtp/36/

如果查看渲染的输出,由于数组的拆分方式,数字仍然会越过,但是渲染是按列进行的

和代码:

class TodoApp extends React.Component {
  state = {
    allItems: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
  };

  separatePhotosForColumns() {
    // split the items into 3 arrays
    // i'll just return 3 arrays for simplicity here
    return {
      one: [1, 4, 7, 10, 13, 16, 19],
      two: [2, 5, 8, 11, 14, 17, 20],
      three: [3, 6, 9, 12, 15, 18]
    };
  }

  render() {
    const parts = this.separatePhotosForColumns();
    return (
      <div className='album'>
        <Column data={parts.one} />
        <Column data={parts.two} />
        <Column data={parts.three} />
      </div>
    )
  }
}

class Column extends React.PureComponent {
  getRandomHeight() {
    return Math.floor(Math.random() * 200) + 100;
  }

  render() {
    const { data } = this.props;
    const images = data.map(i => (
      <div 
        className='photo' 
        key={i} 
        style={{ height: this.getRandomHeight() }}>
        { i }
      </div>
    ));
    return (
      <div className='column'>
        { images }
      </div>
    );
  }
}

css非常简单:

.album {
  display: flex;
}

.column {
  flex-grow: 1;
  flex-shrink: 1;
}

.photo {
  width: 100%;
  min-height: 100px;
  box-sizing: border-box;
  padding: 20px;
  border: 1px solid #ddd;
}

答案 1 :(得分:0)

我认为您应该对每张图片使用三列,而不是对所有图片使用一列。

<div class="album1">
    <div class="column">
        <div class="shortelement">1</div>
        <div class="shortelement">2</div>
        <div class="shortelement">3</div>
    </div>
    <div class="column">
        <div class="longelement">4</div>
        <div class="longelement">5</div>
        <div class="longelement">6</div>
    </div>
    <div class="column">
        <div class="shortelement">7</div>
        <div class="shortelement">8</div>
        <div class="shortelement">9</div>
    </div>

</div>

然后在CSS中,您可以

 .album1{
        display:flex;
        flex-direction: row;
    }
    .column{
        display:flex;
        flex-direction: column;
    }
    .shortelement{
        height: 200%;
    }
    .longelement{
        height: 50%;
    }

您可以修改代码的某些方面,以减少代码的重复性。我希望这会有所帮助!

答案 2 :(得分:0)

Javascript解决方案

如果您将元素258等设置为200px,则快速解决方案是在元素1,4上使用负边距 ,7,10 ...和3,6,9,12 ...元素的高度的一半(100px)-请参见下面的演示。

[...document.querySelectorAll('.album1 > div')].filter(function(e, i) {
  // filter elements 1,4,7,10... and 3,6,9,12...
  return (i + 1) % 3 == 0 || (i + 1) % 3 == 1;
}).forEach(function(e, i) {
  // set negative margins
  e.style.marginTop = (Math.floor(i / 2) * -100) + 'px';
});
.album1 {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
}

.album1 div {
  display: inline-flex;
  width: calc(100% / 3);
  height: 100px;
  background-color: red;
  box-sizing: border-box;
  border: 1px solid black;
  justify-content: center;
  align-items: center;
}

.album1 div:nth-child(3n+2) {
  height: 200px;
}

.album1 div:nth-child(1),
.album1 div:nth-child(3) {
  margin-top: 0 !important; /* no margin for 1 & 3 */
}
<div class="album1">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>


您可以使用 CSS变量使其动态化(并使用变量控制高度):

let margin = -getComputedStyle(document.body).getPropertyValue('--height').replace('px','');

[...document.querySelectorAll('.album1 > div')].filter(function(e, i) {
  // filter elements 1,4,7,10... and 3,6,9,12...
  return (i + 1) % 3 == 0 || (i + 1) % 3 == 1;
}).forEach(function(e, i) {
  // set negative margins
  e.style.marginTop = (Math.floor(i / 2) * margin) + 'px';
});
:root {
  --height: 100px;
}

.album1 {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
}

.album1 div {
  display: inline-flex;
  width: calc(100% / 3);
  height: var(--height);
  background-color: red;
  box-sizing: border-box;
  border: 1px solid black;
  justify-content: center;
  align-items: center;
}

.album1 div:nth-child(3n+2) {
  height: calc(var(--height) * 2);
}

.album1 div:nth-child(1),
.album1 div:nth-child(3) {
  margin-top: 0 !important; /* no margin for 1 & 3 */
}
<div class="album1">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>


纯CSS解决方案

如果选择 CSS网格布局 ,则会更容易-您可以使用grid-template-columns: 1fr 1fr 1fr设置三列布局,并使用grid-template-rows: 100px。现在魔术grid-auto-flow: dense完成-参见下面的演示:

:root {
  --height: 100px;
}

.album1 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr; /* 3 columns */
  grid-auto-rows: var(--height); /* set row height */
  grid-auto-flow: dense; /* fills in the spaces */
}

.album1 div:nth-child(3n+2) {
  grid-row: span 2; /* sets double height */
  grid-column: 2; /* place in second column */
}

.album1 div {
  display: inline-flex;
  background-color: red;
  box-sizing: border-box;
  border: 1px solid black;
  justify-content: center;
  align-items: center;
}
<div class="album1">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

答案 3 :(得分:0)

使用CSS列数将很容易做到这一点。您不需要为此使用flex-box。您只需定义希望浏览器将自动调整每列宽度的大小以均匀填充容器的列数即可。您可以在W3 CSS column-count上了解更多信息。这种方法的缺点是,文本和图像只能从上到下进行组织,然后以相同的顺序流入每一列。

这是我制作的一支笔,用来说明我在说什么:https://codepen.io/MatthewRader/pen/JzgvOV

这是您的CSS的外观:

  .album1 {
    column-count: 3;
    gap: 5px;

    div {
      width: 100%;
      height: 100px;
      background-color: red;
      box-sizing: border-box;
      border: 1px solid black;
      margin-bottom: 5px;

      &:nth-child(3n+2) {
        height: 200px;
      }
    }
  }

答案 4 :(得分:0)

在下面的示例中查看响应式照片网格

HTML

<section id="photos">
  <img src="images/cat-1.jpg" alt="Cute cat">
  <img src="images/cat-2.jpg" alt="Serious cat">
  ...
</section>

CSS

#photos {
  /* Prevent vertical gaps */
  line-height: 0;

  -webkit-column-count: 5;
  -webkit-column-gap:   0px;
  -moz-column-count:    5;
  -moz-column-gap:      0px;
  column-count:         5;
  column-gap:           0px;  
}

#photos img {
  /* Just in case there are inline attributes */
  width: 100% !important;
  height: auto !important;
}

@media (max-width: 1200px) {
  #photos {
  -moz-column-count:    4;
  -webkit-column-count: 4;
  column-count:         4;
  }
}
@media (max-width: 1000px) {
  #photos {
  -moz-column-count:    3;
  -webkit-column-count: 3;
  column-count:         3;
  }
}
@media (max-width: 800px) {
  #photos {
  -moz-column-count:    2;
  -webkit-column-count: 2;
  column-count:         2;
  }
}
@media (max-width: 400px) {
  #photos {
  -moz-column-count:    1;
  -webkit-column-count: 1;
  column-count:         1;
  }
}

https://css-tricks.com/seamless-responsive-photo-grid/

https://codepen.io/team/css-tricks/pen/pvamyK

答案 5 :(得分:0)

因此,这里有很多不错的答案,因为有多种途径可以帮助您实现所需的目标。这是另一个快速简单的CSS网格实现

.album1 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  width: 80%;
  margin: 0 auto;
}

.album1 > div {
  background: #777;
  height: 100px;
  border: 1px solid #000;
  box-sizing: border-box;
}

.album1 > div:nth-child(3n + 2) {
  height: 200px;
}

css网格对于布置随机或布局或将事物放置在奇数位置或偏移图片网格的布局非常有用。我个人喜欢使用网格为网格内的列进行布局和flexbox