CSS float与布局详解

学习CSS大家可能和我一样,都是自学,然后碰到问题,就度娘、谷哥找解决方案,最后虽然都能解决问题,但是久了之后总觉得哪里不对劲,总觉得少了什么。后来我看到W3C对各个属性的详细解释才发现少了什么:基本概念。就像看到有篇文章讲的一个经历:作者说自己面试了一个从事5年js工作的人,然后招至麾下,虽然她自认为javascript技能非常好,但是不久发现她这个手下其实对javascript知之甚少,虽然都能完成任务。

CSS跟javascript也一样,虽然CSS是很好学,但是跟学其他东西一样,先理论再实际操作比直接一头扎进实际工作中再理论,后者肯定比前者伤的脑细胞比白的头发要多的多。

今天我们就将CSS最重要的属性:布局。除去上篇文章讲的绝对定位常规流,今天我们详细讲浮动( Floats ),浮动是个非常强大的属性,我们对它肯定印象非常深刻,因为布局时用到最多的几十它,但是因为IE渲染CSS引擎(Trident)跟其他浏览器不同,更因为年老的IE6我们对于浮动的印象也更加深刻了。

接下来我们就来浮动( Floats )和CSS2.1的块格式化上下文( Block formatting context )和IE6、7以及所有IE版本在混杂版本出现的layout三者的关系。

浮动(Floats)

CSS float与布局详解

浮动 Floats 是 CSS 中的一种布局方式。它的渲染位置在行框与包含块之间,这样就可以使行框内文字与浮动元素不重叠并且环绕它显示。在布局过程中也经常会使用它来达到左右并排布局的效果。

浮动的引用

  • 浮动和文字环绕

    浮动框就是一个框在当前行被向左或向右挪动(偏移),它不在常规流中,浮动框由浮动元素的框组成。 浮动框( ‘float’, ‘floated’ or ‘floating’ box )最有趣的特性是内容(Line Box)可以沿着它的边缘渲染(设置 ‘clear’ 属性禁止此特性 )。 内容排列在沿着左浮动框的右边排列,而沿着右浮动框的左边排列,也就是我们常说的文字环绕效果。

  • 浮动框的位置

    一个浮动框,会被向左或向右偏移,直到它的外边界1接触到它包含块2的边界或另一个浮动元素的外边界1, 如果存在一个行框,浮动框的顶边会和当前行框的顶部对齐。

    如果水平方向没有足够的空间放置浮动元素,它将向下移动,直到有足够的空间或没有更多的浮动元素为止。

  • 浮动元素会缩短行框

    由于浮动框并不在常规流中,在该浮动框之前或之后创建的非定位框垂直排列,就好象浮动框并不存在一样。 然而,浮动框之后创建的行框会被缩短,为浮动框提供空间。如果被缩短的行框无法再容纳更多的内容, 它将向下移动,直到有足够的空间或没有更多的浮动元素为止。当前行里浮动框前的任何内容,都将被重新排列到该浮动另一侧的第一个可用行里。 也就是说,如果在遇到左浮动框之前,行内框被放置到行上,剩余的行框空间足够容纳该左浮动框,那么,左浮动框就会被放置在该行上, 并与该行框的顶端对齐,然后,已经在行上的行内框被相应地移动到该浮动框的右侧(右侧成了该左浮动框的另一侧),反之亦然,对于 rtl 和右浮动框也是一样。

    如上文字环绕浮动元素的例子,包含文字的行框被缩短,是包含块减去浮动元素的外边距 margin 的宽度。其中,”The content” 两字,分别被放到了两行, 因为,一行中的剩余空间无法再容纳 “content”。

  • 浮动元素与相邻的 Block Formatting Context 之间的关系我们接下来详细讲解。

各浏览器中浮动元素与相邻的 Block Formatting Context 之间的关系有差异

表格的 border-box、块级的替换元素、或是在普通流中创建了新的 block formatting context(如元素的 ‘overflow’ 特性不为 ‘visible’ 时)的元素不可以与位于相同的 block formatting context 中的浮动元素相重叠。如果有必要,布局实现中应清除上述元素而将其放置在之前的所有浮动元素之下的一行,但也可能在有足够剩余空间的情况下与浮动元素相邻。它们甚至可能会使上述元素的 border-box 比根据普通流中的非替换块级元素宽度算法计算而来的更窄。CSS2 并没有定义用户端何时将上述元素紧邻浮动元素放置或是变窄。

关于 block formatting context和block formatting context的创建条件请点击

由于 IE6 IE7 以及IE所有混杂模式中没有 block formatting context 的概念,取而代之的是 hasLayout 特性。关于 hasLayout 请点击。如果不了解这些概念,点击链接去看看,再回来看这里

设置的宽度不当导致兼容性问题

