【问题标题】:Left aligned last row in centered grid of elements在元素的中心网格中左对齐最后一行
【发布时间】:2013-10-31 20:50:38
【问题描述】:

我有一堆相同大小的块设置为 display:inline-block 在一个 div 中设置了 text-align:center 以对齐块。

|        _____   _____   _____   _____       |
|       |     | |     | |     | |     |      |
|       |  1  | |  2  | |  3  | |  4  |      |
|       |_____| |_____| |_____| |_____|      |
|        _____   _____   _____   _____       |
|       |     | |     | |     | |     |      |
|       |  5  | |  6  | |  7  | |  8  |      |
|       |_____| |_____| |_____| |_____|      |
|                                            |

这些块水平填充 div,随着浏览器窗口的缩小,一些块会换行,从而创建更多的行和更少的列。我希望所有内容仍保持居中,最后一行与左侧齐平,如下所示:

|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  1  | |  2  | |  3  |       |
|       |_____| |_____| |_____|       |
|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  4  | |  5  | |  6  |       |
|       |_____| |_____| |_____|       |
|        _____   _____                |
|       |     | |     |               |
|       |  7  | |  8  |               |
|       |_____| |_____|               |
|                                     |

目前发生的情况是这样的:

|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  1  | |  2  | |  3  |       |
|       |_____| |_____| |_____|       |
|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  4  | |  5  | |  6  |       |
|       |_____| |_____| |_____|       |
|            _____   _____            |
|           |     | |     |           |
|           |  7  | |  8  |           |
|           |_____| |_____|           |
|                                     |

我不能像一个建议那样添加额外的填充 div,因为可能有任意数量的块,并且行和列的数量会因浏览器宽度而异。出于同样的原因,我也不能直接设置块 #7 的样式。无论有多少列,块必须始终居中

这里有一支笔可以更好地演示:

http://codepen.io/anon/pen/IDsxn

这可能吗?我觉得应该是的。我宁愿不使用 flexbox,因为它只有 ie10+,我想要 ie9+。我真的很想要一个纯 CSS 解决方案,但如果你告诉我 JS 是唯一的方法,我很乐意看到它的实际应用。

供参考 - 类似的问题,但没有一个被彻底解释:

How to align left last row/line in multiple line flexbox

CSS - Left align the last row of images in a centered div

Fix centering last line of elements in fluid container grid to be left aligned while container stays centered

Center multiple inline blocks with CSS and align the last row to the left

【问题讨论】:

  • @j08691 - 如果屏幕宽度小于容器最大宽度,那么您会看到问题。
  • 在容器上放一个背景色,然后你会看到它是如何不完全居中的。
  • 我可能猜想这是不可能的。或者,您可能需要大量媒体查询来准确指定每个屏幕尺寸的容器宽度。
  • @IvanDurst,我玩了很长一段时间,我发现为什么内联元素如此困难。它们本质上是文本(因此 html 中的空格会变得很奇怪)。一旦它们达到它们所在宽度的末端,就没有收缩包装。你不知道行何时结束,这就是为什么我们不能轻易地做悬挂标点。这是一个艰难的:)
  • 有趣的是我如何在你的问题中找到我的答案。

标签: css grid-layout text-align


【解决方案1】:

显示内联块的解决方案

这种自适应网格要简单得多:更少的标记和更少的 CSS,因此更容易在生产站点中实施并适应您的确切需求。

=>> DEMO (调整结果窗口大小以查看效果)

html, body {
    margin:0;
    padding:0;
}
#container{
    font-size:0;
    margin:0 auto;
    width:1000px;
}
.block {
    font-size:20px;
    width: 150px;
    height: 150px;
    margin:25px;
    background: gold;
    display:inline-block;
}

@media screen and (max-width: 430px) {
    #container{
        width:200px;
    }
}

@media screen and (min-width: 431px) and (max-width: 630px) {
   #container{
        width:400px;
    }
}
@media screen and (min-width: 631px) and (max-width: 830px) {
   #container{
        width:600px;
    }
}
@media screen and (min-width: 831px) and (max-width: 1030px) {
   #container{
        width:800px;
    }
}
<div id="container">
    <div class="block">1</div>
    <div class="block">2</div>
    <div class="block">3</div>
    <div class="block">4</div>
    <div class="block">5</div>
    <div class="block">6</div>
    <div class="block">7</div>
    <div class="block">8</div>
    <div class="block">9</div>
    <div class="block">10</div>
    <div class="block">11</div>
    <div class="block">12</div>
    <div class="block">13</div>
