CSS学习-布局

浅谈

对于 CSS 的理解是时而简单既是清晰时而复杂既是迷茫,所以在此写下清晰时刻的理解。但理解不会是一成不变的,不同层次时的理解不一样,特此写下供日后所思。

初识 CSS,开始学习 CSS 时貌似只是在记他的样式规则,随着不断学习也都知道了CSS 样式会改变哪些,如 width 控制宽度,float 设置了会使元素向左或向右浮动,等的,但发现就算知道了所有样式的规则也还是做不了网页,一想该如何去做就会心虚吧,无从下手的感觉。

再识 CSS,意识到这问题后,我便开始四处学习如何布局,DIV+CSS 便是搜索后的结果,于是又去学习,之后不得不说在又学习一段时间后还是提升不大,也试着模仿静态页面,仅看效果来看也有8分相似,但其实写的代码很糟糕,有些地方都不知为何这样做会效果不一样,如浮动造成的父元素高度塌陷,我只知道给父元素设置 overflow:hidden 后高度正常,却不知其原理,但水平如此,也没办法,只是心虚。

正视CSS,算是搁置一段时间又开始学习CSS,这次直接开始做一次完整的网页布局,从慕课网看完后便着手去做,结果还不错,做到了近似一样的网页,这次意识到了不同样式间的制约和配合,仅知道每个样式的规则远远不够,你得非常熟悉他们,并知道设置不同样式会达到什么效果或是产生什么问题,也就是他们之间的关系即规则。算是知道了一点原理,心略有所虚。


正文

CSS 布局,首先要知道元素的属性 display , CSS 中最重要的用于控制布局的属性。每个元素都有一个默认的 display 值,这与元素的类型有关。对于大多数元素它们的默认值通常是 block 或 inline 。

  • block 元素为块级元素。
  • inline 元素为行内元素。
  • 另一个常用的display值是 none 。一些特殊元素的默认 display 值是它。
    • display:none 通常被 JavaScript 用来在不删除元素的情况下隐藏或显示元素。它和 visibility 属性不一样。把 display 设置成 none 不会保留元素本该显示的空间,但是 visibility: hidden; 还会保留,这一点请留意。

知道 display 属性后,还需知道定位机制方可布局。

CSS 有三种基本的定位机制:

普通流、浮动和绝对定位。

  1. 普通流:除非专门指定,否则所有元素都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。
  2. 浮动:浮动的元素可以向左或向右移动,直到它的外边缘碰到包含元素或另一个浮动元素的边框为止。
    由于浮动元素不在文档的普通流中,所以文档的普通流中的块元素表现得就像浮动元素不存在一样。但不会影响到块级框的布局而只会影响内联框(通常是文本)的排列。
  3. 绝对定位:设置为绝对定位的元素会从文档流完全脱离,并相对于其包含块定位,包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。

在这里先讨论浮动及其原理。

浮动

再次首先浮动的由来,浮动这个属性本来的目的是用来实现文字环绕图片,貌似所有 CSS 样式中只有浮动能将文字环绕图片这个效果做的最好。但同时用浮动来布局也时不错的,因此浮动更被常拿来布局,但也因此有了问题,如何清除或是闭合浮动带来的影响。

对于浮动的原理可以参考张鑫旭大牛的文章CSS float浮动的深入研究、详解及拓展1。我看完之后理解不深,自己也阐述不清,仅知道一点皮毛,因此不再记录其原理。

清除浮动

首先看浮动的影响:

  • 元素浮动之后,会影响内联框(通常是文本)的排列,这是我们希望看到的。

  • 但文档中的普通流就会表现得和浮动框不存在一样,当浮动框高度超出包含框的时候,也就会出现包含框不会自动伸高来闭合浮动元素(“高度塌陷”现象)。顾名思义,就是漂浮于普通流之上,这是我们不希望看到的。

因此清除浮动即是在解决浮动元素其父元素高度塌陷问题。

解决方法

在我看来解决方案大体分为两类:

  • 一类是借助 clear 这个“天然属性”来解决。
  • 另一类便是通过 BFC(Block Formatting Context)直译为“块级格式化上下文”。来解决。
    有很多清除浮动的方法都是建立在这两个方法上的。
再次先了解 BFC 是什么?

是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML 元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。

简单来理解 BFC 就是一个作用范围,就是一个独立的容器,拥有一套渲染规则,他决定了其内部元素如何定位,以及与其他元素的相互关系和作用。不会影响外部的元素。

BFC的规则

1、在创建了 BFC 的元素中,其子元素按文档流一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于 margin 特性。

垂直距离取决于 margin 特性的两个相邻的普通流中的块框在垂直位置的空白边会发生折叠现象。也就是处于同一个BFC中的两个垂直窗口的margin会重叠。生成 BFC 的元素不会和在流中的子元素发生空白边折叠。所以解决这种问题的办法是要为两个容器添加具有BFC的包裹容器。

