css 左对齐居中对齐的弹性框的最后一行

sulc1iza  于 2023-01-14  发布在  其他
关注(0)|答案(3)|浏览(218)

我有一个FlexBox。它的内容是NxN个正方形。我希望容器在给定的显示宽度下尽可能多地容纳这些正方形。我希望FlexBox在页面上居中对齐。
但是问题是当我使用

justify-content: center

图像:

那么最后一行就不会左对齐。但是如果我把

justify-content: left

图像:

那么整个容器在页面上就不再显示为居中对齐了。我能以某种方式实现两者的混合吗?在这个例子中,我将居中对齐5个项目,但最后一行将与前几行中的第一个项目对齐?
最小重现性:

<style>
  div { display: flex; flex-wrap: wrap; justify-content: center; }
  i { display: block; width: 300px; height: 300px; background: black; margin: 10px; }
</style>
<div>
  <i></i> <i></i> <i></i> <i></i> <i></i>
  <i></i> <i></i> <i></i>
</div>
deyfvvtc

deyfvvtc1#

您正在构建的布局是一个非常标准的网格。CSS网格将比flexbox更适合。
通过对列使用auto-fit并将每个列设置为固定大小,它将在容器中容纳尽可能多的列。justify-content: center将使列居中,但内容仍将在这些列中从左向右移动。
示例:

div {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fit, 160px);
    justify-content: center;
}

span {
    background: red;
    display: block;
    height: 160px;
}
<div>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
</div>
sqyvllje

sqyvllje2#

找到答案here
添加以下CSS工作

div:after {
    content: '';
    flex: auto;
    margin: 10px;
    max-width: 300px;
}

但是,它打破了iPad和移动的屏幕的响应,你可以通过添加上述CSS只为大屏幕使用媒体查询来修复.
我不建议这样做,如果可能的话,将flex-box切换到@nathan所述的网格

dffbzjpn

dffbzjpn3#

这里有一个解决问题的方法。我使用Angular ( typescript ),但原理是一样的。
首先,您需要以下两个方法/函数:

/** 
   * Returns the width of each item in the flexfox (they need to be equal width!)
   */
  getFlexboxItemWidth(selector: string){
    return document.querySelector(selector)?.getBoundingClientRect().width
  }

  /**
   * Returns the amount of additional, invisible flexbox items to place
   */
  calculateFlexboxFillerItemCount(totalItems: number, selector: string, flexboxSelector: string): number{
    const flexboxWidth: number = document.querySelector(flexboxSelector)?.getBoundingClientRect().width as number
    const itemsPerRow: number = Math.trunc(flexboxWidth / (this.getFlexboxItemWidth(selector) as number))
    const itemsInLastIncompleteRow: number = totalItems % itemsPerRow
    return isNaN(itemsPerRow) 
            || isNaN(itemsInLastIncompleteRow) 
            || itemsPerRow - itemsInLastIncompleteRow === Infinity 
            || itemsInLastIncompleteRow === 0 
              ? 0 
              : itemsPerRow - itemsInLastIncompleteRow + 1
  }

创建了这两个方法后,需要实现它们:

<!--The Flexbox-->
  <ion-list id="home-tab--item-list-container" *ngIf="items.length > 0">

    <!--Visible Flex Items-->
    <ion-card class="home-tab--item-card" *ngFor="let item of items" (click)="goToItemDetails(item)">
      <img [src]="item.images[0]">
      <ion-card-header>
        <ion-card-title>{{item.title}}</ion-card-title>
      </ion-card-header>
    
      <ion-card-content>
        {{item.description}}
        <div class="home-tab--item-slide-price">
          ${{item.cost.toFixed(2)}}
          <div class="home-tab--item-rental-period" *ngIf="item.rentalPeriod !== null">
             /{{item.rentalPeriod}}
          </div>
        </div>
      </ion-card-content>
    </ion-card>

    <!--Invisible Flexbox Items responsible for filling remaining space of last row-->
    <ion-card [ngStyle]="{width: getFlexboxItemWidth('.home-tab--item-card')+'px', visibility: 'hidden'}" *ngFor="let _ of [].constructor(calculateFlexboxFillerItemCount(items.length, '.home-tab--item-card', '#home-tab--item-list-container'))">
    </ion-card>

  </ion-list>

最后,下面是更好的上下文样式:

#home-tab--item-list-container {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    width: 100%;
    overflow: auto;
}

.home-tab--item-card {
    min-width: 170px;
    max-width: 300px;
    cursor: pointer;
}

@media screen and ( max-width: 960px) {
    .home-tab--item-card  { flex: 0 1 30% }
}

最终结果:

相关问题