</div>

涉及到:

  1. 4 个媒体查询,用于 200 像素宽的块和可扩展至 1000 像素的容器。根据网格元素的宽度和容器的总宽度,您可能需要制作更少或更多

  2. 删除行内块元素之间的空白(在下面的演示中,我使用了字体大小技术,但您可以使用其他技术(请参阅 How to remove the space between inline-block elements? 了解其他技术)

  3. 块之间的固定边距

一行中的块数适应容器的大小。 text-align 属性保持默认值 left,因此最后的项目向左对齐。


在块和容器之间具有自适应边距的浮动

=>> DEMO (您需要将结果窗口的大小调整到 750px 以下才能看到它的实际效果)

html, body {
    margin:0;
    padding:0;
    min-width:150px;
}
.wrap {
    float:left;
    position:relative;
}
.foto {
    width: 150px;
    height: 150px;
    background: gold;
    position:absolute;
}

#warning{display:none;}
@media screen and (min-width: 631px) {
    .wrap {
        width:20%;
        padding-bottom:25%;
    }
    .wrap:nth-child(4n+2), .wrap:nth-child(4n+3){
        
    }
    .wrap .foto {
        top:-75px;
        margin-top:100%;
        right:-30px;
    }
    .wrap:nth-child(4n+2){
        margin:0 5% 0 7.5%;
    }
    .wrap:nth-child(4n+3){
     margin-right:7.5%;
    }
    .wrap:nth-child(4n+2) .foto{
        left:50%;
        margin-left:-75px;
    }
    .wrap:nth-child(4n+3) .foto{
        right:50%;
        margin-right:-75px;
    }
    .wrap:nth-child(4n) .foto{
        left:-30px;
    }   
    #container{
        margin-top:-45px;
    }
}

@media screen and (min-width: 481px) and (max-width: 631px) {
    .wrap {
        width:25%;
        padding-bottom:33.3%;
    }
    .wrap:nth-child(3n+2){
        margin:0 12.5%;        
    }
    .wrap .foto {
        top:-75px;
        margin-top:100%;
        right:-37px;
    }
     .wrap:nth-child(3n+2) .foto{
        left:50%;
        margin-left:-75px;
    }
     .wrap:nth-child(3n) .foto{
        left:-37px;
    }
    #container{
        margin-top:-37px;
    }
}


@media screen and (min-width: 331px) and (max-width: 480px) {
    .wrap {
        width:33.3%;
        padding-bottom:50%;
        clear:left;
    }
    .wrap:nth-child(even) {
        float:right;
        clear:right;
    }
    .wrap .foto {
        top:-75px;
        margin-top:100%;
        right:-50px;
    }
    .wrap:nth-child(even) .foto {
        left:-50px;
    }
    .wrap:nth-child(4n+3) .foto, .wrap:nth-child(4n+4) .foto {
        bottom:-75px;
        margin-bottom:100%;
    }
    #container{
        margin-top:-25px;
    }
}


@media screen and (max-width: 330px) {
    .wrap {
        width:50%;
        padding-bottom:100%;
        clear:left;
    }
    .wrap:nth-child(odd) .foto {
        right:-75px;
        bottom:0;
        bottom:-75px;
        margin-bottom:100%;
    }
    .wrap:nth-child(even) .foto {
        top:0px;
        right:-75px;
        top:-75px;
        margin-top:100%;
    }
}

@media screen and (min-width: 751px) {
    #warning{
        color:#fff;
        display:block;
        position:fixed;
        width:100%;
        height:50%;
        top:25%;
        left:0;
        background:#000;
        text-align:center;
        font-size:30px;
}
<div id="container">
    <div class="wrap"><div class="foto">1</div></div>
    <div class="wrap"><div class="foto">2</div></div>
    <div class="wrap"><div class="foto">3</div></div>
    <div class="wrap"><div class="foto">4</div></div>
    <div class="wrap"><div class="foto">5</div></div>
    <div class="wrap"><div class="foto">6</div></div>
    <div class="wrap"><div class="foto">7</div></div>
    <div class="wrap"><div class="foto">8</div></div>
    <div class="wrap"><div class="foto">9</div></div>
    <div class="wrap"><div class="foto">10</div></div>
    <div class="wrap"><div class="foto">11</div></div>
    <div class="wrap"><div class="foto">12</div></div>
    <div class="wrap"><div class="foto">13</div></div>
    <div class="wrap"><div class="foto">14</div></div>
    <div class="wrap"><div class="foto">15</div></div>
