css 如何使弹性容器居中但使弹性项目左对齐

cvxl0en2  于 2023-02-14  发布在  其他
关注(0)|答案(9)|浏览(210)

我希望弹性项目居中,但当我们有第二行,有5(从下图)下1,而不是在父居中。

下面是我的一个例子:

ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
  padding: 0;
}
li {
  list-style-type: none;
  border: 1px solid gray;
  margin: 15px;
  padding: 5px;
  width: 200px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

http://jsfiddle.net/8jqbjese/2/

bd1hkmkf

bd1hkmkf1#

Flexbox挑战和局限性

困难在于如何将一组flex项居中并在换行时左对齐,但除非每行有固定数量的框,并且每个框都是固定宽度的,否则这在当前的flexbox中是不可能的。
使用问题中发布的代码,我们可以创建一个新的flex容器来 Package 当前的flex容器(ul),这将允许我们使用justify-content: center来居中ul
然后ul的flex项可以与justify-content: flex-start左对齐。

#container {
    display: flex;
    justify-content: center;
}

ul {
    display: flex;
    justify-content: flex-start;
}

这将创建一组居中的左对齐Flex项。
这种方法的问题是,在某些屏幕尺寸下,ul的右侧会有一个缺口,使其不再显示居中。
第一节第一节第一节第一节第一次
发生这种情况是因为在Flex布局中(实际上,通常是CSS)容器:
1.不知道元素何时换行;
1.不知道以前占用的空间现在是空的,并且
1.不会重新计算其宽度以收缩包裹较窄的布局。
右边空白的最大长度是容器期望的flex项的长度。
在下面的演示中,通过水平调整窗口大小,可以看到空白的出现和消失。
DEMO

更实用的方法

使用 * inline-block * 和 * 媒体查询 *,可以在没有Flexbox的情况下实现所需的布局。
超文本标记语言

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

中央支助系统

ul {
    margin: 0 auto;                  /* center container */
    width: 1200px;
    padding-left: 0;                 /* remove list padding */
    font-size: 0;                    /* remove inline-block white space;
                                        see https://stackoverflow.com/a/32801275/3597276 */
}

li {
    display: inline-block;
    font-size: 18px;                 /* restore font size removed in container */
    list-style-type: none;
    width: 150px;
    height: 50px;
    line-height: 50px;
    margin: 15px 25px;
    box-sizing: border-box;
    text-align: center;
}

@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }

上面的代码呈现了一个水平居中的容器,其子元素左对齐,如下所示:

DEMO

其他选项

Masonry是一个JavaScript网格布局库。它的工作原理是根据可用的垂直空间将元素放置在最佳位置,有点像泥瓦匠在墙上安装石头。你可能在互联网上到处都能看到它的使用。

这个CSS模块定义了一个二维的基于网格的布局系统,为用户界面设计进行了优化。在网格布局模型中,网格容器的子级可以放置在预定义的灵活或固定大小的布局网格中的任意位置。

dba5bblo

dba5bblo2#

你可以用CSS网格来实现它,只需要使用repeat(autofit, minmax(width-of-the-element, max-content))

ul {
       display: grid;
       grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
       grid-gap: 16px;
       justify-content: center;
       padding: initial;
}

li {
    list-style-type: none;
    border: 1px solid gray;
    padding: 5px;
    width: 210px;
}
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
</ul>

http://jsfiddle.net/rwa20jkh/

bnlyeluc

bnlyeluc3#

不知何故,@Joe82答案对我不起作用。然而,我发现这是正确的方法。在阅读了关于auto-fitauto-fillthis文章后,我发现自动调整在可能的情况下创建新列;然而,如果网格项的最大宽度允许的话,它会将它们折叠,使得网格项填充整个可用空间。

对于感兴趣的用户:auto-fill还在可能的情况下创建新列,但不允许它们折叠,因此它会创建空的可见列,这将占用空间。您可以在下图中看到这一点:

