CSS流体柱,固定边距;圣杯的圣杯

时间:2011-08-25 12:58:31

标签: html css fluid-layout

更新&摘要

我觉得有义务让这个问题更加清晰,因为现在已经有了赏金。

另外,我很确定当支持calc() CSS3单位值时,这将是孩子的游戏,做width: calc(25% - 5px)之类的事情;虽然我们可能会浏览互联网在我们的脑海中

我正在为一些共享设计要求的项目开发一个CSS框架;即流体12列布局。使用宽度为.column的浮动(100% / 12) x col_size元素,这相当容易。但是,问题在于在列之间添加固定边距(或任何形式的间距)。

我的初步尝试使用了所描述的流体柱,每个都嵌套了.panel个孩子。下面是HTML / CSS片段(为了简洁而简化):

.column{
    float: left;
    display: inline-block;
}

.width-01{ width:  8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width:      25%; }
/* etc */

.panel{
    width: 100%;
    padding: 5px;
    box-sizing: border-box; /* so padding doesn't increase width */
}
<div class="column width-02">
    <div class="panel">Width-02</div>
</div>
<div class="column width-03">
    <div class="panel">Width-03</div>
</div>
<div class="column width-02">
    <div class="panel">Width-02</div>
</div>
<div class="column width-05">
    <div class="panel">Width-05</div>
</div>

此代码段会产生类似于下图的布局,但所有.panel元素的所有边都有5px个填充。 我正在尝试使外部列的内容边缘与视口的边缘(或父容器齐平。另一种方法是完全消除.panel类,并且只使用列:

.column{
    float: left;
    display: inline-block;
    padding-left: 10px;
    box-sizing: border-box;
}

.column:first-child{ padding-left: 0px; }

.width-01{ width:  8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width:      25%; }
/* etc */
<div class="column width-02">Width-02</div>
<div class="column width-03">Width-03</div>
<div class="column width-02">Width-02</div>
<div class="column width-05">Width-05</div>

再次,这很好用,产生的结果更接近下图的结果,但是现在(实际)问题是填充正在进入列的宽度拧紧向上宽度分布。 :first-child列有10个像素(或任何边距大小),其内容区域宽度大于其兄弟姐妹。

这看似无害,甚至不明显;然而,有一些情况下,元素之间的完全尽可能精确)宽度分布是必要的,或者会使事情变得更加容易。

所以,是否使用填充,边距或其组合;是否有任何流体柱,固定边距,具有均匀分布的沟槽空间的解决方案,不会从相邻列中抢夺“边缘”(***哈哈* )内容区域? **


原始问题

由于我的搜索和尝试简单缺乏结果,我得出结论这是不可能的。如果任何地方都能得到答案,我肯定它就在这里。

有没有办法,使用纯CSS来实现具有固定宽度边距的流畅宽度圆柱布局?

重要提示 :这个数字只是一个例子,而不是我想要实现的具体布局。给定的解决方案应允许相邻列的任何组合,总宽度分布总计为12或更小。考虑一下流行的960 grid作为参考。)

super_awesome_layout.css
注意 :在12列布局中,图像中列的宽度分布分别为2,3,2和5. < / p>

到目前为止,我已经使用了一个网格,使用百分比,几乎完成了这个。问题是,为了获得边距,每列需要一个额外的孩子(我称之为.panel ):

width: 100%;
box-sizing: border-box;
padding: 10px;

这是几乎,很好;问题在于这种方法是第一列和最后一列具有外部“边距”( 10px ),并且每列之间的“边距”加倍( {{1} }

当然,通过包含新的CSS3 2 x 10px值类型,可以更轻松地解决这个问题。方向:

calc()

我有一些Javascript修复,我已经破解了一些“有效”的东西,但我正在寻求。希望最大的圣杯存在。

以下的解决方案,以及@avall提供的(虽然肯定是简化上的一个很好的选择)但遗憾的是我并不是我想要的。主要问题是,边距不会在列之间平均分配。

我能看到这种方法的唯一方法是将.width-12 > .panel{ width: 100%; } .width-09 > .panel{ width: calc(75% - 10px); margin: ...; } 填充减少到.panel,例如:

5px

这个解决方案是不可接受的,只是因为IE8无法识别.column:first-child > .panel { padding-left: 0px; } .column:last-child > .panel { padding-right: 0px; } /* not necessary? in any case, haven't tested */ .column:only-child > .panel { padding-right: 0px; padding-left: 0px; } 以及那个:last-child )伪选择器。

