创建水平排列的一行等距对象是网页设计中另一项比它应该更困难的事情。这可能是一项非常有用的功能,尤其是在流体宽度布局中,您试图充分利用可用的水平空间时。
以下是我们试图实现的目标
- 最左侧的对象与其父元素左对齐。
- 最右侧的对象与其父元素右对齐。
- 每个对象始终彼此等距。
- 当浏览器窗口变窄时,对象将停止重叠。
- 当浏览器窗口变窄时,对象不会换行。
- 该技术可在流体宽度环境中工作。甚至在一个居中的环境中。
我尝试了许多不同的技术来实现这一点。让我们回顾一下我所有的失败尝试,然后转向最终似乎效果很好的技术。
失败:为每个对象设置百分比左定位
首先,我为每个图像赋予了一个唯一的类
<img src="images/shape-red.png" class="first-r">
<img src="images/shape-green.png" class="second-r">
<img src="images/shape-yellow.png" class="third-r">
<img src="images/shape-blue.png" class="fourth-r">
然后,我为每个类设置了基于百分比的左定位
img.first-r { left: 0%; position: relative; }
img.second-r { left: 25%; position: relative; }
img.third-r { left: 50%; position: relative; }
img.third-r { left: 75%; position: relative; }
请注意相对定位。这是为了让最左侧的图像尊重父元素而必需的,假设内容居中而不是左对齐。问题在于应用于最右侧对象的左外边距是浏览器窗口宽度的 75%,但它是从父元素的左侧开始应用,而不是从浏览器窗口的左侧开始。这可能导致最右侧的元素超出屏幕(不尊重父元素的右边缘)。此外,不可思议的是,如果您将浏览器窗口缩小到足够窄,这些元素最终将换行。
如果您在此处切换到绝对定位,则可以解决上述部分问题,但随后您的对象将左对齐,并完全忽略父元素的左位置。此外,在浏览器窗口尺寸足够窄的情况下,图像将重叠。但是,至少对象是等距的!
失败:为对象设置公共百分比左外边距
我的下一次尝试是为每个元素(第一个元素除外)设置一个公共百分比左外边距。
<span class="do-not-wrap">
<img src="images/shape-red.png">
<img src="images/shape-green.png" class="mover">
<img src="images/shape-yellow.png" class="mover">
<img src="images/shape-blue.png" class="mover">
</span>
应用外边距
img.mover {
margin-left: 15%;
}
您应该能够从查看该百分比看出此技术注定会失败。我只是选择了一个看起来效果最佳的百分比。我无法想到任何在这里可行的数学方法。因为父元素是浏览器窗口宽度的百分比,而外边距是浏览器窗口的百分比,而不是父元素的百分比,所以增长率将非常难以匹配。还要注意“不换行”跨度,这是为了防止……等等……换行而必需的。但是,至少对象是等距的!
失败:直接使用表格!
即使“放弃”CSS 似乎也无法解决此问题。我认为这肯定可以奏效,因为表格具有有时有用、有时令人恼火的自动均匀间隔单元格的能力。
<table>
<tr>
<td class="leftalign">
<img src="images/shape-red.png">
</td>
<td>
<img src="images/shape-green.png">
</td>
<td>
<img src="images/shape-yellow.png">
</td>
<td class="rightalign">
<img src="images/shape-blue.png">
</td>
</tr>
</table>
请注意第一个和最后一个单元格中的额外对齐类。如果所有单元格都居中,则允许对象等距,但最左侧的对象或最右侧的对象都不会与父元素的边缘对齐。这可以通过对最左侧单元格应用左对齐,对最右侧单元格应用右对齐来解决——但这会导致对象不再等距。回到绘图板。
成功:Flexbox 对齐
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
.container {
display: flex;
justify-content: space-between;
}
查看 Chris Coyier 在 CodePen 上的笔 等距对象(@chriscoyier)。
成功:第一个在左侧,其余的在右侧以相等大小的盒子浮动
幸运的是,表格的想法引发了一些思考。第一个图像需要左对齐,但其余所有图像都可以右对齐。事实上,如果它们是右对齐的,并且还在均匀分割其余空间的盒子内,那可能就可以了。也许用视觉方式解释这一点最好。
HTML
<img src="images/shape-red.png">
<div id="movers-row">
<div><img src="images/shape-green.png"></div>
<div><img src="images/shape-yellow.png"></div>
<div><img src="images/shape-blue.png"></div>
</div>
CSS
#movers-row {
margin: -120px 0 0 120px;
}
#movers-row div {
width: 33.3%;
float: left;
}
#movers-row div img {
float: right;
}
有一个 示例页面,我在那里进行这项工作。它不太漂亮……但您可以在底部看到获胜者。我相信你们中的一些人对此有一些更好的解决方案,所以请告诉我!
成功:使用内联块和两端对齐文本
这可以通过将元素设置为display: inline-block;
并将父元素设置为text-align: justify;
来完成。好吧,它稍微复杂一些,我称之为真正的 CSS 技巧。您添加一个额外的元素(通过伪元素),该元素宽度为 100%,并且之前的内联块将对齐。
<div id="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
#container {
height: 125px;
text-align: justify;
border: 10px solid black;
font-size: 0.1px; /* IE 9/10 don't like font-size: 0; */
min-width: 600px;
}
#container div {
width: 150px;
height: 125px;
display: inline-block;
background: red;
}
#container:after {
content: '';
width: 100%; /* Ensures there are at least 2 lines of text, so justification works */
display: inline-block;
}
演示
Check out this Pen!
非常好,尽管当屏幕缩小到很小的时候,它们会聚在一起,但我认为当他们在浏览并且需要查看类似的东西时,没有人会缩小到那么小。干得好。
我不明白为什么表格不起作用……无论如何,如果您不想使用表格并且不介意额外的 div,这在 Firefox 中有效,可能还有其他浏览器……
CSS
HTML
它只是伪装成表格……=)
有趣 :)
Chris,感谢你提供如此棒的技巧!我一定会牢记这个技巧:D
对于我上面的帖子我表示歉意,因为我没有注意到左边的和右边的 img 必须接触边界的那个部分。感谢你的技巧,继续努力,我喜欢你的视频。
谢谢!这看起来像是完美的解决方案。我一定会在我下一个 CSS 挑战中尝试它。
继续努力,
Michal
谢天谢地!这已经困扰我一段时间了,所以我很高兴有人比我更聪明的人已经解决了它。一定会用上它!
啊哈,甜蜜的浮动属性。浮动属性拯救一切!
哦,这很有帮助!我正坐在那里试图做到这一点,而你写了关于它的文章! :)
好吧,它很凌乱,但我认为没有更好的方法了。感谢你的建议。
看起来示例页面仍然没有满足“停止重叠”标准,至少在我的 FF2 中是这样。如果我缩小窗口,图像开始重叠并相互剪切,从
OOOO
变成类似
OICO
这些元素似乎按照(从左到右位置)1432的顺序堆叠,这很有道理,因为对于右浮动元素,这与它们在标记中出现的顺序相同(我假设——我还没有实际查看标记)。
第一次尝试中元素“莫名其妙地”换行的原因是:position:relative 会相对于盒子原本应该存在的位置进行偏移(而不是相对于父元素)。
此外,百分比不一定指的是浏览器窗口——它们指的是最近的、本身具有定位的祖先元素。如果要相对于父元素使用百分比,只需向父元素添加“position: relative”。
正确使用绝对定位和相对定位可以解决所有问题。而且,如果你真的想使用那些讨厌的表格,你可以轻松地添加 display:[inline][block] 等样式。使用样式,每个元素都可以是 span;你只需要删除元素的默认样式。
需要一些技巧才能在 IE6 中工作…
感谢所有指出“通过”解决方案确实仍然会导致重叠的人。我错过了这一点。但我认为它仍然是一个相当有效的解决方案,并且我认为在大多数使用它的情况下,我更喜欢重叠而不是换行。
像横幅这样的整块代码怎么办?我有 4 个生成的广告,我想把它们放在一起(不使用表格)。
有趣的技巧。感谢你的分享。我需要尝试一下,看看它运行得如何。
你获得了我的书签!
我从头尝试了这个,并得出了与你几乎相同的解决方案
HTML
<div id="container">
<div id="butlast">
<div><img src="images/shapes-red.png"></div>
<div><img src="images/shapes-green.png"></div>
<div><img src="images/shapes-yellow.png"></div>
</div>
<img src="images/shapes-blue.png">
</div>
CSS
#container {
min-width: 480px;
}
#butlast div {
float: left;
width: 33%;
}
#butlast {
margin-right: 120px;
}
唯一的真正区别在于,我将除最后一个之外的所有元素组合在一起,而不是除第一个之外的所有元素,并使用左浮动而不是右浮动。只需将整个内容包装在 min-width: 480px 中即可解决重叠问题。
Vineet,干得好。有趣的是,这是一个完全相反的解决方案=)。感谢你关于 min-width 的评论,将其应用于父容器绝对有助于解决支持它的浏览器的重叠问题。
这个也很好用——并且使用了更有语义的标记
只需要一个名为 expando 的包装 div 和一个标准的 UL 放在里面——搞定。
http://www.fu2k.org/alex/css/cssjunk/equidistant
两种方法。
第一种方法借鉴了你的思路,但将第一个红色圆圈放在包装 div 内,并使用绝对定位将其推到左边。
第二种方法简单地使用绝对定位。
主体上的 Min-width(以及 IE6 的表达式)解决了重叠问题。
两个不同的 Alex,还有两个很好的例子。干得好,你们俩!
你必须承认 Alex Morris 的解决方案在 Firefox 和 IE 中都能正常工作。
谢谢 Alex!!!
该死!现在我看到比尔·盖茨和史蒂夫·鲍尔默,尽管他们拥有数十亿美元和数千名开发人员,却无法让 IE7 解析 Alex Morris 优雅解决方案中列表项的顺序。
嘿,你知道什么——忘记那些糟糕的浏览器不理解的 first-child 东西吧。
你可能会认为 4 个设置为 25% 的项目会正确浮动并组成 100%。
有趣的是,好的浏览器可以很好地做到这一点,但 IE 却做不到——所以你只需要为 IE 设置一个单独的样式表,并将百分比设置为略低于 25%——比如 24.9%,它就能完美呈现。简而言之,你需要
CSS 代码很简单
#expando ul {
margin:0;
padding:0;
list-style-type:none;
}
#expando li span {
height:95px;
width:95px;
background:#f39;
}
#expando ul li {
width: 24.9%;
float: right;
background:#000;
margin:0 0 10px 0;
text-align:center;
}
你让我燃起了希望。
不错的解决方案,尽管我希望你能解决一个不同的问题。我一直都在寻找一个与上述相同的解决方案,但适用于跨越多行的元素列表。
如果有人有解决这个问题的好方法,请分享 :)
如果你向容器添加 position: relative,从而建立一个新的定位上下文(即所有具有 position: relative/absolute 的元素现在将相对于父容器而不是浏览器窗口进行放置),则不会出现这种情况。
错误:使用 it’s 代替 its。
这个与 Alex 的有点不同:http://tjkdesign.com/lab/equidistant/
该方法不使用“float”,而是依赖于“position:absolute”来处理除最后一个元素之外的所有元素(这样整行就不会脱离文档流)。
此外,我使用左负边距而不是右负边距(我认为这样更省心)。
感谢 Chris 的想法
Thierry,干得好,感谢分享!
现在真正的挑战将是找到一种方法,在不使用任何唯一 ID 的情况下,对任何大小的对象执行此操作。嗯嗯嗯
不错。我一直都是通过使用与间隙相同的负边距来实现的,例如
<ul>
<li>项目一</li>
<li>项目二</li>
<li>项目三</li>
<li>项目四</li>
<li>项目五</li>
<li>项目六</li>
</ul>
div {
width : 600px; }
ul {
overflow : hidden; /* 扩展 ul 以围绕浮动 li */
margin-left : -40px; }
li {
float : left;
display : block; width : 160px; margin-left : 40px; }
\抱歉,数学计算都错了,这是我自己的文章:http://mattwilcox.net/archive/entry/id/977/
这是示例代码:http://mattwilcox.net/sandbox/edge-to-edge/edge-to-edge-alignment.html
@Chris:谢谢
我认为使用相邻兄弟选择器,我们可以不用 ID,但“任何大小的东西”很棘手 ;-)
@Matt:目标是在流体容器内使此方法起作用。
在你的示例中,删除/更改 #content 的宽度将破坏布局。
@Thierry
为什么不能用百分比替换我在示例中使用的 px?
给你一个流体版本的示例
http://mattwilcox.net/sandbox/edge-to-edge/edge-to-edge-alignment-fluid.html
@Matt:你的第一个示例使用固定宽度的容器和固定宽度的子元素,最新的示例使用流体容器和流体子元素。
据我所知,迄今为止给出的示例都在流体容器内使用固定宽度的元素(四个)。
请注意,四个是挑战的一部分,因为保持三个元素之间的距离要容易得多。
示例:http://tjkdesign.com/lab/equidistant/three_is_easy.asp
@ Thierry
请查看我上面提供的流体变体的链接。
我的技术允许在一行中放置任意数量的项目,你只需更改数学计算即可;无论你在一行中放置三个项目还是五个项目,或者任何数量的项目,技术都保持不变:在包含元素上应用一个与项目之间间隙相同值的负边距。唯一复杂的部分是计算出要在一行中获得所需数量的数学计算。
我的技术满足了帖子正文中列出的所有要点。例如,通过为容器提供最小宽度值,可以进行进一步的改进。
另外,供你参考,此帖正文中给出的示例**并没有**一行四个固定宽度项目。它们一行有四个**弹性**容器,每个容器包含一个固定宽度项目。你只需将图像放入 LI 中,就可以使用我的示例获得完全相同的效果。你甚至可以使用 text-align 在 LI 本身内移动它们。
但是,为了演示它的简单性,这里有一个每行 4 个,且每个“单元格”最小宽度为 120px 的示例。
http://mattwilcox.net/sandbox/edge-to-edge/edge-to-edge-alignment-fluid-4.html
如果你想在 li 中添加图像等内容,那只是标记。这里的“布局”才是诀窍,处理内容是微不足道的。
@Matt
但我们试图对**图像**进行间距,而不是它们的容器。看看 Chris 的图表中“PASS”的位置。看看那些大点。
你为什么不创建另一个示例,其中图像的行为与图表中(带有额外的标记)一样?这样我们就不会拿苹果和橘子比较了。
啊哈,我现在明白了区别(即使第三次重读帖子,也**没有**在任何地方真正说明。我的解决方案确实检查了所有要点,但同时也错过了正在寻找的精确效果,因为示例比所需功能的描述更具体)。
好的,在建立了细微差别之后,我无法看到使用我的方法(或除了已说明的方法之外的任何其他方法)灵活实现此目的的方法。
另一方面,帖子中描述的方法也非常具体且相当有限。它有很多多余的标记,并且不适合多行或动态生成的内容(我主要在电子商务网站的类别页面上使用我的方法,其中网格中的项目数量未知)。你有多常需要在一页上对四个图像进行对齐,并且每个图像都_必须_具有完全相同的(预先确定的)宽度才能使该技术在流体布局中按行排列?
这是一个有效的解决方案,但对于如此具体且需要如此精确的图像,我认为只需将 UL 设置为 position: relative,然后直接绝对定位图像会容易得多(我以前也这样做过)。如果我们已经知道图像必须是精确的宽度,那么它们也可以设置一个最大高度,因此将 UL 设置为 block 并为其提供高度以避免任何“清除”问题。
给自己记个笔记,定位也不像我想象的那么容易。
呵呵,有趣!描述中缺少的“对象必须是固定宽度”的细节确实让生活变得非常棘手。:-)
很好的讨论,伙计们!有趣的是,对象具有静态宽度是导致困难的原因。我认为我们都可以同意,这比它应该的要棘手得多。
这里有一些很棒的想法,但我仍然认为它们(包括我的)都存在一个问题,那就是对所有细节进行硬编码的依赖性太强。对于大多数技术,你需要知道有多少个,有多宽,并且对这两件事进行硬编码。有些技术甚至需要为每个元素分配唯一的 ID。在一个理想的世界里,我们应该能够在不知道任何这些事情的情况下做到这一点。
我甚至可以说这是 CSS 的一个主要缺陷(并且 CSS3 中可能不会修复)。
但是 Chris,你想要的东西可以用 CSS2.1 实现。Display:table 可以完成这项工作。我已经更新了我之前指向的页面。
http://www.fu2k.org/alex/css/cssjunk/equidistant
#wrapper3 span
{
display: table-cell;
}
#wrapper3 span img
{
float: right;
}
#wrapper3 span:first-child
{
width: 1px;
}
无需知道有多少个元素。除了“表格”上的 100% 以使其拉伸以填充可用宽度和最左侧“表格单元格”上的 1px 以确保它折叠为仅在其内部图像的宽度之外,不需要任何高度或宽度。是的,这基本上只是你最初的非失败想法的再次出现。
它适用于所有支持 display:table 的浏览器(包括 IE8b)。
非常棒,Alex!
遗憾的是,IE6 和 IE7 不行。
像许多事情一样,如果我们能够在生产环境中使用我们应该能够使用的_所有_ CSS 片段,生活会容易得多,但由于某些流行浏览器对某些属性的支持不足,我们无法做到这一点。
使这个挑战如此困难的原因是我们混合了单位类型,而 CSS 在这方面很糟糕。我们可以使用像素,也可以使用%,但混合两者在许多情况下是不可能的。如果 CSS 支持表达式,那么这将不会那么困难(width: 90%-120px;)。在查看了 CSS3 规范后,我认为其中没有任何内容可以帮助我们解决这种情况。
@matt wilcox
> 遗憾的是,IE6 和 IE7 不行。
嗯,显而易见。但我的意思是,这是某些当前浏览器实现的缺陷,而不是 CSS 无法做到的事情。
display:table 解决方案在任何支持 display:table 的浏览器中都能正常工作。因此,无需查看 CSS3 并哀叹。(尽管一个合适的官方方法,display: spaced-out 或其他什么,将是更好的)。
同样显而易见的是,目前它不是一个可行的解决方案,除非你使用 Dean Edwards 风格的方法并使用 javascript 将 display:table 转换为实际的表格以处理那些棘手的 IE。
我一直是这样做的
.equidistant > * {
display: inline;
width: 30%;
float: left;
}
.equidistant > *:first-child { float: left; width: auto; }
.equidistant > * > * { float: right; }
使 Alex 的解决方案在 IE lt 8 中起作用
使用 setExpression()
这不是最好的解决方案,因为存在重排,并且表达式有点“邪恶”,但在某些情况下可能有用(如果元素位于屏幕外,则重排不是问题)。
似乎 :first-child 是完成此类操作的最佳方法。它在 FF 和 IE7 中都能完美运行(当我第一次尝试时,IE7 部分让我感到惊讶)。
是的,IE6 存在问题,但什么时候 IE6 没有问题呢?很有可能,你无论如何都在为了其他问题而进行 hack 或使用条件 CSS,因此添加几行代码以使 :first-child 工作应该不是什么大问题。
实际上,使用表格可以轻松地做到这一点。有时 css 会使事情变得更复杂。表格解决方案不如 css 解决方案优雅,但效果一样好。而且,它不会在怪异模式下中断。:-)
你可以使 FarLeftCell、MiddleCells 和 FarRightCell 中的图像具有任何你想要的宽度,只要它们不超过父对象的宽度即可。(如果图像的总宽度等于 500px,但父级只有 400px,则表格将为 500px)
表格的长度不能短于其单元格中图像的总宽度。css 将 MiddleCells 的宽度设置为 1px,但它可以是 0px。表格意识到图像更大,并扩展单元格以适应图像周围。中间单元格确定其他单元格之间相等的空间量。你必须将它们交错放置在其他单元格之间。更改 css 中的宽度以反映你拥有的中间单元格数量。如果你在表格中有 4 个 MiddleCells,则 100% 除以 4 = 25%。如果你有 6 个 MiddleCells,则 100% 除以 6 = 16.66%。
非常重要:确保在每个 SpacerCells 中都放置了一个不间断空格 ( )。除非你这样做,否则空的表格 SpacerCells 将无法正常工作。
HTML
CSS
在尝试用正确的方法解决这个问题一个周末后,我想出了简单的方法。
这不是我最喜欢的方法,但我将一个 DIV 设置为 {text-align: justify},并在我想均匀间隔的图像(在本例中,跨多行平铺,宽度足够大以确保它需要自己的行)的末尾添加了一个间隔图像。
不漂亮,但真的很容易,而且有效。
我一段时间前想出了另一种方法,它允许在没有额外 html 元素的情况下实现相同的功能。
看看
我的博客…它适用于所有常用的浏览器。
我想解决一个类似但不同的问题:均匀分布元素,但在边缘留出一些空间(准确地说,每个边缘物体之间间距的 1/2)。我的解决方案类似于你使用内联块和两端对齐文本的方案,但不得不修改 HTML 代码为:
有没有人知道一种“更简洁”的方法,不需要修改 HTML 代码?
为什么不只是在你的容器上添加一些填充,然后稍微缩小宽度呢?
Dan,我想要一个适用于不同大小窗口的解决方案,而不需要在 JavaScript 中进行计算。
感谢 Chris,这是另一篇关于有趣主题的不错的文章。
实际上,在阅读这篇文章后,我想出了一个解决问题的新思路。
主要思想是,通过数学计算,边距应该混合使用 px 和 %。
所以我们可以使用边距表示 px,使用填充表示 %。
我在这里详细解释了它
http://mohammad-sabbagh.com/responsive-equidistant-menu-css/
如果你有 100 多张固定高度但纵横比宽度可变的图片,该怎么办?你想在每一行中尽可能多地容纳图片,但随着浏览器窗口的扩大或缩小,图片的数量甚至大小也会随之扩展或缩小。例如,谷歌或必应图片搜索。扩展/缩小浏览器可视区域,看看我的意思。我想模仿这种行为来处理一组 N 张图片。
我正在尝试用四张不同宽度的图片(公司徽标)来实现这一点。我希望第一个徽标从左边缘开始,最后一个徽标与右边缘对齐,徽标 2 和 3 在彼此之间留出相等的空间。根据以上内容,我无法确定是否有任何建议的解决方案适用于我的场景?
我使用了它的一个变体来均匀地间隔一些链接,但我能够在不定义任何特定大小的情况下做到这一点。它在你的内容永远不会比它所在的容器更宽的前提下有效,否则它将溢出到另一行。在快速测试中,它似乎也适用于图像。诀窍是在两侧添加空白的 div。
所以 CSS 代码是
而 HTML 代码是
在 IE9+ 中,你可以使用 calc() 和边距来做一些更简单的事情。我认为它更简洁,并且可以使用几个参数将其转换为 Sass mixin。
Codepen:http://codepen.io/robwierzbowski/pen/fromp
简而言之,如果笔被移动了
…咳咳,