因此,我对“grid-template-columns”使用了repeat(auto-fit, minmax(10rem, 1fr)
然后,我将justify-items设置为center,这将对齐内联轴上网格区域内的项目。
我还希望在列和行之间有一些“边距”,所以我用简写添加了row-gap1remcolumn-gap
因此,我将以下CSS添加到div中,其中包含网格项:

.card-section {
  width: 100%;
  display: grid;
  justify-items: center;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}

我知道这并不完全是OP想要实现的,但也许它能帮助一些人,他们和我有同样的问题,偶然发现了这个问题。

mspsb9vt

mspsb9vt4#

您可以放置与其他元素具有相同类的不可见元素(出于展示目的,在示例中将其删除),并将高度设置为0。这样,您就可以将项目对齐到网格的最开头。

示例

<div class="table-container">
  <div class="table-content">
    <p class="table-title">Table 1</p>
    <p class="mesa-price">$ 20</p>
  </div>
  
  <!-- Make stuff justified start -->
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>

结果

q1qsirdb

q1qsirdb5#

正如@michael所建议的,这是当前flexbox的一个局限性,但是如果你仍然想使用flexjustify-content: center;,那么我们可以通过添加一个虚拟的li元素并赋值margin-left来解决这个问题。

const handleResize = () => {
        const item_box = document.getElementById('parentId')
        const list_length  = item_box.clientWidth
        const product_card_length = 200 // length of your child element
        const item_in_a_row = Math.round(list_length/product_card_length)
        const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
        const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin 
        const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
        dummy_product.style.marginLeft = `${left_to_set}px`
    }
    handleResize() // Call it first time component mount
    window.addEventListener("resize", handleResize);

选中此fiddle (resize and see )video for reference

krcsximq

krcsximq6#

获得所需样式和边距的一种方法是执行以下操作:

#container {
    display: flex;
    justify-content: center;
}

#innercontainer {
    display: flex;
    flex: 0.9; -> add desired % of margin
    justify-content: flex-start;
}
bq8i3lrv

bq8i3lrv7#

TL; DR

您可以在容器的末尾填充一些填充元素,并设置**visibility: hidden使其不可见,记住设置height: 0px**以防止高度被占用。

演示

在下面的示例中,您可以单击按钮以查看更改。
第一节第一节第一节第一节第一次

const container = document.getElementsByClassName('container')[0];

const item = document.createElement('div');
item.classList.add("item");

const filler = document.createElement('div')
filler.classList.add("filler");

item.appendChild(filler);

Array.from(Array(5).keys()).forEach(() => {
  container.appendChild(item.cloneNode(true));
});

function onShowClick() {
  const filler = document.getElementsByClassName('filler')
  for (let i = 0; i < filler.length; i++) {
    filler[i].style.border = "1px dashed #686868"
    filler[i].style.visibility = "visible"
    filler[i].style.height = "100px"
  }
};

function onHideClick() {
  const filler = document.getElementsByClassName('filler')
  for (let i = 0; i < filler.length; i++) {
    filler[i].style.border = "none"
    filler[i].style.visibility = "hidden"
    filler[i].style.height = "0px"
  }
};
* {
  box-sizing: border-box;
}

#root {
  height: 400px;
  width: 500px;
  border: 1px solid #ff955a;
}

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.item {
  padding: 5px;
}

.content-box {
  height: 100px;
  width: 100px;
  padding: 10px;
  background-color: lightblue;
  border-radius: 10px;
}

.filler {
  visibility: hidden;
  height: 0px;
  width: 100px;
}
<div id="root">
  <button onclick="onShowClick()">Show</button>
  <button onclick="onHideClick()">Hide</button>
  <div class="container">
    <div class="item">
      <div class="content-box">1</div>
    </div>
    <div class="item">
      <div class="content-box">2</div>
    </div>
    <div class="item">
      <div class="content-box">3</div>
    </div>
    <div class="item">
      <div class="content-box">4</div>
    </div>
    <div class="item">
      <div class="content-box">5</div>
    </div>
    <div class="item">
      <div class="content-box">6</div>
    </div>
    <div class="item">
      <div class="content-box">7</div>
    </div>
    <div class="item">
      <div class="content-box">8</div>
    </div>
    <div class="item">
      <div class="content-box">9</div>
    </div>
  </div>
</div>
2nbm6dog

2nbm6dog8#

我在使用React Native进行编码时遇到了这个问题。使用FlexBox有一个很好的解决方案。在我的特定情况下,我尝试将三个Flex框(Flex:2)在另一个里面使用alignItems。我想到的解决方案是使用两个空s,每个都有Flex:1.

<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
  <View style={{flex: 1}} />
    // Content here
  <View style={{flex: 1}} />
</View>

很容易转换成web/css。

jfgube3f

jfgube3f9#

我发现解决这个问题最简单的方法就是添加一些具有可见性的占位符:隐藏。这样它在换行时保持正确的间距。

相关问题