使用css网格进行砌体布局

时间:2017-05-11 13:48:08

标签: css css3 grid-layout css-grid

我正在尝试使用css网格布局创建砌体布局。网格中的所有项目都具有可变高度。我不知道会有什么东西。所以我不能为每个项目定义grid-row。是否可以在列中的上一个结尾之后立即启动每个新项目?

我正在尝试的代码:

.wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fill, 330px);
  align-items: flex-start;
  grid-column-gap: 10px;
  grid-row-gap: 50px;
}

.item {
  background: black;
  border-radius: 5px;
}
<div class="wrapper">
  <div class="item" style="height:50px"></div>
  <div class="item" style="height:100px"></div>
  <div class="item" style="height:30px"></div>
  <div class="item" style="height:90px"></div>
  <div class="item" style="height:80px"></div>
  <div class="item" style="height:50px"></div>
  <div class="item" style="height:70px"></div>
  <div class="item" style="height:40px"></div>

</div>

full codepen here

4 个答案:

答案 0 :(得分:1)

在您的问题中,您将分别设置每个项目的高度。如果您愿意这样做,那么可以通过网格轻松实现砌体布局。

而不是为每个项目集l = [1, 2, 3, 4, 5] def generator(l, batch_size=2): while 1: for i in range(0, len(l), batch_size): batch = l[i:(i + batch_size)] if len(batch) < batch_size: batch.extend(l[0: batch_size - len(batch)]) yield batch >> gen = generator(l, batch_size=2) >> next(gen) # [1, 2] >> next(gen) # [3, 4] >> next(gen) # [5, 1] >> next(gen) # [1, 2] << want [2, 3] instead 设置高度,以便每个项目跨越一定数量的行。

grid-row-end

项目的高度将取决于您为网格设置的 <div class="item" style="grid-row-end: span 5"></div> grid-auto-rows的值。

我在这里制作了一个Codepen:https://codepen.io/andybarefoot/pen/NaprOB

如果您不想为每个项目单独设置grid-row-gap值,则可以使用一些JavaScript动态执行此操作。我在每个项目中放置了另一个“容器”div,并测量此容器的高度以计算项目需要跨越多少行。我在页面加载时执行此操作,并在加载任何图像时再次为每个项目执行此操作(因为内容的高度将更改)。如果将此方法与响应式布局结合使用,则还应重新计算页面调整大小,因为列的宽度可能已更改,这将影响内容的高度。

以下是响应列调整大小的完整示例:https://codepen.io/andybarefoot/pen/QMeZda

如果你有宽度可变的物品,你仍然可以达到类似的效果,但是网格的包装不是很完美,可以改变物品顺序以优化包装。

我在Media上写了一篇关于这种方法的博客,如果感兴趣的话:使用CSS Grid的砌体样式布局

答案 1 :(得分:0)

这是仅使用CSS创建Masonry布局的一种方法。

*,
*:before,
*:after {
  box-sizing: border-box !important;
}

article {
  -moz-column-width: 13em;
  -webkit-column-width: 13em;
  -moz-column-gap: 1em;
  -webkit-column-gap: 1em;
}

section {
  display: inline-block;
  margin: 0.25rem;
  padding: 1rem;
  width: 100%;
  background: #efefef;
}

p {
  margin: 1rem 0;
}

body {
  line-height: 1.25;
}
<article>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error aliquid reprehenderit expedita odio beatae est.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nobis quaerat suscipit ad.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nihil alias amet dolores fuga totam sequi a cupiditate ipsa voluptas id facilis nobis.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem ut debitis dolorum earum expedita eveniet voluptatem quibusdam facere eos numquam commodi ad iusto laboriosam rerum aliquam.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat architecto quis tenetur fugiat veniam iste molestiae fuga labore!</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Odit accusamus tempore at porro officia rerum est impedit ea ipsa tenetur. Labore libero hic error sunt laborum expedita.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima asperiores eveniet vero velit eligendi aliquid in.</p>
  </section>
  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus dolorem maxime minima animi cum.</p>
  </section>
</article>

注意:我没有制作代码,我发现它做了一些小改编,  可以找到原始代码here

请注意,正如Zen所指出的那样:

  

[...]项目布局从上到下从左到右,   而人们通常期望的是(文化假设可以理解)   从左到右从上到下布局。这是基于CSS3列的常见建议的showstopper。

答案 2 :(得分:0)

您可以动态设置span的{​​{1}}值(使用一些JS,就像下面示例中基于Codepen experiment的那个)并使用grid-row-end dense的关键字:

grid-auto-placement
const gridStyles = getComputedStyle(document.querySelector('.wrapper',null));
const rowHeight = parseInt(gridStyles.getPropertyValue('--grid-row-height'));
const gap = parseInt(gridStyles.getPropertyValue('--grid-gutter'));;

let makeGrid = function() {
  let items = document.querySelectorAll('.item');
  for (let i=0, item; item = items[i]; i++) {
    // take an item away from grid to measure it
    item.classList.add('is-being-measured');
    let height = item.offsetHeight;
    // calcylate the row span
    let rowSpan = Math.ceil((height + gap)/(rowHeight + gap));
    // set the span value for grid-row-end
    item.style.gridRowEnd = 'span '+rowSpan;
    // return the item into the grid
    item.classList.remove('is-being-measured');
  }
}

window.addEventListener('load', makeGrid);
window.addEventListener('resize', () => {
  clearTimeout(makeGrid.resizeTimer);
  makeGrid.resizeTimer = setTimeout(makeGrid, 50);
});
.wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fill, 330px);
  --grid-gutter: 10px;
  grid-gap: var(--grid-gutter);
  --grid-row-height: 10px;
  grid-auto-rows: var(--grid-row-height);
  grid-auto-flow: row dense;
  position: relative;
}

.item {
  background: black;
  color: white;
  border-radius: 5px;
}
.item.is-being-measured {
  /* temporary styles for measuring grid items */
  position: absolute;
  width: 330px;
  top: 0;
  left: 0;
}

.item > * { margin-left: 20px; }

答案 3 :(得分:-1)

您可以使用column完成此操作。

.wrapper {
    column-gap: 10px;
    column-count: 4;
}

.item {
    display: inline-block;
    background: #000;
    width: 100%;
    border-radius: 3px;
}

您似乎尝试使用flexgrid的组合,这可能会令人感到困惑。据我所知,flex是相对于页面上其他项目的,其中设置列会影响属于这些列的项目。

updated codepen