10 个答案:

答案 0 :(得分:64)

我终于明白了。在过去的十年中浪费了数百小时的浪费(虽然我依赖于一些年前无法工作的css)。我解决了它没有任何陷阱。在IE8 +中。

请准备2001:太空漫游音乐,因为我要登陆这艘船。

这种方法的天才和技巧在于使用内联块元素,然后使用字间距来使用负右边距进行平衡。它自身的负右边距会将元素拉到一起,允许你设置100%的宽度并且仍然适合它们之间的东西,但是让元素重叠。设置父母的负边距只是撤消子边距关于与总宽度交互的影响(我们试图击中的魔术“100%宽度”标记“)。填充仅用于增加元素的大小对于反作用边际而言,它是无用的。它通常用于陪审团操纵解决这个问题的盒子大小,但代价是失去了使用填充的能力,否则可能需要更多包装元素。

字间距提供了神奇的“第三种方式”来添加或删除两个元素之间的水平距离,只要它们是内联块,因为在这种情况下它们将被计为单个“单词”,并且它们之间的任何空格都是collpapse到一个可控的“字间距”属性。除了这个技巧,我还没有意识到获得100%结果的另一种方法。

我谦卑地提出了固定排水沟柔性柱问题的最终答案。我在此命名我的解决方案“欧米茄机动”。它具有处理任意混合宽度列的能力(精确加起来总宽度的100%或略小于圆角),任何装订线尺寸,宽度上任何预定义的列数,使用自动换行处理任意数量的行,以及因此使用内联块元素,因此提供了内联块附带的垂直对齐选项,并且它不需要任何额外的标记,并且只需要在容器上使用单个类声明(不计算定义列宽度)。我认为代码说明了一切。这是2-6列的代码实现,使用10px排水沟和百分比奖金助手类。

编辑:有趣的难题。我设法得到两个略有不同的版本;一个用于mozilla和ie8 +,另一个用于webkit。似乎单词间距技巧在webkit中不起作用,我不知道为什么其他版本在webkit中工作但不是ie8 + / mozilla。将两者结合起来可以让你覆盖所有内容,我愿意打赌有一种方法可以统一这种策略或类似于解决问题的方法。

EDIT2:大部分都得到了!神奇text-align: justify几乎在那里使用单词间距获取WebKit。间距似乎有点偏离,就像右边的像素,也可能是排水沟中的一个。但它可以使用,并且保持列比我之前使用的任何东西看起来更可靠。它永远不会减少到更少的列,它会压缩,直到浏览器获得一个水平滚动条。

Edit3:有点接近完美。将font-size设置为0会将大部分剩余问题规范化,并使间距关闭。现在只需要修复IE9,如果它的字体大小为0,就会崩溃它。

EDIT4:从其他一些流畅的帖子中获得了IE的答案:-ms-text-justify: distribute-all-lines。在IE8-10中测试过。

/* The Omega Maneuver */
[class*=cols] { text-align: justify; padding-left: 10px; font-size: 0;
             -ms-text-justify: distribute-all-lines; } 

 [class*=cols]>* { display: inline-block; text-align: left; font-size: 13px;
                word-spacing: normal; vertical-align: top;
                -webkit-box-sizing: border-box;
                   -moz-box-sizing: border-box;
                        box-sizing: border-box; }

.cols2 { word-spacing: 20px; padding-right: 20px; }
.cols3 { word-spacing: 30px; padding-right: 30px; }
.cols4 { word-spacing: 40px; padding-right: 40px; }
.cols5 { word-spacing: 50px; padding-right: 50px; }
.cols6 { word-spacing: 60px; padding-right: 60px; }

  .cols2 > * { margin-right: -10px; }
  .cols3 > * { margin-right: -20px; }
  .cols4 > * { margin-right: -30px; }
  .cols5 > * { margin-right: -40px; }
  .cols6 > * { margin-right: -50px; }

