4

需要:一个仅 CSS 的解决方案,可以在每行的基础上启用多个等高网格“部分”,这也是响应式的。

注意:这是这个问题的后续问题,每个项目只有一个“等高”部分 - 这可以通过 flexbox 实现

下图应该有助于解释要求: 有用的图表

“项目网格”应该是响应式的 - 因为它可以根据视口宽度显示每行不同数量的卡片(桌面上 4 个,移动设备上 2 个)。在给定的行内,等效的“内容”和“功能”部分应该具有相同的高度。

在下面的 HTML 和 CSS 中 - 项目卡被分成我们需要的行(在桌面和移动的两个示例断点处),但内容部分的高度是可变的:

.items {
  max-width: 1200px;
}

.item {
  width: 25%;
  box-sizing: border-box;
  display: inline-block;
  vertical-align: top;
  padding: 0 12px;
  margin: 24px -4px 24px 0;
}

@media (max-width: 600px) {
  .item {
    width: 50%;
  }
}

.item__heading {
  background-color: #d4d0f5;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
}

.item__content {
  padding: 10px;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
}

.item__features {
  padding: 10px;
  border-top: 1px solid #bbbbbb;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  background-color: #f7cbb1;
}

.item__features ul {
  margin: 0px;
}

.item__price {
  background-color: #e0f6d9;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
}
<div class="items">

  <div class="item">
    <div class="item__heading">
      Item 1
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £99.99
    </div>
  </div>


  <div class="item">
    <div class="item__heading">
      Item 2
    </div>
    <div class="item__content">
      Some content that is longer than other items on the same row and sets the height of this section as it spans many more lines than the rest of the other content sections on this row
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £69.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 3
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>                         <li>feature 2</li>
        <li>feature 3</li>
      </ul>
    </div>
    <div class="item__price">
      £69.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 4
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £109.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 5
    </div>
    <div class="item__content">
      Some content that is a medium kind of length blah blah
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £29.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 6
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
        <li>feature 2</li>
      </ul>
    </div>
    <div class="item__price">
      £99.99
    </div>
  </div>

    
</div>

我创建了以下 codepen 作为基于 JavaScript 的解决方案,实现了预期的结果 - 但如果可能的话,我希望用 CSS 解决方案替换它:http: //codepen.io/rusta/pen/xdmdxm

限制

  • 网格列表中要显示的项目数可以是 1-n 中的任意数字
  • 要显示的“内容”和“功能”部分的大小将是真正可变的(因此不能选择“合理的”最小高度)

基于 Flexbox 的解决方案似乎无法应对项目有多个需要对齐的部分这一事实

我希望新的 CSS Grid 系统能够帮助实现上述目标,但我在这方面做了几次尝试,但都没有成功,所以我打开社区看看我是否遗漏了什么

进一步说明:我说的是纯 CSS 解决方案,我的意思是非 JS 解决方案。如果 HTML 块需要更改(订单/嵌套/类名)以支持非 JS 解决方案,这是一个可行的选择

4

2 回答 2

8

根据您自己的答案,您将它们按 4 分组,您也可以使用 CSS Flexbox 来做到这一点。

为了让它们在少于 4 的情况下运行,可以使用nth-child选择器来完成,但使用last*类更简单,所以我选择了后者。

一个人甚至可以在没有.group_of_4包装器的情况下使用一些巧妙的nth-child规则来做到这一点,但同样,因为它没有任何明显的限制,所以还是选择了更简单的方法

小提琴演示

.items {
  display: flex;
  flex-direction: column;
  max-width: 1200px;
}

.items .group_of_4 {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;        /*  updated  */
}

.items .group_of_4 ~ .group_of_4 {
  margin-top: 24px;
}

.items .group_of_4 > div {
  width: calc(25% - 12px);                /*  updated  */
  box-sizing: border-box;
  padding: 12px;
}


.item__heading {
  background-color: #d4d0f5;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
  order: 1;
}

.item__content {
  padding: 10px;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  order: 2;
}

.item__features {
  padding: 10px;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  background-color: #f7cbb1;
  order: 3;
}

.item__price {
  background-color: #e0f6d9;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
  order: 4;
}

/* one item in a group */
.items .group_of_4 .last1 {
    margin-right: calc(75%  6px);        /*  updated  */
}
/* two items in a group */
.items .group_of_4 .last2 {
    margin-right: calc(50% + 6px);       /*  updated  */
}
/* three items in a group */
.items .group_of_4 .last3 {
    margin-right: calc(25% + 6px);       /*  updated  */
}

