将变宽的网格居中,同时将其元素向左对齐

5
请确认以下内容:
考虑以下情况:
<div class="container">
     <div class="grid">
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
         <div class="unit"></div>
          ....
      </div>
</div>

使用图片,基本上我有这样的东西
如您所见,绿色块和容器都靠左对齐。
我想要实现的是这样的效果。
.unit元素具有恒定的宽度。
.grid元素应该随着宽度扩展(以便更多的单元元素适合一行),同时始终在.container内居中。
有什么办法只使用CSS(如果必要,可以使用一些html包装器)来实现这个目标吗?

没有看到 CSS,很难说。这是由浮动引起的。当使用浮动时,没有简单的方法来使子元素在父容器中居中。如果容器是固定宽度的,您可以尝试添加 margin: 0 auto; 以使容器本身居中。 - EternalHour
有趣的问题。 - DRD
我不使用任何浮点数..边距无法正常工作,因为如果我将 grid 设置为 block,则无法像图像中那样居中 units - man
5个回答

1
让我首先说,这是一个有趣的问题,我的第一反应是使用flexbox来解决。我尝试了各种flexbox排列方式,但这种类型的解决方案却避而不及。因此,下面是使用浮动、清除和媒体查询的解决方案。
对于这个示例,我假设每行至少有3个方块,但不超过9个方块。但是,您可以扩展此解决方案以处理1个到超过9个方块之间的任何数量。
以下是HTML代码:
<div class="grid">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

这是一段 CSS 代码,它(1)执行迷你重置以消除浏览器应用的填充和边距,可能会干扰大小,和(2)格式化 .grid 及其 div 子元素。
* {
    margin: 0;
    padding: 0;
}

.grid {
    display: table;
    outline: 1px solid blue;
    min-width: 330px;
    margin: 0 auto;
}

.grid > div {
    width: 100px;
    height: 61px;
    margin: 5px;
    background-color: teal;
    float: left;
}

