【问题标题】:Fluid width with equally spaced DIVs等距 DIV 的流体宽度
【发布时间】:2011-10-15 11:08:17
【问题描述】:

我有一个流体宽度的容器 DIV。

在这里面我有 4 个 DIV,都是 300px x 250px...

<div id="container">
   <div class="box1"> </div>
   <div class="box2"> </div>
   <div class="box3"> </div>
   <div class="box4"> </div>
</div>

我想要发生的是框 1 向左浮动,框 4 向右浮动,框 2 和 3 在它们之间均匀间隔。我希望间距是流动的,以便浏览器变小,空间也变小。

【问题讨论】:

  • 为什么不使用display:inline-block; 而不是浮动?
  • 因为 IE6/IE7 仅支持 inline-block on inline 元素
  • 好的,不确定您要使用哪种浏览器。
  • 我能想到的最接近的解决方案是将每个子 .box div 包装在另一个宽度为 25% 的 div 中。然后,将子 .box div 居中到包装器。 .box div 将均匀分布,但左右 div 不会在边缘。
  • 我把@Paul Sham 的想法变成了JSFiddle

标签: html css fluid-layout


【解决方案1】:

见:http://jsfiddle.net/thirtydot/EDp8R/

  • 这适用于 IE6+ 和所有现代浏览器!
  • 我已将您要求的尺寸减半只是为了更易于使用。
  • text-align: justify 结合 .stretch 是处理定位的内容。
  • display:inline-block; *display:inline; zoom:1 修复了 IE6/7 的 inline-blocksee here
  • font-size: 0; line-height: 0 修复了 IE6 中的一个小问题。

#container {
  border: 2px dashed #444;
  height: 125px;
  text-align: justify;
  -ms-text-justify: distribute-all-lines;
  text-justify: distribute-all-lines;
  /* just for demo */
  min-width: 612px;
}

.box1,
.box2,
.box3,
.box4 {
  width: 150px;
  height: 125px;
  vertical-align: top;
  display: inline-block;
  *display: inline;
  zoom: 1
}

.stretch {
  width: 100%;
  display: inline-block;
  font-size: 0;
  line-height: 0
}

.box1,
.box3 {
  background: #ccc
}

.box2,
.box4 {
  background: #0ff
}
<div id="container">
  <div class="box1"></div>
  <div class="box2"></div>
  <div class="box3"></div>
  <div class="box4"></div>
  <span class="stretch"></span>
</div>

多余的span (.stretch) 可以替换为:after

在与上述解决方案相同的所有浏览器中,这仍然有效:after 在 IE6/7 中不起作用,但无论如何他们都在使用 distribute-all-lines,所以没关系。

见:http://jsfiddle.net/thirtydot/EDp8R/3/

:after 有一个小缺点:要使最后一行在 Safari 中完美运行,您必须小心 HTML 中的空格。

具体来说,这是行不通的:

<div id="container">
    ..
    <div class="box3"></div>
    <div class="box4"></div>
</div>

确实如此:

<div id="container">
    ..
    <div class="box3"></div>
    <div class="box4"></div></div>

您可以将其用于任意数量的子 divs,而无需通过更改为每个子添加 boxN