@media (max-width: 600px) {
  .items .group_of_4 > div:nth-child(8) ~ .item__heading {
    margin-top: 24px;
    order: 5;
  }
  .items .group_of_4 > div:nth-child(8) ~ .item__content {
    order: 6;
  }
  .items .group_of_4 > div:nth-child(8) ~ .item__features {
    order: 7;
  }
  .items .group_of_4 > div:nth-child(8) ~ .item__price {
    order: 8;
  }
  
  .items .group_of_4 > div {
    width: calc(50% - 12px);             /*  updated  */
  }

  /* one item in a group */
  /* three items in a group */
  .items .group_of_4 .last1,
  .items .group_of_4 .last3 {
    margin-right: 50%;
  }
  /* two items in a group */
  .items .group_of_4 .last2 {
    margin-right: 0%;
  }  
}
<div class="items">

  <div class="group_of_4">
    <div class="item__heading">
      Item 1
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £99.99
    </div>

    <div class="item__heading">
      Item 2
    </div>
    <div class="item__content">
      Some content that is longer than other items on the same row and sets the height of this section as it spans many more lines than the rest of the other content sections on this row
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £69.99
    </div>

    <div class="item__heading">
      Item 3
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
        <li>feature 2</li>
        <li>feature 3</li>
      </ul>
    </div>
    <div class="item__price">
      £69.99
    </div>

    <div class="item__heading">
      Item 4
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £109.99
    </div>
  </div>
  
  
  <div class="group_of_4">
    <div class="item__heading">
      Item 5
    </div>
    <div class="item__content">
      Some content that is a medium kind of length blah blah
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £29.99
    </div>

    <div class="item__heading last2">
      Item 6
    </div>
    <div class="item__content last2">
      Some content that is not that long
    </div>
    <div class="item__features last2">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price last2">
      £99.99
    </div> 

  </div>
</div>


这是一个基于脚本的解决方案,适合任何想要的人。

它缺少的是一个调整大小事件处理程序,它会重新计算每行的最大高度。

(function(d) {
  window.addEventListener("load", function() {
    var item = d.querySelector('.items');
    var items = item.querySelectorAll('.item__features');
    var heights = [], i = 0, css;
    for (i = 0; i < items.length; i++) {
      heights.push(parseFloat(window.getComputedStyle(items[i], null).getPropertyValue("height")));
    }
    css = ".item__features { height: " + Math.max.apply(null, heights) + "px; }" ;
    var st = d.createElement('style');
    st.type = 'text/css';
    if (st.styleSheet) {
      st.styleSheet.cssText = css
    } else {
      st.appendChild(d.createTextNode(css));
    }
    (d.head || d.getElementsByTagName('head')[0]).appendChild(st);
  }, false);
}(document));
.items {
  display: flex;
  flex-wrap: wrap;
  max-width: 1200px;
}

.item {
  display: flex;
  flex-direction: column;
  width: 25%;
  box-sizing: border-box;
  padding: 0 12px;
  margin: 24px -4px 24px 0;
}

@media (max-width: 600px) {
  .item {
    width: 50%;
  }
}

.item__heading {
  background-color: #d4d0f5;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
}

.item__content {
  flex: 1 1 auto;
  padding: 10px;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
}

.item__features {
  padding: 10px;
  border-top: 1px solid #bbbbbb;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  background-color: #f7cbb1;
}

.item__features ul {
  margin: 0px;
}

.item__price {
  background-color: #e0f6d9;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
}
<div class="items">

  <div class="item">
    <div class="item__heading">
      Item 1
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £99.99
    </div>
  </div>


  <div class="item">
    <div class="item__heading">
      Item 2
    </div>
    <div class="item__content">
      Some content that is longer than other items on the same row and sets the height of this section as it spans many more lines than the rest of the other content sections on this row
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £69.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 3
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
        <li>feature 2</li>
        <li>feature 3</li>
      </ul>
    </div>
    <div class="item__price">
      £69.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 4
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £109.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 5
    </div>
    <div class="item__content">
      Some content that is a medium kind of length blah blah
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item__price">
      £29.99
    </div>
  </div>

  <div class="item">
    <div class="item__heading">
      Item 6
    </div>
    <div class="item__content">
      Some content that is not that long
    </div>
    <div class="item__features">
      <ul>
        <li>feature 1</li>
        <li>feature 2</li>
      </ul>
    </div>
    <div class="item__price">
      £99.99
    </div>
  </div>

</div>

于 2017-05-24T17:00:21.610 回答
1

我正在为我自己的问题提供一个答案 - 但如果其他人想出更好的东西,我会推迟接受它,因为这个答案无疑会打破一些可访问性规则,并且几乎不可能为浏览器提供优雅的回退不支持 CSS Grid 但是...

如果您将 HTML 内容项分成四个块,您可以使用 CSS 网格样式规则获得所需的结果,无需 JavaScript

.items {
  max-width: 1200px;
}

.item__heading {
  margin-top: 30px;
  background-color: #d4d0f5;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
}

.item__content {
  padding: 10px;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
}