2、在 BFC 中,每一个元素左外边与包含块的左边相接触,反之亦然,即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的 BFC。

3、创建了BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会在布局上影响到外面的元素,反之也是如此。

4、创建了 BFC 的元素不能与浮动元素重叠。

表格的 border-box、块级的替换元素、或是在普通流中创建了新的 BFC 的元素不可以与位于相同的 BFC 中的浮动元素相重叠。

5 、当容器有足够的剩余空间容纳 BFC 的宽度时,所有浏览器都会将 BFC 放置在浮动元素所在行的剩余空间内,是所在行。

当 BFC 的宽度介于 “容器剩余宽度” 与 “容器宽度” 之间时,BFC 会显示在浮动元素的下一行或是仍然保持显示在浮动元素所在行,并且 BFC 溢出容器;取决于浏览器。

当 BFC 的宽度大于 “容器宽度” 时,BFC 会显示在浮动元素的下一行或仍然保持显示在浮动元素所在行,并且 BFC 溢出容器;取决于浏览器。

6、计算生成了 BFC 的元素的高度时,其浮动子元素参与计算。

BFC的生成

满足下列CSS声明之一的元素便会生成BFC。

  1. 根元素
  2. float的值不为none
  3. overflow的值不为visible
  4. display的值为inline-block、table-cell、table-caption
  5. position的值为absolute或fixed

注: display:table也可以生成BFC,主要原因在于Table会默认生成一个匿名的table-cell,正是这个匿名的table-ccell生成了BFC。

BFC在布局中的应用

  1. 防止重叠:
    处于同一个BFC中的两个垂直窗口的 margin 会重叠,把两个容器分别放在两个有 BFC 的包裹容器即可解决。

  2. 清除浮动:
    清除元素内部浮动以及不和浮动元素重叠。

关于 IE 的 Layout

Layout 是 IE 浏览器渲染引擎的一个内部组成部分。在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算大小, 要么依赖于包含块来计算尺寸和组织内容。为了协调这两种方式的矛盾,渲染引擎采用了 ‘hasLayout’ 属性,属性值可以为 true 或 false。 当一个元素的 ‘hasLayout’ 属性值为 true 时触发,我们说这个元素有一个布局(layout),或拥有布局。可以通过 hasLayout 属性来判断一个元素是否拥有 layout ,object.currentStyle.hasLayout 。

hasLayout 与 BFC 有很多相似之处,在 IE 中,元素使用“布局”概念来控制尺寸和定位,分为拥有布局和没有布局两种情况,拥有布局的元素由它控制本身及其子元素的尺寸和定位,而没有布局的元素则通过父元素(最近的拥有布局的祖先元素)来控制尺寸和定位,而一个元素是否拥有布局则由 hasLayout 属性告知浏览器,它是个布尔型变量,true 代表元素拥有布局,false 代表元素没有布局。
hasLayout 只是一个 IE 下专有的属性,hasLayout 为 true 的元素浏览器会赋予它一系列的效果。

注意: hasLayout 在 IE 8 及之后的 IE 版本中已经被抛弃,所以在实际开发中只需针对 IE 8 以下的浏览器为某些元素触发 hasLayout。

触发layout

一个元素触发 hasLayout 会影响一个元素的尺寸和定位,这样会消耗更多的系统资源,因此 IE 默认只为一部分的元素触发 hasLayout (即默认有部分元素会触发 hasLayout ,这与 BFC 基本完全由开发者通过特定 CSS 触发并不一样)。
除了 IE 默认会触发 hasLayout 的元素外,Web 开发者还可以使用特定的 CSS 触发元素的 hasLayout 。
通过为元素设置 CSS,可以触发 hasLayout (即把元素的 hasLayout 属性设置为 true)。

zoom 是除了在 IE 5.0 中外,总是能触发 hasLayout 。zoom 用于设置或检索元素的缩放比例,为元素设置 zoom: 1 既可以触发元素的 hasLayout 同时不会对元素造成多余的影响。因此使用 zoom: 1 来触发元素的 hasLayout 。

再回到清除浮动上

先看一下清理浮动的各种方法:

1、添加额外的标签:

在父元素中的浮动末尾处添加一个额外的空标签。设置其样式 clear。

2、使用 br标签:

在父元素中的浮动末尾处添加一个br标签,可以设置其样式有 clear=“all | left | right | none” 属性。

3、父元素设置 overflow:hidden

通过设置父元素overflow值设置为hidden使其成为BFC,在IE6中还需要触发 hasLayout ,例如 zoom:1。

4、父元素设置 overflow:auto

通过设置父元素overflow值设置为auto使其成为BFC,但可能会产生滚动条。

5、父元素也设置浮动

