【问题标题】:Place div below another div with property display:grid将 div 放在另一个具有属性 display:grid 的 div 下方
【发布时间】:2022-01-26 04:07:43
【问题描述】:

我在尝试使用 diplay:grid 将 div 放在另一个 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。当显示扩展卡片列表时,div(TEXT)被正确放置在列表下方,但是当堆叠卡片列表被激活时,div被放置在列表顶部,这是错误的,它应该放在堆叠下方/折叠的卡片列表。请参阅下面的图片。

【问题讨论】:

  • 您要显示多少堆栈列项?
  • 你的意思是堆叠了多少张卡片?如果是,它是一个动态值。问题与网格有关,因为 div (TEXT) 的行为就像是堆叠的另一张卡片,它应该放在堆叠的卡片下方,因为它是另一个 div..对吧?
  • 所以你真的想在网格下方显示文本?堆栈网格很适合你。
  • 我希望 div TEXT 保持在堆叠网格下方,就像第二张图片中 div TEXT 放在展开的卡片列表正下方一样。
  • 我已经给你发了邮件。请检查一下。谢谢。

标签: html css angular ionic-framework css-grid


【解决方案1】:

有趣的问题,因为“钱包”中的卡片数量可以是 1、2 或 N,而且 grid-auto-rows 和/或 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 技巧,只有纯网格 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 将类设置为 #wrapper

你也可以用JS检测卡片的数量,然后将正确的类应用于网格(#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(您只需将一个类设置为 div),只有当您知道不可能拥有更多像 5 或 6 张卡片时,这并不是一个糟糕的解决方案,因为用几十个无用的定义污染你的 CSS 不是一件好事。

【讨论】:

    【解决方案2】:

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

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

    stackedContainerHeight = 堆叠卡片的高度(以像素为单位) *(卡片/配置文件数组的长度 -1)+ 完整卡片高度 + 边距等调整。

    例如:

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

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

    [style.height.px]="stackedContainerHeight"
    

    最初的问题是什么:Grid-auto-rows 削减了容器高度和容器上最后一个完整卡流的一部分。此解决方案计算正确的高度,文本 div 将正确呈现在容器之后。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-14
      • 2016-03-18
      • 2016-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多