.item__features {
  padding: 10px;
  border-top: 1px solid #bbbbbb;
  border-left: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  background-color: #f7cbb1;
}

.item__price {
  background-color: #e0f6d9;
  padding: 10px;
  text-align: center;
  border: 1px solid #bbbbbb;
}

/* DESKTOP GRID */

/* DESKTOP COLUMN LAYOUT - 4 columns, one row */
.item-block-of-four {
  display: grid;
  grid-template-columns: 2% 22.5% 2% 22.5% 2% 22.5% 2% 22.5% 2%;
}
.item-1 {
  grid-column-start: 2;
  grid-column-end: 3;
}
.item-2 {
  grid-column-start: 4;
  grid-column-end: 5;
}
.item-3 {
  grid-column-start: 6;
  grid-column-end: 7;
}
.item-4 {
  grid-column-start: 8;
  grid-column-end: 9;
}

/* ROW LAYOUT - one row for all 4 items */
.item__heading {
  grid-row-start: 1;
  grid-row-end: 2;
}
.item__content {
  grid-row-start: 2;
  grid-row-end: 3;
}
.item__features {
  grid-row-start: 3;
  grid-row-end: 4;
}
.item__price {
  grid-row-start: 4;
  grid-row-end: 5;
}

/* MOBILE GRID */

@media (max-width: 600px) {
  /* MOBILE COLUMN LAYOUT - 2 columns 2 rows */
  .item-block-of-four {
    display: grid;
    grid-template-columns: 6% 41% 6% 41% 6%;
  }
  .item-1, .item-3 {
    grid-column-start: 2;
    grid-column-end: 3;
  }
  .item-2, .item-4 {
    grid-column-start: 4;
    grid-column-end: 5;
  }

  /* MOBILE ROW LAYOUT - two sets of rows */

  /* first row set */
  .item-1.item__heading, .item-2.item__heading {
    grid-row-start: 1;
    grid-row-end: 2;
  }

  .item-1.item__content, .item-2.item__content {
    grid-row-start: 2;
    grid-row-end: 3;
  }

  .item-1.item__features, .item-2.item__features {
    grid-row-start: 3;
    grid-row-end: 4;
  }

  .item-1.item__price, .item-2.item__price {
    grid-row-start: 4;
    grid-row-end: 5;
  }

  /* second row set */
  .item-3.item__heading, .item-4.item__heading {
    grid-row-start: 6;
    grid-row-end: 7;
  }

  .item-3.item__content, .item-4.item__content {
    grid-row-start: 7;
    grid-row-end: 8;
  }

  .item-3.item__features, .item-4.item__features {
    grid-row-start: 8;
    grid-row-end: 9;
  }

  .item-3.item__price, .item-4.item__price {
    grid-row-start: 9;
    grid-row-end: 10;
  }
}
<div class="items">

  <div class="item-block-of-four">

    <div class="item-1 item__heading">
      Item 1
    </div>
    <div class="item-2 item__heading">
      Item 2
    </div>
    <div class="item-3 item__heading">
      Item 3
    </div>
    <div class="item-4 item__heading">
      Item 4
    </div>

    <div class="item-1 item__content">
      Some content that is not that long
    </div>
    <div class="item-2 item__content">
      Some content that is longer than other items on the same row and sets the height of this section as it spans many more lines than the rest of the other content sections on this row
    </div>
    <div class="item-3 item__content">
      Some content that is not that long
    </div>
    <div class="item-4 item__content">
      Some content that is not that long
    </div>

    <div class="item-1 item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item-2 item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item-3 item__features">
      <ul>
        <li>feature 1</li>
        <li>feature 2</li>
        <li>feature 3</li>
      </ul>
    </div>
    <div class="item-4 item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>

    <div class="item-1 item__price">
      £99.99
    </div>
    <div class="item-2 item__price">
      £69.99
    </div>
    <div class="item-3 item__price">
      £69.99
    </div>
    <div class="item-4 item__price">
      £109.99
    </div>

  </div><!-- /item-block-of-four -->

  <div class="item-block-of-four">

    <div class="item-1 item__heading">
      Item 5
    </div>
    <div class="item-2 item__heading">
      Item 6
    </div>

    <div class="item-1 item__content">
      Some content that is a medium kind of length blah blah
    </div>
    <div class="item-2 item__content">
      Some content that is not that long
    </div>

    <div class="item-1 item__features">
      <ul>
        <li>feature 1</li>
      </ul>
    </div>
    <div class="item-2 item__features">
      <ul>
        <li>feature 1</li>
        <li>feature 2</li>
      </ul>
    </div>

    <div class="item-1 item__price">
      £29.99
    </div>
    <div class="item-2 item__price">
      £99.99
    </div>

  </div><!-- /item-block-of-four -->

</div><!-- /items-container -->

于 2017-05-24T13:58:23.240 回答