.box1, .box2, .box3, .box4 { ...

#container > div { ...

这会选择#container div 的第一个子元素的任何 div,并且在它下面没有其他子元素。要概括背景颜色,您可以使用CSS3 nth-order selector,尽管它仅在 IE9+ 和其他现代浏览器中受支持:

.box1, .box3 { ...

变成:

#container > div:nth-child(odd) { ...

有关 jsfiddle 示例,请参阅 here

【讨论】:

  • 我花了 3 小时才发现在 html 中的每个框之间应该有空格。 “对齐”扩展元素之间的空格,如果您的内容是 &lt;div/&gt;&lt;div/&gt;&lt;div/&gt;,则它不起作用。你需要有&lt;div/&gt; &lt;div/&gt; &lt;div/&gt;
  • 只是想指出:),因为如果您使用生成的内容(这是常见情况),很难注意到。我想在这种情况下使用justify,但感谢您提供一个可行的解决方案。为我节省了很多实验(尽管调试了 3 小时 :D)。此外,我可以添加一个注释,如果您希望最后一行左对齐,您应该添加一些额外的不可见框(以完成该行)
  • @venimus:我使用这种技术写了另一个答案:stackoverflow.com/questions/10548417/…。你做了什么来消除添加不可见框造成的额外高度?
  • 有人可以解释为什么 .stretch 是必要的吗?
  • @HartleySan:.stretch/:after 是必需的,因为(通常)带有对齐的文本,the last line is not justified。在这里,我们确实希望最后一行是合理的,因此需要:after。至于你的第二个问题,我刚才探讨过in a previous answer。在那个答案中,JavaScript 是必需的。如果您需要支持旧版浏览器 (IE8),那么我相信您确实需要 JavaScript。
【解决方案2】:

如果 css3 是一个选项,则可以使用 css calc() 函数来完成。

案例 1:在一行中对齐框 (FIDDLE)

标记很简单 - 一堆带有一些容器元素的 div。

CSS 看起来像这样:

div
{
    height: 100px;
    float: left;
    background:pink;
    width: 50px;
    margin-right: calc((100% - 300px) / 5 - 1px); 
}
div:last-child
{
    margin-right:0;
}

-1px 处修复 IE9+ 计算/舍入错误 - 请参阅 here

案例 2:多行对齐框 (FIDDLE)

这里,除了calc()函数,media queries是必须的。

基本思想是为每个#columns 状态设置一个媒体查询,然后我使用 calc() 计算每个元素(最后一列中的元素除外)的边距。

这听起来工作量很大,但如果你使用 LESS 或 SASS,这可以很容易地完成

(仍然可以使用常规 css 完成,但是您必须手动进行所有计算,然后如果您更改框宽度 - 您必须重新计算所有内容)

以下是使用LESS的示例:(您可以复制/粘贴此代码here来玩它,[这也是我用来生成上述小提琴的代码])

@min-margin: 15px;
@div-width: 150px;

@3divs: (@div-width * 3);
@4divs: (@div-width * 4);
@5divs: (@div-width * 5);
@6divs: (@div-width * 6);
@7divs: (@div-width * 7);

@3divs-width: (@3divs + @min-margin * 2);
@4divs-width: (@4divs + @min-margin * 3);
@5divs-width: (@5divs + @min-margin * 4);
@6divs-width: (@6divs + @min-margin * 5);
@7divs-width: (@7divs + @min-margin * 6);


*{margin:0;padding:0;}

.container
{
    overflow: auto;
    display: block;
    min-width: @3divs-width;
}
.container > div
{
    margin-bottom: 20px;
    width: @div-width;
    height: 100px;
    background: blue;
    float:left;
    color: #fff;
    text-align: center;
}

@media (max-width: @3divs-width) {
    .container > div {  
        margin-right: @min-margin;
    }
    .container > div:nth-child(3n) {  
        margin-right: 0;
    }
}

@media (min-width: @3divs-width) and (max-width: @4divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{3divs})/2 - 1px)";
    }
    .container > div:nth-child(3n) {  
        margin-right: 0;
    }
}

@media (min-width: @4divs-width) and (max-width: @5divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{4divs})/3 - 1px)";
    }
    .container > div:nth-child(4n) {  
        margin-right: 0;
    }
}

@media (min-width: @5divs-width) and (max-width: @6divs-width) {
    .container > div {  
        margin-right: ~"calc((100% - @{5divs})/4 - 1px)";
    }
    .container > div:nth-child(5n) {  
        margin-right: 0;
    }
}

@media (min-width: @6divs-width){
    .container > div {  
        margin-right: ~"calc((100% - @{6divs})/5 - 1px)";
    }
    .container > div:nth-child(6n) {  
        margin-right: 0;
    }
}

所以基本上你首先需要确定一个盒子宽度和你想要的盒子之间的最小边距。

这样,您可以计算出每个州需要多少空间。

然后,使用 calc() 计算右边距,并使用 nth-child 从最后一列的框中删除右边距。

与使用text-align:justify 的已接受答案相比,此答案的优势是,当您有不止一排框时 - 最后一行的框不会“合理”,例如:如果最后一行还剩下 2 个盒子 - 我不希望第一个盒子在左边,下一个在右边 - 而是让盒子按顺序相互跟随。

关于浏览器支持:这将适用于 IE9+、Firefox、Chrome、Safari6.0+ -(请参阅here 了解更多详细信息)但是我注意到在 IE9+ 上有点媒体查询状态之间的故障。 [如果有人知道如何解决这个问题,我真的很想知道:)] HERE