一些助手:

.⅛, .⅛s >* { width: 12.50%; }
.⅙, .⅙s >* { width: 16.66%; }
.⅕, .⅕s >* { width: 20.00%; }
.¼, .¼s >* { width: 25.00%; }
.⅓, .⅓s >* { width: 33.00%; }
.⅜, .⅜s >* { width: 37.50%; }
.⅖, .⅖s >* { width: 40.00%; }
.½, .½s >* { width: 50.00%; }
.⅗, .⅗s >* { width: 60.00%; }
.⅝, .⅝s >* { width: 62.50%; }
.⅔, .⅔s >* { width: 66.00%; }
.¾, .¾s >* { width: 75.00%; }
.⅘, .⅘s >* { width: 80.00%; }
.⅚, .⅚s >* { width: 83.33%; }
.⅞, .⅞s >* { width: 87.50%; }
.blarg-five-twelfs { width: 41.66%; }

你可以在这里荣耀之中见证我的巨着:http://jsfiddle.net/xg7nB/15/

<div class="cols4">
    <div class="⅙">This is my magnum opus</div>
    <div class="¼">I finally beat css</div>
    <div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

绝对最小的实现,以4个相等宽度(25%)宽度cols和10px排水沟为例:

.fourEqualCols { word-spacing: 40px; padding: 0 40px 0 10px;
                 text-align: justify; font-size: 0;
                 -ms-text-justify: distribute-all-lines; }

.fourEqualCols>* { margin-right: -30px; width: 25%;
                   display: inline-block; word-spacing: normal;
                   text-align: left; font-size: 13px; }


<div class="fourEqualCols ">
  <div>GLORIOUSLY CLEAN MARKUP</div>
  <div>I hate extra markup and excessive class props</div>
  <div>Naked code</div>
  <div>get intimate</div>
</div>

Soooo这段代码基本上取代了几乎任何现有的网格框架吗?如果你可以任意设置排水沟,然后只是制作100%宽度的列,那实际上不是大多数/所有网格框架都不是吗?如果你不像我们很多人那样为IE7开发那么结合盒子大小调整:border-box渲染填充和边框也没有问题。

编辑:哦,你想要与容器的两侧齐平。没问题,我不得不专门添加侧排水沟,所以我们可以将一些值改为10并摆脱填充和瞧。 http://jsfiddle.net/bTty3/

[class^=cols] { text-align: justify; font-size: 0;
             -ms-text-justify: distribute-all-lines; } 

 [class^=cols] >* { display: inline-block; text-align: left; font-size: 13px;
                word-spacing: normal; vertical-align: top;
                -webkit-box-sizing: border-box;
                   -moz-box-sizing: border-box;
                        box-sizing: border-box; }

.cols2 { word-spacing: 20px; padding-right: 10px; }
.cols3 { word-spacing: 30px; padding-right: 20px; }
.cols4 { word-spacing: 40px; padding-right: 30px; }
.cols5 { word-spacing: 50px; padding-right: 40px; }
.cols6 { word-spacing: 60px; padding-right: 50px; }
 .cols2 >* { margin-right: 0 }
 .cols2 >* { margin-right: -10px; }
 .cols3 >* { margin-right: -20px; }
 .cols4 >* { margin-right: -30px; }
 .cols5 >* { margin-right: -40px; }
 .cols6 >* { margin-right: -50px; }

相同的HTML

<div class="cols4">
    <div class="⅙">This is my magnum opus</div>
    <div class="¼">I finally beat css</div>
    <div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

I beat CSS here's your proof

答案 1 :(得分:8)

尝试这种纯CSS2解决方案: demo fiddle

基本CSS fiddle没有化妆品)

html, body {
    padding: 0;
    margin: 0;
}
#wrap {
    padding-right: 30px;
    overflow: hidden;
}
.col {
    float: left;
    margin-left: 40px;
    margin-right: -30px;
}
.col:first-child {
    margin-left: 0;
}
.small {
    width: 16.66%;
}
.medium {
    width: 25%;
}
.large {
    width: 41.66%;
}