若容器的宽度、浮动元素的宽度、BFC 的宽度的值设置不当,导致 BFC 的宽度大于 “容器的剩余空间宽度” 时,在各浏览器之间可能会触发兼容性问题,最终造成布局上的极大的差异,如内容丢失、错位等。

  • 当容器有足够的剩余空间容纳 BFC 的宽度时,所有浏览器都会将 BFC 放置在浮动元素所在行的剩余空间内。
  • 在 IE6 IE7 IE8 Chrome Opera 中,当 BFC 的宽度介于 “容器剩余宽度” 与 “容器宽度” 之间时,BFC 会显示在浮动元素的下一行;在 Safari 中,BFC 则仍然保持显示在浮动元素所在行,并且 BFC 溢出容器;在 Firefox 中,当容器本身也创建了 BFC 或者容器的 ‘padding-top’、’border-top-width’ 这些特性不都为 0 时表现与 IE8(S)、Chrome 类似,否则表现与 Safari 类似。
  • 在 IE6 IE7 IE8 Opera 中,当 BFC 的宽度大于 “容器宽度” 时,BFC 会显示在浮动元素的下一行;在 Chrome Safari 中,BFC 则仍然保持显示在浮动元素所在行,并且 BFC 溢出容器;在 Firefox 中,当容器本身也创建了 BFC 或者容器的 ‘padding- top’、’border-top-width’ 这些特性不都为 0 时表现与 IE8(S) 类似,否则表现与 Chrome 类似。

由于可以创建 BFC 的条件很多,这里以最常见的利用 ‘overflow:hidden’ 创建 BFC 为例,在 IE6 IE7 IE8(Q) 中则靠为元素设置宽度触发其 hasLayout 特性。

因为兼容性的问题,所以BFC的宽度尽量要小心设置,而且触发 layout 和建立 Block Formatting Context 的属性有重叠,所以接下来我们来介绍他们俩的差异性。

layout 和 Block Formatting Context的差异性

Block Formatting Context (块格式化上下文)是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。而“Layout”是一个 IE 的私有概念,IE 中使用布局概念来控制元素的尺寸和定位,跟Block Formatting Context 有点类似,而且

区别

  1. 在 IE8(S) 之前的版本中,没有规范中提及的 block formatting context 和 Inline formatting context 概念,而是用 hasLayout 来达到相似的目的。
  2. 在 IE 中可通过设置 ‘width’、’height’、’min-width’、’min-height’、’max-width’、’max-height’、’zoom’、’writing-mode’ 来触发 hasLayout,而这些特性值的设置不能够使元素创建 block formatting context。
  3. 在 IE 中很多元素默认就是拥有布局的,如 IPUNT, BUTTON, SELECT, TEXTAREA 等,但是这些元素在标准中会形成 Inline formatting context 。

共同点

  1. 两者都是决定了对内容如何定位及大小计算的规则。
  2. ‘table-cell’ 和 ‘table-caption’ 既是 hasLayout 的元素,又是可以创建 block formatting context 的元素。
  3. 浮动元素,绝对定位元素,inline-block 元素以及除 ‘visible’ 外任意值的 overflow(IE7) 在 IE 中可以触发 hasLayout,同时在标准中,又可以创建 block formatting context。

可能产生的兼容性问题

由于 hasLayout 和 block formatting context 是对一类事物的不同理解,并且他们的启用条件不尽相同,因此如果一个元素设计时,在 IE 早期版本中触发了 hasLayout ,但在其他浏览器中又没有创建 block formatting context,或者相反,一个元素在 IE 早期版本中没有触发 hasLayout ,在其他浏览器中却创建了 block formatting context(如设置了 ‘overflow:hidden’ ),将导致页面布局的重大差异。

解决方案

仅当一个元素即在 IE 早期版本中触发了 hasLayout,又在其他浏览器中创建了 block formatting context 时,才能避免上述问题的发生。即同时启用上述两者以保证各浏览器的兼容,或者相反,两者皆不启用。

  • 使元素即生成了 block formatting context,又触发了 hasLayout
    • 对于触发 hasLayout 的元素,通过 CSS 设置,使它产生 block formatting context;
    • 生成 block formatting context 但是没有触发 hasLayout 的元素,通过设置 ‘zoom:1’,使其触发 hasLayout。
  • 使元素即没有触发 hasLayout,又没有创建 block formatting context。

block formatting context和layout的实际应用

左右浮动两列布局

实例代码

<div style="width:400px;overflow:hidden;background-color:#0000ff;">
    <div style="background:gray;float:left;_margin:0 -3px 0 0;">left text</div>
    <div style="background:green;overflow:hidden;_zoom:1;">right text</div>
</div>

DEMO

simple text
in f123123123low
324324w
左右两列布局实例以及代码

代码讲解

  • 最外层div的overflow:hidden;创建了 block formatting context,在 IE6 中未触发 hasLayout,但在 IE7(S) 中触发了 hasLayout;所以height=auto

    只要 最外层div 创建了 block formatting context,其浮动子元素就会参与其高度计算(IE7 是由于 hasLayout 导致与其他浏览器的效果相同),而zoon:1则是针对IE6触发hasLayout

  • 第一个子集div是一个浮动元素,而_margin:0 -3px 0 0;是专门针对IE6 3pxbug的
  • 第二个子集div的 overflow:hidden; 在 IE6 中未触发 hasLayout,但在 IE6 中触发了 hasLayout。

    根据 CSS 2.1 9.5 Floats 中的描述,创建了 Block Formatting Context 的元素不能与浮动元素重叠,所以不第二个子集永远不回和第一个子集重合。

实例代码

<div style="width:300px; border:1px solid gold;">
    <div style="overflow:hidden;_zoom:1;background:darkgray;">
        <div style="margin:30px 0;width:60px;">content</div>
    </div>
</div>

DEMO

content
建立block formatting context和触发layout不会和在流中的子元素发生空白边折叠

本文源链接:http://www.html5jscss.com/css-float-layout.html

转载请注明《CSS float与布局详解》| html5jscss

评论关闭了.