48

更新与总结

既然附加了赏金,我觉得有义务让这个问题更清楚。

另外,我很确定当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-child10 像素(或任何边距大小)。

这可能看起来无害,甚至不引人注意;然而,在某些情况下,元素之间的精确尽可能精确)宽度分布要么是必要的,要么会使事情变得更容易。

因此,无论是使用填充、边距还是它们的某种组合;有没有针对流体列、固定边距、均匀分布的排水沟空间的解决方案,不会从相邻列中抢走“边际”(***哈哈*)内容区域?**


原始问题

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

有没有办法使用纯 CSS 来实现具有固定宽度边距的流体宽度列布局?

重要说明:此图只是一个示例,而不是我希望实现的特定布局。给定的解决方案应允许相邻列的任意组合,总宽度分布总计为 12 或更少。考虑流行的960 网格以供参考。)

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

到目前为止,我使用了一个使用百分比的网格,几乎可以做到这一点。问题是,为了实现边距,每一列都需要一个额外的孩子(我称之为他们.panel):

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

这又差不多,很好;这种方法的问题是第一列和最后一列具有外部“边距”(10px),并且每列之间的“边距”加倍(2 x 10px

当然,通过包含新的 CSS3calc()值类型,可以更轻松地解决这个问题。方向:

.width-12 > .panel{ width: 100%; }
.width-09 > .panel{
    width: calc(75% - 10px);
    margin: ...;
}

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

不幸的是,以下解决方案以及@avall 提供的解决方案(尽管在简化方面肯定是一个不错的选择)并不是我想要的。主要问题是,边距在列之间分布不均。

我能看到这个工作的唯一方法是将.panel填充减少到5px和类似的东西:

.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;
}

这种解决方案是不可接受的,只是因为 IE8 无法识别:last-child并且就此而言:only-child)伪选择器。

4

10 回答 10

64

我终于想通了。在过去十年间断断续续地浪费了数百个小时之后(尽管我依赖的是一些一年前无论如何都不会工作的 CSS)。我没有任何问题就解决了。在 IE8+ 中。

请准备好 2001: A Space Odyssey 音乐,因为我要登陆这艘船。

这种方法的天才和技巧是使用内联块元素,然后使用字间距来平衡使用负右边距。一个负的右边距本身会将元素拉在一起,允许您设置 100% 的宽度并且仍然可以在两者之间放置东西,但让元素重叠。在父级上设置负边距只会撤消子级边距对与总宽度交互的影响(我们试图击中的神奇“100% 宽度”标记“)。填充仅用于增加元素的大小on 并且对于反作用边距是无用的。它通常与 box-sizing 一起使用,在陪审团操纵解决此问题的方法中,以失去使用填充(和边距)的能力为代价,并且可能需要更多包装元素。

word-spacing 提供了神奇的“第三种方式”来添加或删除两个元素之间的水平距离,前提是它们是 inline-block,因为在这种情况下它们将被视为一个“单词”,并且它们之间的任何空格都将折叠到一个单一的可控“字间距”属性。除了这个技巧之外,我不知道获得这个 100% 结果的另一种方法。

我谦虚地提出了固定排水沟弹性列问题的最终答案。我在此将我的解决方案命名为“欧米茄机动”。它具有处理任意混合宽度列的能力(添加多达 100% 的总宽度以进行四舍五入)、任何装订线大小、任何预定义的宽度列数、使用自动换行处理任意数量的行,以及使用 inline-block 元素,因此提供了 inline-block 附带的垂直对齐选项,并且它不需要任何额外的标记,只需要容器上的单个类声明(不计算定义列宽)。我认为代码不言自明。这是 2-6 列的代码实现,使用 10px 排水沟和用于百分比的奖励辅助类。

编辑:有趣的难题。我设法得到了两个略有不同的版本;一个用于 Mozilla 和 ie8+,另一个用于 webkit。似乎 word-spacing 技巧在 webkit 中不起作用,我不知道为什么其他版本在 webkit 中起作用,但在 ie8+/mozilla 中不起作用。将两者结合起来可以覆盖所有内容,我敢打赌,有一种方法可以统一这种策略或非常相似的方法来解决这个问题。

EDIT2:大部分都明白了!Magicaltext-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="⅙">⚉ ☺ ☻ ♾ ☢&lt;/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 开发,那么结合 box-sizing: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="⅙">⚉ ☺ ☻ ♾ ☢&lt;/div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

我打败了 CSS,这是你的证明

于 2011-08-31T11:29:43.160 回答
8

试试这个纯 CSS2 解决方案:demo fiddle

基本 CSS (没有化妆品的小提琴) :

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>

看到这个更新的小提琴展示了许多不同的列数。

可能的错误:

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

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

我尝试通过引入一个额外的最后一列类来解决这个问题,正如这个小提琴所示,但它不能解决小浏览器宽度的问题。由于宽度百分比损坏,它确实解决了一个微小的舍入误差,但我想这个问题可以忽略。

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

于 2011-08-26T05:26:13.360 回答
7

你为什么不使用

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

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

它只会在盒子之间产生 10px 的空间,并且不使用最后一个孩子。

于 2011-08-25T13:46:50.890 回答
2

查看此线程中的 tyyddot 的答案以获得纯 CSS/HTML(具有等间距“列”的流体布局,不使用 JavaScript)...

等距 DIV 的流体宽度

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

JSFiddle 的修改表明“列”可以设置为不同的固定宽度,并且仍然具有相等且流动的边距。

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

最后是另一个使用百分比的示例,同时仍然保持相等和流动的边际。

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

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

于 2011-08-31T15:43:12.767 回答
2

参考原始问题“有什么方法可以使用纯 CSS 来实现具有固定宽度边距的流体宽度列式布局?”

值得注意的是,这些问题让 CSS 变得异常困难。过去一周我一直在研究一个“基本模板”来创建我自己的“圣杯”,包括边框、边距和填充……似乎 CSS 无法解决这类问题。尽管头脑中的问题很简单,但它变得(几乎?)不可能在 CSS 中实现,尤其是跨浏览器。

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

无论如何,如果你想要一个表格结构(因为列是表格的一部分),我建议使用'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 没有“边距框”模型,它实际上可以解决十亿个问题。

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

在我看来,CSS 未能满足要求。虽然要更换表来代替 positiong,但经过这么多年,仍然不可能得到相同的结果。实现“圣杯中的圣杯”表格结构不仅是最简单的方法,也是唯一的方法……至少,据我所知,在尝试了数百种可能性之后。

剩下的问题是:如果您将 div 用作表格,为什么还要使用它们?这一点我自己并不完全理解,但人们似乎有他们的理由。

于 2012-05-03T13:55:51.210 回答
1

我为此使用了 OOCSS 的网格

https://github.com/stubbornella/oocss

我最近在我自己的网站上放了一个演示,因为网上没有合适的例子:(

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

于 2011-09-01T04:14:31.760 回答
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;
}

这也简化了列大小、嵌套和将背景应用于乐高积木。

于 2012-02-01T21:53:58.940 回答
0

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

于 2013-03-11T09:12:27.850 回答
0

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

这不使用任何 JavaScript 并且适用于 IE8+。

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

您可以在http://www.andrewjamestait.co.uk/conflexgrids/看到一个示例

或者它可以在 GitHub 上的https://github.com/andrewjtait/conflexgrids

于 2015-01-06T11:18:43.527 回答
0

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

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

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

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

应该适用于大多数浏览器。如果没有,请告诉我——我已经在使用它了。

问候,马克斯

于 2015-01-15T15:14:02.233 回答