通过设置父元素float值使其成为BFC,但与父元素相邻的元素的布局会受到影响。

6、父元素设置display:table

通过设置父元素display值使其成为BFC,盒模型属性会改变,由此造成的一系列问题。

7、使用 :after伪元素

通过在父元素上使用伪元素设置clear来达到清除浮动,之后再隐藏其伪元素已达到对布局的最小影响,IE6-7不支持:after。
伪元素可以在元素的内容前面或后面插入新内容。

由此看来最好的清除浮动方法为使用 :after伪元素来清除浮动

详细描述:
:after { content:”“; display:block; height:0; visibility:hidden; clear:both; }

  1. display:block 使生成的元素以块级元素显示,占满剩余空间;
  2. height:0 避免生成内容破坏原有布局的高度。
  3. visibility:hidden 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;
  4. 通过 content:”“;生成内容作为最后一个元素,至于content里面是点还是其他都是可以的。
  5. clear:both 清除浮动。

除了clear:both用来清除浮动的,其他代码都是为了隐藏掉content生成的内容,因此其他版本的清除浮动可能会有font-size:0,line-height:0。

以下是参考到的最佳解决代码

.clearfix:after { content:”\200B”; display:block; height:0;
clear:both; }
.clearfix { *zoom:1; }.

.cf:before,.cf:after {content:”“; display:table; } .cf:after {
.cf { zoom:1; }

注意:
上面的方法用到了 :before伪元素,它是用来处理margin边距重叠的,由于内部元素 float 创建了BFC,导致内部元素的margin-top和 上一个盒子的margin-bottom 发生叠加。如果这不是你所希望的,那么就可以加上 :before,如果只是单纯的闭合浮动,after就够了。

到此浮动的清除及BFC算理解完了


顺便补充自适应布局

1、overflow:auto/hidden
2、display:inline-block
3、display:table-cell

overflow有剪裁和出现滚动条等隐患,不适合作为通用类

display:table-cell

会让元素表现得像单元格一样,IE8+以上浏览器才支持。 与 display:inline-block一样,会跟随内部元素的宽度显示。但是,单元格有个特性是宽度值设置地再大,实际宽度也不会超过表格容器的宽度。

因此,如果把 display:table-cell 这个BFC元素宽度设置的很大。比如9999px。那其实就跟block水平元素自动适应容器空间效果一样了。
有两点制约
一是IE8+以上浏览器兼容。二是应付连续英文字符换行有些吃力(可以嵌套table-layout:fixed解决)。总体来看,适用的场景要比 overflow:hidden 大很多。

两栏或多栏自适应布局的通用类语句(block水平标签,需配合浮动)

.cell { display: table-cell; width: 9999px; *display: inline-block;
*width: auto;}

这是zxx.lib.cssCSS样式库中.cell的由来!

display:inline-block

inline-block元素跟元素设置浮动后的表现差别并不是很大。虽然他们实现的原理不同,但内部表现为块级元素,水平排列这种需求,浮动跟inline-block都适合实现。

两者的区别

  • 文档流:浮动元素会脱离文档流,并使得周围元素环绕这个元素。而inline-block元素仍在文档流内。
  • 水平位置:不能通过给父元素设置text-align:center让浮动元素居中。事实上定位类属性设置到父元素上,均不会影响父元素内浮动的元素。但是父元素内元素如果设置了display:inline-block,则对父元素设置一些定位属性会影响到子元素。(这还是因为浮动元素脱离文档流的关系)。
  • 垂直对齐:inline-block元素沿着默认的基线对齐。浮动元素紧贴顶部。可以通过vertical属性设置这个默认基线,但对浮动元素这种方法就不行了。
    空白:inline-block包含html空白节点。如果html中一系列元素每个元素之间都换行了,当对这些元素设置inline-block时,这些元素之间就会出现空白。而浮动元素会忽略空白节点,互相紧贴

IE6和IE7对此属性部分支持。要兼容这些浏览器,必须解决这个问题。值得留意一下。

主要问题

display:inline-block 会让元素尺寸包裹收缩,不具block水平的流动特性
inline-block 元素的空白间距

解决空白问题
1、改变HTML结构
2、负的margin
3、设置父元素字体为0
4、丢失结束标签
5、jquery方法
$(“).contents().filter(function() { return this.nodeType === 3; }).remove();

全兼容的样式解决方法

在父元素中设置font-size:0,用来兼容chrome等,使用letter-space:-N px来兼容safari。

以上参考自“如何解决inline-block元素的空白间距2


写到这算是告一段落,仅仅作为现在此时的理解,等以后理解更深再来补充。

什么事物都是在你不懂它时会感到难以理解,待明白过后再看便“简单”许多,虽并非如此,但总是如此。

最怕无知,写给再看的自己,愿你能够努力再奋斗!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值