将 div 放在另一个 div 的下面 属性 display:grid

Place div below another div with property display:grid

我在尝试将 div 放在另一个带有 diplay:grid 的 div 下方时遇到问题。 div 被放置在另一个上面而不是下面。

“app-bm-payment-card-item”是自定义 Angular 组件。

HTML 文件

//div wrapper
<div *ngIf="pageReady && myProfiles" class="ion-padding">

//div showing the cards stacked or collapsed
<div *ngIf="!inEditMode" class="card_container_stacked_main">
  <app-bm-payment-card-item *ngFor="let card of myProfiles" [card]="card" [editMode]="inEditMode"
    (onDeleteClick)="removeCard(card)" (onSelect)="selectCard(card)" (onEditClick)="editCardInfo(card)">
  </app-bm-payment-card-item>
</div>

//div showing the cards expanded
<div *ngIf="inEditMode" class="card_container_expanded_main">
  <app-bm-payment-card-item *ngFor="let card of myProfiles" [card]="card" [editMode]="inEditMode"
    (onDeleteClick)="removeCard(card)" (onSelect)="selectCard(card)" (onEditClick)="editCardInfo(card)">
  </app-bm-payment-card-item>
</div>

//div to be placed below the other one(s)
<div class="div">
  TEXT
</div>

</div>

SCSS 文件:

.card_container_stacked_main {
display:grid;
position: relative;
grid-auto-rows:30px; /* a fixed height to create an overflow */ 
}

.card_container_expanded_main {
position: relative;
max-width: 400px !important;
//margin-bottom: 15px;
}

.div {
position: relative;
}

所以,基本功能是当点击任何卡片时,卡片列表应该显示为堆叠或折叠。这就是为什么我使用 inEditMode 布尔值来了解应该显示哪个 div 以及隐藏哪个。当显示展开的卡片列表时,div (TEXT) 被正确地放置在列表下方,但是当激活堆叠卡片列表时,div 被放置在列表顶部,这是错误的, 它应该放在 stacked/collapsed 卡列表下面。见下图。

这应该将文本移到最后一张卡片下。我测试了它并为我工作:

设置 属性 stackedContainerHeight 或类似的东西并计算容器高度 ->

stackedContainerHeight = height of a stacked card in pixels * (lenght of card/profile array -1) + full card height + adjustments like margins etc.

例如:

stackedContainerHeight = 30 * (this.myProfiles.length-1) + 50 +15;

动态设置容器元素的堆叠容器高度

[style.height.px]="stackedContainerHeight"

原问题是什么:grid-auto-rows裁剪了容器高度,最后满卡的一部分流过容器。此解决方案计算出正确的高度,文本 div 将在容器正确呈现后呈现。

有趣的问题,因为“钱包”中的卡片数量可以是 1、2 或 N,而且 grid-auto-rows and/or grid-template-rows 需要在 CSS.

中明确指定 跟踪大小

多种解决方案可用(保留网格的使用)

#1 简单但丑陋的

只需将 margin-top: 200px; 设置为 TEXT div。仅当卡片堆叠时才应用此方法。

我不是这个解决方案的忠实粉丝,因为它更像是一个“修复”而不是一个合适的设计。

function expandStackCards() {
  var wrapper = document.getElementById("wrapper");
  if (wrapper.classList.contains("stacked")) {
    wrapper.classList.remove("stacked");
  } else {
    wrapper.classList.add("stacked");
  }
}
button {
  width: 400px;
  margin-bottom: 10px;
}
#wrapper {
  display: grid;
  grid-template-columns: 400px;
  gap: 10px;
}
#wrapper.stacked  {
  grid-auto-rows: 30px;
  gap: 0px;
}
.card {
  width: 100%;
  height: 200px;
  background-color: grey;
  border-radius: 20px;
  padding: 6px 20px;
  box-sizing: border-box;
}
.card span {
  font-family: sans-serif;
  text-transform: uppercase;
  color: white;
}
.card.green {
  background-color: green;
}
.card.blue {
  background-color: blue;
}
.my-text {
  margin: 10px;
}
.stacked .my-text {
  margin-top: 200px;
}
<button onclick="expandStackCards()">Expand / Stack</button>
<div id="wrapper" class="stacked">
  <div class="card green"><span>Card #1</span></div>
  <div class="card blue"><span>Card #2</span></div>
  <div class="my-text">TEXT</div>
</div>

或查找here the Codepen code

#2 使用 JavaScript 检测并正确设置 grid-auto-rows

我认为最好的解决方案,因为没有 margin 技巧,只有 pur 网格 CSS.

为此,您需要一些 JS 来检测钱包中卡的数量,然后设置值。

function stackedCards() {
  var wrapper = document.querySelector('#wrapper.stacked');
  if (wrapper) {
    var num_cards = wrapper.querySelectorAll(':scope .card').length;

    let style = getComputedStyle(wrapper);
    row_height_str = style.gridAutoRows;

    var new_grid_auto_rows = row_height_str.concat(' ').repeat(num_cards - 1);

    new_grid_auto_rows = new_grid_auto_rows.concat('auto');

    wrapper.style.gridAutoRows = new_grid_auto_rows;
  }
}

// This function is only for the DEMO button
function expandStackCards() {
  var wrapper = document.getElementById("wrapper");
  if (wrapper.classList.contains("stacked")) {
    wrapper.classList.remove("stacked");
    wrapper.style.removeProperty("grid-auto-rows");
  } else {
    wrapper.classList.add("stacked");
    stackedCards();
  }
}

stackedCards();
button {
  width: 400px;
  margin-bottom: 10px;
}
#wrapper {
  display: grid;
  grid-template-columns: 400px;
  gap: 10px;
}
#wrapper.stacked {
  grid-auto-rows: 30px;
  gap: 0px;
}
.card {
  width: 100%;
  height: 200px;
  background-color: grey;
  border-radius: 20px;
  padding: 6px 20px;
  box-sizing: border-box;
}
.card span {
  font-family: sans-serif;
  text-transform: uppercase;
  color: white;
}
.card.green {
  background-color: green;
}
.card.blue {
  background-color: blue;
}
.my-text {
  margin: 10px;
}
<button onclick="expandStackCards()">Expand / Stack</button>
<div id="wrapper" class="stacked">
  <div class="card green"><span>Card #1</span></div>
  <div class="card blue"><span>Card #2</span></div>
  <div class="my-text">TEXT</div>
</div>

或查找here the Codepen code

#3 使用 JavaScript 将 class 设置为 #wrapper

也可以用JS检测出牌数,然后把右边的class应用到格子上(#wrapper)。

它有点像之前的解决方案,但没有通过 JS 应用 CSS 样式,但是当然为此你需要在你的 CSS 文件中有这样的东西:

.wallet-1-cards {
  grid-auto-rows: auto;
}
.wallet-2-cards {
  grid-auto-rows: 30px auto;
}
.wallet-3-cards {
  grid-auto-rows: 30px 30px auto;
}
.wallet-4-cards {
  grid-auto-rows: 30px 30px 30px auto;
}

// etc...

使用第三种解决方案,您可以避免在 JS 代码中执行 CSS(您只需将 class 设置为 div),只有当您知道时,这才是一个不错的解决方案不可能有超过 5 或 6 张卡片,因为用几十个无用的定义污染你的 CSS 不是一件好事。