由于.grid显示为表格,因此消除了.container块。后者是一个包裹其子元素的收缩块,可以应用margin: 0 auto将其居中于页面上。 .gridmin-width为330px,确保每行至少可以容纳三个块。每个.grid div子元素占据110px的水平空间(100px宽度+左右10px的边距),这个数字对于下面的媒体查询代码非常重要。在table元素内部进行浮动时,其边距不会折叠,因此不需要明确清除浮动(例如,通过clearfix)。
@media screen and (min-width: 330px) and (max-width: 439px) {
    .grid > div:nth-of-type(3n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 440px) and (max-width: 549px) {
    .grid > div:nth-of-type(4n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 550px) and (max-width: 659px) {
    .grid > div:nth-of-type(5n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 660px) and (max-width: 769px) {
    .grid > div:nth-of-type(6n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 770px) and (max-width: 879px) {
    .grid > div:nth-of-type(7n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 880px) and (max-width: 989px) {
    .grid > div:nth-of-type(8n + 1) {
        clear: left;
    }
}

@media screen and (min-width: 990px) {
    .grid > div:nth-of-type(9n + 1) {
        clear: left;
    }    
}

代码背后的理念是:如果每行只有足够的空间容纳 n 个块,则每第 (n+1) 个块的左边缘会被清除,将该块移动到新行。
这里有一个示例:http://jsfiddle.net/5hWXw/。调整预览窗口大小以查看调整效果。

这实际上解决了问题,但问题是它不是通用的。想象一下,如果我有一行中有20个或更多块,条件是屏幕宽度,这是我不想依赖的。 - man
我们都必须在一定的限制内工作。考虑到您的具体要求 - 仅使用CSS解决方案,将一个 .grid 居中,并在其容器内伸缩适当,以完美地收紧流向左侧的固定大小块 - 这就是我能想出的最好的解决方案了。祝贺您。 - DRD
这是我与@Tyblitz的对话产生的产品 - 一种使用jQuery的通用解决方案:http://jsfiddle.net/GWQSe/. - DRD
似乎可以通过添加尾随的空元素来完成,而无需使用jquery。 - man
.unit的大小和用户浏览器的宽度将影响您需要多少尾随空元素。这肯定需要一些好的代码。而且,这绝不是最佳解决方案,因为如果例如对于一个屏幕尺寸,您需要5个尾随块,则对于调整大小的浏览器,其中一些尾随元素需要被删除。更多的代码。总的来说,使用间隔元素会让人想起间隔gif的日子。这不是最优雅的做事方式。使用纯CSS和媒体查询听起来更好。 - DRD

0

你只需要像这样为你的类赋值:

.grid { text-align:center; }

.unit { display:inline-block; }

我希望这可以解决你的问题。

如果不能,那么请通过Jsfiddle展示你的完整代码。


0

@DRD的回答很好,但需要大量媒体查询。然而,如果以下内容适合您:当它可以简单时,不要过于追求:在容器上设置padding-left/-right...

.grid {
  padding: 0 5%;
}

当宽度不是.unit整个盒子(填充、边距、边框、宽度)的倍数时,您会注意到空格不均匀。设置基于百分比的宽度可以帮助解决这个问题。

请参见this fiddle进行测试。我添加了一点JavaScript来动态调整填充,删除它以查看仅使用CSS的结果。编辑:@DRD创建了一个比我的JS更好的jQuery函数,请在此处here查看(如果要使用它,请不要忘记包含jQuery)。


我很想看看这个解决方案的演示。 - DRD
@DRD,我fork了你的fiddle并将其添加到我的答案中,很好的观点。 - webketje
1
使用JS调整填充是一种方法,但它也会产生很多闪烁。这里有一个解决方案,让浏览器完成所有定位工作,脚本决定将clear: left应用于哪些元素。体验更加流畅,解决方案是可推广的,无需使用媒体查询:http://jsfiddle.net/GWQSe/。此外,即使我使用jQuery而不是直接与DOM交互,它也使用更少的处理能力。 - DRD
@DRD 很好的修复,我会将其添加到我的答案中!只有在缩小窗口时才会出现闪烁问题(?),我没有花时间在常规JS中进行更正。如果能够在本机JS中使其工作,那就更完美了。虽然如果该函数仅在页面加载时触发(用户并不总是调整窗口大小,尽管偶尔可能会这样做),两者都可以正常工作。非常感谢您的贡献。 - webketje

0

看起来解决方法类似于这里Flex-box: Align last row to grid

首先将.grid设置为inline,然后添加更多的带有height: 0的div即可,额外的div数量应至少等于一行中units的最大数量(减1)。

这有点不方便,但仍然比定义多个@media简单,也不需要处理javascript/window.resize()。

<div class="container">
    <div class="grid">
        <div class="unit"></div>
        <div class="unit"></div>
        <div class="unit"></div>
        <div class="unit"></div>
        <div class="unit"></div>
        <div class="unit"></div>
        <div class="unit empty"></div>
        <div class="unit empty"></div>
        <div class="unit empty"></div>
        <div class="unit empty"></div>
        <div class="unit empty"></div>
        <div class="unit empty"></div>
        <div class="unit empty"></div>
    </div>
</div>


.container {
   display: block;
   text-align: center;
}

.empty {
   height: 0 !important;
}

.grid {
   display: inline;
}

我仍然希望能够使用纯CSS找到更好的解决方案


您所链接的帖子中提到的 Codepen 使用了弹性盒排列,其中盒子的尺寸会根据浏览器宽度而改变:http://jsfiddle.net/4z8b4/。一旦您固定它们的宽度,解决方案就会崩溃:http://jsfiddle.net/nkX6p/。 - DRD
还有一件事,我就完成了这个线程。CSS仍然是一种表现性语言,所以要明智地选择战斗,伙计。我预测在未来,我们会在CSS中轻松地完成许多我们现在在JS中做的事情。 - DRD

0
在你的CSS中,请确保: 1. 在.grid规则中,将text-align设置为center 2. 在.unit规则中,将display设置为inline-blockdiv元素是块级元素,因此每个新元素都显示在新行上。将display属性的值设置为inline-block会强制所有具有类unitdiv在同一行上显示(直到没有更多空间)。此外,text-align: center不适用于显示属性设置为block的元素,块级元素默认具有block的显示值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接