<强> HTML:

<div id="wrap">
    <div class="col small"></div>
    <div class="col medium"></div>
    <div class="col small"></div>
    <div class="col large"></div>
</div>

在IE7,IE8,IE9,Opera 11.50,Safari 5.0.5,FF 6.0,Chrome 13.0的Win7上测试。


更新

现在,如果您希望使用任意数量的列,则必须在容器中添加一个额外的类,指定列数:

<div class="cols-12 count-04">
    <div class="col width-02"></div>
    <div class="col width-03"></div>
    <div class="col width-02"></div>
    <div class="col width-05"></div>
</div>

请参阅this updated fiddle,了解各种列数。

可能的错误:

理论上,imho此解决方案应适用于任何浏览器窗口宽度中每个可能的最小列宽的任意数量的列。但似乎所有浏览器都无法处理:1。大量1列宽列,或2.浏览器窗口宽度小。

请注意,所有浏览器的最小宽度为1440像素,等于12倍120像素(所有10px边距占用的空间),处理解决方案就好了。当您使用2个或更多列宽列时,对最小浏览器宽度的要求确实下降到720像素(6 * 120px)。最后一种情况听起来更加真实,但仍然无法解释这种浏览器行为。

我尝试通过引入this fiddle所示的其他最后一列类来修复此问题,但它并没有解决小浏览器宽度的问题。尽管如此,由于宽度百分比的破坏,它可以解决一个微小的舍入误差,但我认为这个问题可以忽略不计。

我想听听其他css专家的意见,所以我加了赏金。

答案 2 :(得分:7)

为什么不使用

.column > .panel {
    padding: 10px 0 10px 10px;
}

.column:first-child > .panel {
    padding-left: 0px;
}

它只在盒子之间制作10px空格而不使用last-child。

答案 3 :(得分:2)

在这个帖子中查看thirtydot的答案,获得纯CSS / HTML(没有JavaScript的等间距“列”的流体布局)......

Fluid width with equally spaced DIVs

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

JSFiddle的修改表明,“列”可以制成不同的固定宽度,并且仍然具有相同且流畅的边距。

http://jsfiddle.net/EDp8R/43/

最后,另一个使用百分比的例子,同时仍保持相等和流动的利润。

http://jsfiddle.net/EDp8R/45/

我意识到这可能不是一个确切的解决方案,但我认为它让你非常接近。

答案 4 :(得分:2)

参考原始问题“有没有办法,使用纯CSS,实现具有固定宽度边距的流体宽度圆柱布局?”

值得注意的是,在这些问题中,CSS变得非常困难。在过去的一周里,我一直在制作一个“基本模板”来创建我自己的“圣杯”,包括边框,边距和填充......似乎CSS无法解决这些问题。虽然这个问题很容易,但在CSS中实现(几乎?)是不可能实现的,尤其是跨浏览器。

有趣的是,通过使用表格可以轻松解决这些问题。我不明白为什么我们被网络社会强迫使用div而不是像“语义”和“简单概述”这样模糊的论据,因为大多数论据都很弱甚至是错误的。人们说桌子给了更多的麻烦,显然不了解CSS中的真正困难。

无论如何,如果你想拥有一个表结构(就像colums是表的一部分),我建议使用'display:table'。

要使用纯CSS在原始问题下方获得图像,可以使用以下内容:

<强> CSS

html,body{
    margin: 0px; 
    padding: 0px; 
    height: 100%; 
    width: 100%;
    overflow: auto;
}
.table{
    background: pink;
    display: table;
    width: 100%;
    height: 100%;
}
.tableRow{
    display: table-row;         
}
.tableCell{
    display: table-cell;
    vertical-align: top;
    height: 100%;  
}
/*
    Ensures the full size of the table-cell has the behaviour of a block-element. 
    This is needed, because 'table-cell' will behave differently in different browsers.
*/
.tableCell>div{
    height: 100%;
}
/*
    Padding has to be used instead of margin in 'border-box' modus.
*/
.tableCell>div>div{
    height: 100%;
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}
/*
    The final content.
*/
.tableCell>div>div>div{
    background: lightblue;
    padding: 5px;
    height: 100%;
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}