【讨论】:

    【解决方案3】:

    jQuery 中,您可以直接定位到父级。

    如果您不知道到底有多少孩子,这很有用 动态添加,或者如果您无法确定他们的数量。

    var tWidth=0;
    
    $('.children').each(function(i,e){
    tWidth += $(e).width();
    
    ///Example: If the Children have a padding-left of 10px;..
    //You could do instead:
    tWidth += ($(e).width()+10);
    
    })
    $('#parent').css('width',tWidth);
    

    这将使parent 在添加children 时水平增长。

    注意:这假设 '.children' 有一个 widthHeight

    希望有所帮助。

    【讨论】:

      【解决方案4】:

      现在最简单的方法是使用 flexbox:

      http://css-tricks.com/snippets/css/a-guide-to-flexbox/

      CSS 很简单:

      #container {
          display: flex;
          justify-content: space-between;
      }
      

      演示:http://jsfiddle.net/QPrk3/

      但是,目前只有相对较新的浏览器 (http://caniuse.com/flexbox) 支持。 此外,flexbox 布局的规范已经更改了几次,因此可以通过另外包含旧语法来覆盖更多浏览器:

      http://css-tricks.com/old-flexbox-and-new-flexbox/

      http://css-tricks.com/using-flexbox/

      【讨论】:

      • 谢谢你,这太容易了,我将它应用到页面底部固定的页脚中的四个均匀间隔的列表中。在 FF28.0、Chrome 34.0.1847.116 m 和 IE11 中工作过。
      • Flexbox 不是网络上最受支持的工具,它也无法击败经典的边距和内边距方法。
      • 对于所有寻找未定义宽度的多个 div 对齐的人:使用 flex-wrap 和 display: flex 选项。它将用动态宽度包装 div。
      【解决方案5】:

      如果您知道每“行”的元素数量和容器的宽度,则可以使用选择器为需要的元素添加边距,以产生合理的外观。

      我有三个我想要合理的 div 行,所以使用了:

      .tile:nth-child(3n+2) { margin: 0 10px }

      这允许每行中的中心 div 有一个边距,迫使第一个和第三个 div 到容器的外部边缘

      也适用于边框背景颜色等其他方面

      【讨论】:

        【解决方案6】:

        这对我有用,有 5 张不同尺寸的图片。

        1. 创建容器 div
        2. 图像的无序列表
        3. 在 css 上,无序必须垂直显示且没有项目符号
        4. 对齐容器 div 的内容

        这是因为 justify-content:space-between,它在一个列表中,水平显示。

        关于 CSS

         #container {
                    display: flex;
                    justify-content: space-between;
         }
            #container ul li{ display:inline; list-style-type:none;
        }
        

        在 html 上

        <div id="container"> 
          <ul>  
                <li><img src="box1.png"><li>
                <li><img src="box2.png"><li>
                <li><img src="box3.png"><li>
                <li><img src="box4.png"><li>
                <li><img src="box5.png"><li>
            </ul>
        </div>
        

        【讨论】:

        • 虽然这段代码可能很好用,但一个好的答案应该包括解释它是如何工作的以及为什么它是一个好的解决方案。
        • 值得注意的是 IE caniuse.com/#feat=flexbox 不(或仅部分)支持 flexbox
        • 这是响应式的吗?
        【解决方案7】:

        其他帖子都提到了flexbox,但是如果需要多行项目,flexbox的space-between属性失败(见文末)

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

        CSS Grid Layout Module (Codepen demo)

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

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

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

        2) 根据需要设置具有“自动”列数的网格。这是为响应式布局完成的。每列的宽度为 120 像素。 (注意使用auto-fit(与auto-fill相对),它(对于1行布局)将空轨道折叠为0 - 允许项目展开以占用剩余空间。(查看@ 987654324@ 看看我在说什么))。

        3) 为网格行和列设置间隙/间距 - 在这里,因为需要“间距”布局 - 间隙实际上是最小间隙,因为它会根据需要增大。

        4) 和 5) - 类似于 flexbox。

        body {
          margin: 0;
        }
        ul {
          display: grid;
          grid-template-columns: repeat(auto-fit, 120px);
          grid-gap: 1rem;
          justify-content: space-between;
          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></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
        </ul>

        Codepen demo(调整大小看效果)


        浏览器支持 - Caniuse

        目前受 Chrome (Blink)、Firefox、Safari 和 Edge 支持! ... 在 IE 的部分支持下(参见 Rachel Andrew 的 this post


        注意:

        Flexbox 的 space-between 属性对一行项目非常有效,但是当应用于包装它的项目的 flex 容器时 - (使用 flex-wrap: wrap) - 失败,因为您无法控制最后一行的对齐方式项目; 最后一行将总是被证明是合理的(通常不是你想要的)

        演示:

        body {
          margin: 0;
        }
        ul {
          
          display: flex;
          justify-content: space-between;
          flex-wrap: wrap;
          align-content: flex-start;
          
          list-style: none;
          width: 90vw;
          height: 90vh;
          margin: 2vh auto;
          border: 5px solid green;
          padding: 0;
          overflow: auto;
          
        }
        li {
          background: tomato;
          width: 110px;
          height: 80px;
          margin-bottom: 1rem;
        }
        <ul>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
        </ul>

        Codepen(调整大小看看我在说什么)


        进一步阅读 CSS 网格:

        【讨论】:

        • 非常被低估的答案。这是实现我想做的最简单和最有效的方法。谢谢。
        • 这是最少量的 CSS(而且没有 JS!),它产生了我正在寻找的行为,只是对大小和空间进行了一些调整。
        • 找了好久终于找到了!谢谢@Danield
        猜你喜欢
        • 2015-02-19
        • 1970-01-01
        • 2012-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-26
        • 1970-01-01
        相关资源
        最近更新 更多