</div>

<!-- FOLLOWING JUST FOR THE DEMO -->
<div id="warning">I haven't written the code for windows bigger than 751px.<br/>
    You must resize this window under 751px.</div>

这项技术涉及:

  1. 浮动
  2. position:absolute;
  3. :nt-child()css 选择器
  4. 媒体查询

它将块在其容器中居中,并在所有块的顶部/左侧/紧/底部+容器的侧面提供相同的边距。由于此解决方案使用浮点数,因此最后一行左对齐。

一行的块数适应窗口的宽度。

【讨论】:

    【解决方案2】:

    值得一提的是:现在是 2017 年,grid layout module 开箱即用

    * {
        margin:0;
        padding:0;
    }
    
    .container {
      display: grid;
      grid-template-columns: repeat(auto-fill, 100px);
      grid-gap: 10px;
      justify-content: center;
      align-content: flex-start;
      margin: 0 auto;
      text-align: center;
      margin-top: 10px;
    }
    .block {
      background-color: #ddd;
      border: 1px solid #999;
      height: 100px;
      width: 100px;
    }
    <div class="container">
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
      <div class="block">Foo</div>
    </div>

    (Codepen demo).

    如果browser support 适合您 - 然后使用网格。如果没有,请继续阅读......


    正如@Web-tiki 的回答中提到的,使用 CSS 能做的最好的事情就是使用一系列媒体查询。

    话虽如此,如果您使用的是 LESS 等预处理器 - 这并不是一项困难或容易出错的任务。 (虽然,是的,CSS 仍然会很长而且很丑)

    UPDATED CODEPEN(调整窗口大小以查看结果)

    以下是利用 LESS 设置媒体查询的方法:

    首先根据你需要的设计设置一些较少的变量:

    @item-width:100px;
    @item-height:100px;
    @marginV: 4px;
    @marginH: 2px;
    @min-cols:2;
    @max-cols:9; //set an upper limit of how may columns you want to write the media queries for
    

    然后:

    像这样设置一个迭代混合:(您可以将此代码粘贴到http://less2css.org

    .loopingClass (@index-width) when (@index-width <= @item-width * @max-cols) {
        @media (min-width:@index-width) {
            .container{
                width: @index-width;
            }
        }
    
        .loopingClass(@index-width + @item-width + 2*@marginH);
    }
    
    .loopingClass (@item-width * @min-cols + @min-cols*@marginH*2);
    

    上面的mixin会以表格形式吐出一系列媒体查询:

    @media (min-width: 208px) {
      .container {
        width: 208px;
      }
    }
    @media (min-width: 312px) {
      .container {
        width: 312px;
      }
    }
    @media (min-width: 416px) {
      .container {
        width: 416px;
      }
    }
    @media (min-width: 520px) {
      .container {
        width: 520px;
      }
    }
    @media (min-width: 624px) {
      .container {
        width: 624px;
      }
    }
    @media (min-width: 728px) {
      .container {
        width: 728px;
      }
    }
    @media (min-width: 832px) {
      .container {
        width: 832px;
      }
    }
    

    剩余的 CSS (LESS):

    .container {
      margin: 0 auto;
      text-align: center;
      overflow: auto;
        min-width: @min-cols * @item-width;
        max-width: @max-cols * @item-width;
        display: block;
        list-style:none;
    }
    .block {
      background-color: #ddd;
      border:1px solid #999;
      box-sizing:border-box;
      float: left;
      height: @item-height;
      width: @item-width;
      margin:@marginV @marginH;
    }
    

    ... 你会得到想要的结果。

    ...自定义布局非常容易:

    我需要做的就是根据我的需要更改我在 LESS 混合中使用的变量 - 我得到了我想要的确切布局。

    【讨论】:

    • 创造力+1。虽然我很难接受这么多媒体查询
    • 我刚刚在帖子中添加了一个css网格解决方案:)
    【解决方案3】:

    您的问题没有“正常”解决方案,只有提到的“解决方法”。

    情况是,您的块容器将填满可用空间直至最大可用/设置,然后将所有内部块分解到下一行,这将导致容器溢出。此外,对于浮动等其他配置,它的行为也是相同的。这就是渲染的工作方式——每次都在空间中贪婪地计算内部元素的行为。

    也许未来Flexboxes 将使这成为可能 - 但我没有阅读完整的规格。只是猜测...

    【讨论】:

    • 谢谢 Mohre,你可能是对的。仅供参考,这应该是评论,而不是答案。
    【解决方案4】:

    这里有一个非常简单的 JavaScript(以及您的 CSS 中的一些小改动)解决方案:

    http://jsfiddle.net/ha68t/

    对我来说效果很好。

    CSS:

    .container {
      margin: 0 auto;
      max-width:960px;
      background-color: gold;
    }
    
    .block {
      background-color: #ddd;
      border:1px solid #999;
      display: block;
      float: left;
      height: 100px;
      margin: 4px 2px;
      width: 100px;
    }
    

    JavaScript:

    $(document).ready(function(){
        setContainerWidth();
    });
    
    $(window).resize(function(){
       setContainerWidth();
    });
    
    function setContainerWidth()
    {
        $('.container').css('width', 'auto'); //reset
        var windowWidth = $(document).width();
        var blockWidth = $('.block').outerWidth(true);
        var maxBoxPerRow = Math.floor(windowWidth / blockWidth);
        $('.container').width(maxBoxPerRow * blockWidth);
    }
    

    需要 jQuery :)

    【讨论】:

    • 这是这个页面上最简单的实现,即使它必须使用一点js。我不再需要解决方案,但有人会!
    • 在问题中你说你“真的很想要一个纯 CSS 解决方案”,但将此答案标记为已接受。不知道怎么回事,是不是对面?如果是,是否意味着不是?但如果不是,是否意味着即使不是,它也是?我是谁?现在是几奌?沃尔多在哪里?这么亮的光是什么?妈妈?........
    • @Cthulhu:哈哈。 “我真的喜欢一个纯 CSS 解决方案,但如果你告诉我 JS 是唯一的方法,我很乐意看到它的实际应用。”他付诸行动。我最喜欢他的解决方案。给你!
    • 这确实表明如果接受的解决方案使用 jQuery,CSS 是多么糟糕:(
    【解决方案5】:

    使用弹性框:

    .container {
      display: -webkit-flex;
       display: flex;
       -webkit-flex-direction: row; 
       flex-direction: row;
       -webkit-justify-content: flex-start;
       justify-content: flex-start;
       flex-wrap:wrap;
    }
    
    .block {
      background-color: #ddd;
      border:1px solid #999;
      display: inline-block;
      height: 100px;
      margin: 4px 2px;
      width: 100px;
    }
    

    完成。

    【讨论】:

    • 谢谢老鹰。这样做的问题是整组块在容器的左侧 inside 对齐,因此在容器内的某些尺寸下,右侧会有一个尴尬的白色边距(参见这支笔和调整窗口大小:codepen.io/anon/pen/pvXoEZ)。您可以使用justify-content: center; 解决此问题,但底部的块将居中对齐,而不是与第一列对齐,这是最初的问题。还希望支持 IE9+,但仍然希望看到 flexbox 解决方案。接近了!
    • @IvanDurst 您可以将flex-grow: 1; 添加到.block
    • @hawkeye126,如果您将flex-grow:1 添加到.block,您将调整最后一行的块大小,这不是我认为@IvanDurst 想要的。
    • @GabrielKohen 是正确的 - 我们不想单独调整任何块的大小,它们是固定大小的。
    【解决方案6】:

    用简单的 css 试试这个:

    CSS:

    .row{text-align:center;font-size:0;} .block{text-align:center;display:inline-block;width:150px;height:15px;margin:5px;边框:1px 实心#dddddd;字体大小:13px;}

    HTML:

    <div class="row">
      <div class="block"></div> 
    </div>
    

    .row{text-align:center;font-size:0;}
        .block{text-align:center;display:inline-block;width:150px;height:150px;margin:5px; border:1px solid #dddddd;font-size:13px;line-height:150px;}
    <div class="row">
          <div class="block">1</div> 
          <div class="block">2</div> 
          <div class="block">3</div> 
          <div class="block">4</div> 
          <div class="block">5</div> 
          <div class="block">6</div> 
          <div class="block">7</div> 
          <div class="block">8</div> 
        </div>

    【讨论】:

    • 元素没有在容器中居中 - 它们是左对齐的。左右边距需要相同。
    • 我没有看到任何问题,请详细说明。我已经编辑了保证金问题。
    • 元素需要在容器中居中,现在它们是左对齐的。再次阅读问题:)
    • @Ivan Durst,现在检查,我改为 text-align:center;在行上。
    • 除此解决方案外,上述方法均不适合我。伟大的! :) 这正是我所寻找的。​​span>
    【解决方案7】:

    使用 flexbox、一些伪元素、一个额外的 div,在经历了很多挫折之后,我能够在没有媒体查询的情况下实现这一点(因为我需要将我的网格放在许多不同大小的元素中,媒体查询实际上无法工作为了我)。

    一个警告:项目之间的排水沟是流动的。

    演示:http://codepen.io/anon/pen/OXvxEW

    CSS:

    .wrapper {
        display: flex;
        flex-wrap: wrap;
        border: 2px solid #ffc0cb;
        max-width: 1100px;
        margin: 0.5rem auto;
        justify-content: center;
    }
    
    .wrapper:after {
        content: ' ';
        flex: 1;
        height: 100%;
        border: 1px solid #00f;
        margin: 0.5rem;
    }
    
    .child {
        flex: 1;
        border: 2px solid #ffa500;
        min-width: 300px;
        margin: 0.5rem;
        text-align: center;
    }
    
    .child-contents {
        width: 300px;
        border: 2px solid #008000;
        height: 100px;
        margin: 0 auto;
    }
    

    HTML:

    <div class='wrapper'>
        <div class='child'>
            <div class='child-contents'></div>
        </div>
        <div class='child'>
            <div class='child-contents'></div>
        </div>
        <div class='child'>
            <div class='child-contents'></div>
        </div>
    
        ...etc., more .child's...
    
    </div>
    

    最终结果是这样的,绿色矩形是 div。粉红色/橙色边框仅供参考,以便您了解发生了什么。如果您移除粉红色/橙色边框,您应该会得到您正在寻找的网格(不过,请注意,排水沟是流动的)。

    【讨论】:

    • 我会在有时间的时候再看看这个,但你可能会有所收获。 (虽然它在 Safari 9.1 中被破坏了)
    • 这种方法对我真的很管用!在伪元素上使用flex: auto 确实会有所作为。我一直在寻找这个解决方案。谢谢!
    【解决方案8】:

    迄今为止,唯一干净的解决方案是使用

    CSS Grid Layout Module (Codepen demo)

    基本上必要的相关代码归结为:

    ul {
      display: grid; /* (1) */
      grid-template-columns: repeat(auto-fill, 120px); /* (2) */
      grid-gap: 1rem; /* (3) */
      justify-content: center; /* (4) */
      align-content: flex-start; /* (5) */
    }
    

    1) 使容器元素成为网格容器

    2) 使用宽度为 120 像素的“自动”列数设置网格。 (自动填充值用于响应式布局)。

    3) 为网格行和列设置间隙/gutters。

    4) 和 5) - 类似于 flexbox。

    body {
      margin: 0;
    }
    ul {
      display: grid;
      grid-template-columns: repeat(auto-fill, 120px);
      grid-gap: 1rem;
      justify-content: center;
      align-content: flex-start;
      
      /* boring properties: */
      list-style: none;
      width: 90vw;
      height: 90vh;
      margin: 2vh auto;
      border: 5px solid green;
      padding: 0;
      overflow: auto;
    }
    li {
      background: tomato;
      height: 120px;
    }
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
      <li>6</li>
      <li>7</li>
      <li>8</li>
      <li>9</li>
      <li>10</li>
    </ul>

    Codepen demo(调整大小看效果)


    浏览器支持 - Caniuse

    Chrome (Blink) 和 Firefox 目前支持,IE 和 Edge 部分支持(参见 Rachel Andrew 的 this post


    进一步阅读 CSS 网格:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 2015-01-03
      • 2016-09-05
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 2012-08-27
      相关资源
      最近更新 更多