#col1{
    width: 16.66%;          
}
#col1>div>div{
    padding-right: 10px;
}
#col2{
    width: 25%;         
}
#col2>div>div{
    padding-right: 10px;
}
#col3{      
    width: 16.66%;
}
#col3>div>div{
    padding-right: 10px;
}
#col4{
    width: 41.66%;
}

<强> HTML

<div class="table">
    <div class="tableRow">
        <div id='col1' class="tableCell">   
            <div><div><div>16.66%</div></div></div>
        </div>
        <div id='col2' class="tableCell">
            <div><div><div>25%</div></div></div>
        </div>
        <div id='col3' class="tableCell">
            <div><div><div>16.66%</div></div></div>
        </div>
        <div id='col4' class="tableCell">
            <div><div><div>41.66%</div></div></div>
        </div>  
    </div>
</div>

我认为使用额外的div仅仅是一个余地是非常过分,但不幸的是CSS没有'margin-box'模型,这实际上可以解决十亿个问题。

这些嵌套代码可能会让你想到“为什么不使用其他技术?”因为这可能会导致更少的代码。对于一个非常具体的愿望,情况就是如此。然而,其他技术通常涉及浮动或绝对定位。这些技术无法达到同样的效果:例如浮动可以实现长度相等的列,但是当你想要边框或边距时,你会发现自己陷入困境。对于绝对定位,它更像是相反的:你可以解决边缘问题,但高度只能基于一列。

在我看来,CSS未能满足要求。虽然替换positiong的表是有意义的,但在这些年之后仍然无法获得相同的结果。为了实现“圣杯的圣杯”,桌面结构不仅是最简单的方法,还有唯一的方法......至少,在我尝试了数百种可能性之后,我知道。

剩下的问题是:如果你将div用作表格,为什么要使用div?我对自己并不完全了解,但人们似乎也有其理由。

答案 5 :(得分:1)

我使用OOCSS的网格

https://github.com/stubbornella/oocss

我最近在我自己的网站上进行了在线演示,因为网上没有适当的例子:(

http://www.leipeshit.com/awesome_stuff/oocss/core/grid/grids_all.html

答案 6 :(得分:1)

获得相同效果的更简单方法是让列中的内容创建排水沟,而不是将边距/填充应用于列本身。这可以通过固定,流体,弹性等网格来完成。

例如:

/* Gutters */
h1, h2, h3, h4, h5, h6,
p, ul, ol, blockquote,
hr, address, pre, object, fieldset
{
    margin-right: .75rem;
    margin-left: .75rem;
    padding-right: .75rem;
    padding-left: .75rem;
}

这也简化了您的列的大小调整,嵌套以及将背景应用于乐高积木。

答案 7 :(得分:0)

为什么不像第一个例子中那样使用填充,然后在所有元素上设置box-sizing:border-box?

答案 8 :(得分:0)

我最近为此开发了一种替代解决方案,它允许一行中的灵活列的任意组合,在所有列中具有固定且一致的余量,而不管父元素的宽度。

这不使用任何JavaScript并且可以在IE8 +中使用。

在此解决方案中,边距是在两个类别上定义的 - 因此很容易为响应式设计更改它。列宽也代表它们使用的空间,例如2列行的宽度为50%,4列行的宽度为25%。

您可以在http://www.andrewjamestait.co.uk/conflexgrids/

查看示例

或者可以在https://github.com/andrewjtait/conflexgrids

的GitHub上找到它

答案 9 :(得分:0)

如果您可以使用每列另一个嵌套div,则可以为每个列定义所需的边距。要消除左外边缘和右外边缘上的边距,可以在外部容器上定义负边距。

例如:使用pureCSS pure-g是外部容器,pure-u- *是包含嵌套div的列节点(display:inline-block)。 spacing是pureCSS网格系统的自定义扩展名的名称,以允许列边距。

.pure-g.spacing {
    margin: 0 -10px;
}

.pure-g.spacing [class *= "pure-u"] > div {
    margin: 10px;
}

应该适用于大多数浏览器。告诉我它是不是 - 我已经在使用它了。

的问候, 最大