在响应式网格上设置多个“相同高度"行部分的唯一 CSS 解决方案 [英] CSS only solution to set MULTIPLE “same height” row sections on a responsive grid

查看:15
本文介绍了在响应式网格上设置多个“相同高度"行部分的唯一 CSS 解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想要:一种仅 CSS 的解决方案,可在每行的基础上启用多个等高网格部分",这也是响应式的.

注意:这是

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

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

.items {最大宽度:1200px;}.物品 {宽度:25%;box-sizing: 边框框;显示:内联块;垂直对齐:顶部;填充:0 12px;边距:24px -4px 24px 0;}@media(最大宽度:600px){.物品 {宽度:50%;}}.item__标题{背景颜色:#d4d0f5;填充:10px;文本对齐:居中;边框:1px 实心 #bbbbbb;}.item__内容{填充:10px;左边框:1px 实心 #bbbbbb;右边框:1px 实心 #bbbbbb;}.item__功能{填充:10px;边框顶部:1px 实心 #bbbbbb;左边框:1px 实心 #bbbbbb;右边框:1px 实心 #bbbbbb;背景色:#f7cbb1;}.item__features ul {边距:0px;}.item__价格{背景颜色:#e0f6d9;填充:10px;文本对齐:居中;边框:1px 实心 #bbbbbb;}

<div class="item"><div class="item__heading">第 1 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">99.99 英镑

<div class="item"><div class="item__heading">第 2 项

<div class="item__content">某些内容比同一行上的其他项目长,并设置此部分的高度,因为它比此行上的其他内容部分跨越的行多得多

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">69.99 英镑

<div class="item"><div class="item__heading">第 3 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li><li>特征2</li><li>特征3</li>

<div class="item__price">69.99 英镑

<div class="item"><div class="item__heading">第 4 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">109.99 英镑

<div class="item"><div class="item__heading">第 5 项

<div class="item__content">一些中等长度的内容等等

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">29.99 英镑

<div class="item"><div class="item__heading">第 6 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li><li>特征2</li>

<div class="item__price">99.99 英镑

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

限制

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

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

进一步说明:我说的是仅使用 CSS 的解决方案,我指的是非 JS 解决方案.如果 HTML 块需要更改(顺序/嵌套/类名)以支持非 JS 解决方案,这是一个可行的选择

解决方案

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

为了让它们在少于 4 个时表现,可以使用 nth-child 选择器来实现,但使用 last* 更简单> 课,所以我选择了后者.

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

小提琴演示

.items {显示:弹性;弹性方向:列;最大宽度:1200px;}.items .group_of_4 {显示:弹性;flex-wrap: 包裹;对齐内容:间隔;/*  更新  */}.items .group_of_4 ~ .group_of_4 {边距顶部:24px;}.items .group_of_4 >div {宽度:计算(25% - 12px);/*  更新  */box-sizing: 边框框;填充:12px;}.item__标题{背景颜色:#d4d0f5;填充:10px;文本对齐:居中;边框:1px 实心 #bbbbbb;订单:1;}.item__内容{填充:10px;左边框:1px 实心 #bbbbbb;右边框:1px 实心 #bbbbbb;订单:2;}.item__功能{填充:10px;左边框:1px 实心 #bbbbbb;右边框:1px 实心 #bbbbbb;背景色:#f7cbb1;订单:3;}.item__价格{背景颜色:#e0f6d9;填充:10px;文本对齐:居中;边框:1px 实心 #bbbbbb;订单:4;}/* 一组中的一项 */.items .group_of_4 .last1 {margin-right: calc(75% 6px);/*  更新  */}/* 一组中的两个项目 */.items .group_of_4 .last2 {margin-right: calc(50% + 6px);/*  更新  */}/* 一组中的三个项目 */.items .group_of_4 .last3 {margin-right: calc(25% + 6px);/*  更新  */}@media(最大宽度:600px){.items .group_of_4 >div:nth-child(8) ~ .item__heading {边距顶部:24px;订单:5;}.items .group_of_4 >div:nth-child(8) ~ .item__content {订单:6;}.items .group_of_4 >div:nth-child(8) ~ .item__features {订单:7;}.items .group_of_4 >div:nth-child(8) ~ .item__price {订单:8;}.items .group_of_4 >div {宽度:计算(50% - 12px);/*  更新  */}/* 一组中的一项 *//* 一组中的三个项目 */.items .group_of_4 .last1,.items .group_of_4 .last3 {右边距:50%;}/* 一组中的两个项目 */.items .group_of_4 .last2 {右边距:0%;}}

<div class="group_of_4"><div class="item__heading">第 1 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">99.99 英镑

<div class="item__heading">第 2 项

<div class="item__content">某些内容比同一行上的其他项目长,并设置此部分的高度,因为它比此行上的其他内容部分跨越的行多得多

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">69.99 英镑

<div class="item__heading">第 3 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li><li>特征2</li><li>特征3</li>

<div class="item__price">69.99 英镑

<div class="item__heading">第 4 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">109.99 英镑

<div class="group_of_4"><div class="item__heading">第 5 项

<div class="item__content">一些中等长度的内容等等

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">29.99 英镑

<div class="item__heading last2">第 6 项

<div class="item__content last2">一些不那么长的内容

<div class="item__features last2"><ul><li>特征1</li>

<div class="item__price last2">99.99 英镑

<小时>

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

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

(function(d) {window.addEventListener("加载", function() {var item = d.querySelector('.items');var items = item.querySelectorAll('.item__features');var 高度 = [], 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 = '文本/css';如果(st.styleSheet){st.styleSheet.cssText = css} 别的 {st.appendChild(d.createTextNode(css));}(d.head || d.getElementsByTagName('head')[0]).appendChild(st);}, 错误的);}(document));

.items {显示:弹性;flex-wrap: 包裹;最大宽度:1200px;}.物品 {显示:弹性;弹性方向:列;宽度:25%;box-sizing: 边框框;填充:0 12px;边距:24px -4px 24px 0;}@media(最大宽度:600px){.物品 {宽度:50%;}}.item__标题{背景颜色:#d4d0f5;填充:10px;文本对齐:居中;边框:1px 实心 #bbbbbb;}.item__内容{弹性:1 1 自动;填充:10px;左边框:1px 实心 #bbbbbb;右边框:1px 实心 #bbbbbb;}.item__功能{填充:10px;边框顶部:1px 实心 #bbbbbb;左边框:1px 实心 #bbbbbb;右边框:1px 实心 #bbbbbb;背景色:#f7cbb1;}.item__features ul {边距:0px;}.item__价格{背景颜色:#e0f6d9;填充:10px;文本对齐:居中;边框:1px 实心 #bbbbbb;}

<div class="item"><div class="item__heading">第 1 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">99.99 英镑

<div class="item"><div class="item__heading">第 2 项

<div class="item__content">某些内容比同一行上的其他项目长,并设置此部分的高度,因为它比此行上的其他内容部分跨越的行多得多

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">69.99 英镑

<div class="item"><div class="item__heading">第 3 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li><li>特征2</li><li>特征3</li>

<div class="item__price">69.99 英镑

<div class="item"><div class="item__heading">第 4 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">109.99 英镑

<div class="item"><div class="item__heading">第 5 项

<div class="item__content">一些中等长度的内容等等

<div class="item__features"><ul><li>特征1</li>

<div class="item__price">29.99 英镑

<div class="item"><div class="item__heading">第 6 项

<div class="item__content">一些不那么长的内容

<div class="item__features"><ul><li>特征1</li><li>特征2</li>

<div class="item__price">99.99 英镑

Wanted: a CSS only solution to enable MULTIPLE equal height grid "sections" on a per row basis, that is also responsive.

Note: this is a follow-up question to this question which has only a single "equal height" section per item - which can be achieved through flexbox

The below diagram should help explain the requirement:

The "item grid" should be responsive - in that it can show a different number of cards per row based on viewport width (4 on desktop, 2 on mobile). Within a given row, the equivalent "content" and "feature" sections should have the same height.

In the below HTML & CSS - the item cards are split into the rows that we need (at the two example break points desktop & mobile) but the content section heights are variable:

.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>

I created the following codepen as a JavaScript based solution that achieves the desired outcome - but I am hoping to replace this with just a CSS solution if possible: http://codepen.io/rusta/pen/xdmdxm

Limitations

Flexbox based solutions seem to be un-able to cope with the fact that the items have more than one section that needs to be aligned

I was hoping that the new CSS Grid system would help achieve the above, but I have made several attempts at this with no luck, so am opening it up the community to see if I am just missing something

Further note: I say a CSS only solution, by which I mean a non-JS solution. If the HTML blocks need to change (order/nesting/class names) to support a non-JS solution that's a viable option

解决方案

Based on your own answer, where you grouped them by 4, you can do that with CSS Flexbox too.

To make them behave when there is less than 4, it might be possible to accomplish that using the nth-child selector, but it was simpler to use a last* class, so I went for the latter.

One might even be able to do this without the .group_of_4 wrapper, with some clever nth-child rules, but again, went for the simpler since it does not come with any obvious limitations

Fiddle demo

.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>


Here's a script based solution, for anyone who want that.

What's missing in it is a resize event handler, that does recalculate max height per row instead.

(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>

这篇关于在响应式网格上设置多个“相同高度"行部分的唯一 CSS 解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