CSS 中,用 float 和 position 的区别是什么?

CSS 中,用 float 和 position 的区别是什么?

呃,其实这个命题有误,只有position才是定位,float不能说是定位,不过你可以说这两种布局方式有什么不同。
float和position这两者并没有孰好孰不好的问题,两者按需使用,各得所需的效果。
float从字面上的意思就是浮动,这种在印刷排版之类中可能解释的更加贴切。float能让元素从文档流中抽出,它并不占文档流的空间,典型的就是图文混排中文字环绕图片的效果了。并且float这也是目前使用最多的网页布局方式。不过需要注意的是清除浮动是你可能需要注意的地方。并且如果你要考虑到古老的IE6之类的还会有一些bug诸如双边距等等问题。
而position顾名思义就是定位。他有以下这几种属性:static(默认),relative(相对定位),absolute(绝对定位)和fixed(固定定位)。其中static和relative会占据文档流空间,他们并不是脱离文档的。absolute和fixed是脱离文档流的,不会占据文档流空间。
比较可以发现,float和position最大的区别其实是是否占据文档流空间的问题。虽然position有absolute和fixed这两个同样不会占据文档流的属性,但是这两个并不适合被用来给整个网页做布局。为什么?因为这样你就得为页面上的每一个元素设置一个xy坐标来定位。
float布局就显得灵活多了。但是一些特殊的地方搭配relative和absolute布局可以实现更好的效果。因为absolute是基于父级元素的定位,当父级元素是relative的时候,absolute的元素就会是基于它的定位了。比如你可以让一个按钮始终显示在一个元素的右下角。
如果说到性能问题reflow问题,将元素的position设置为absolute和fixed可以使元素从DOM树结构中脱离出来独立的存在,而浏览器在需要渲染时只需要渲染该元素以及位于该元素下方的元素,从而在某种程度上缩短浏览器渲染时间。所以如果是制作js动画等,用absolute或者fixed定位会更好。
说得不好的地方请大家补充。总结一句就是不推荐用position来布局整个页面的大框架,而推荐用float或者文档流的默认方式。

贺师俊

在已有的回答中,我最赞同田乐。这里稍作补充。
在绝大多数Web开发者的语境中,“布局”这个术语和“排版”是有差异的。“布局”偏向于指宏观的GUI区域划分,比如双栏布局或三栏布局等。从这一点出发,float其实本不是一项用于“布局”的属性。float对应的其实是传统印刷排版中图文混排中的环绕。这其实可以理解,因为CSS的模型和术语脱胎于传统排版,故而与计算机GUI技术通常基于组件的模型相差甚远。除了float之外,另一个例子是CSS中上下margin的collapse,显然这是为了满足段落排版的需求。所以像float、margin collapse等,在典型的GUI技术中是没有的。还有,CSS box model中,width/height不算入padding和border,许多开发者对这点很不适应,这实际上是GUI的控件思维与CSS排版思维的冲突。这个冲突在浏览器技术实现上的遗迹就是IE臭名昭著的“hasLayout”。元素“has layout”的真实意思是这样的元素直接对应一个控件。也正是由于IE很naive的在实现中直接结合了这两种矛盾的模型,从而导致了无数的布局bug。
言归正传,CSS1时代的网页还很简陋,但是随着万维网的迅猛发展,Web界面也迅速进化,当初简单的如同书页般的通栏式网页迅速绝迹,frameset由于天生存在的一堆问题也很快退出主流,这时CSS在GUI布局方面就显出了缺陷,开发者被迫使用各种trick。比如历史悠久的table布局。后来table布局被鄙视,开发者逐渐转向了float布局。
要说float布局之所以流行,IE“功”不可没。在IE中,has layout的元素是不会环绕float元素的(因为has layout的元素自己是一个控件,所以总是保持一个矩形区域)。这本来是一个bug,但是其效果却正好符合常见的双栏布局的需要。另外IE下float元素会自动撑开其父级container元素(当然前提是container元素也是has layout的),这其实也是bug,但是也恰好符合模块布局的需求。后来所谓inline-block布局其实正是这些bug的合理化。
站在今天回望过去十多年的CSS实践,我们可以发现,无论float布局还是后来的inline-block布局,其实都是trick。所谓trick,就是将一些特性挪作他用,以很曲折的方式实现出想要的效果。CSS作为样式语言,其可维护性的最终来源,就是代码能清晰的表达出设计意图。而CSS trick当然不能很好的满足这一点。
那么如何才能真正用CSS来表达布局?如田乐所说,这有赖于“CSS3的进化”。如multiple column、flex box、grid layout等。其中直接对应目前float布局/inline-block布局所要达到效果的,是flex box。当然,考虑到兼容性问题(IE9仍不支持flex box模块,IE10才支持),我们可能很长时间内还是会继续使用float布局,不过必须始终牢记这是trick,是workaround。如有可能,最好引入SCSS/LESS之类的CSS框架来对此种布局trick做进一步抽象和解耦。
再说position布局。position其实比float要更接近“布局”属性。但是position的问题是,所谓布局是设定各区域(元素)的关联和约束,而定位只是设定单一元素的位置大小。要实现一个布局,要对多个定位元素中手动设定相关的参数(如左栏width:200px,右栏left:200px),相当于人为的把大小和位置参数计算出来。这违背了DRY原则,也无法真正实现关联约束。(如左栏设了max/min-width之后,最终实际width未必是200px,此时右栏怎么设left值?又如一个水平固定width、垂直自适应height的绝对定位元素,我们如何从它的底部继续排下一个元素?)除非我们引入JavaScript脚本来进行计算。因此运用position布局的限制条件相当多,通常只适合那些相对孤立的部件(如页头页脚)或较为简单且各区域大小位置固定的布局。至于说以JavaScript实现的布局管理器,是将position作为实现布局的底层技术,已经算不得CSS了(因为你也不写CSS)。

田乐

我补充一下float的问题。我们常说的文档流其实是指默认文档流。基本显示模型block和inline分别是块狀换行和连续多行模型,前者可以设定尺寸,后者不可以设定尺寸(根据内容决定尺寸和折行)。
不过我们总是遇到固定尺寸,或者固定部分尺寸且不折行的场景,这个时候我们马上会想到使用float来做布局,因为float会触发shrink to fit特性,实现根据内容决定尺寸,float还不会产生折行,我们通过clear来手工模拟折行。这个现状我觉得主要是因为对inline-block的兼容性顾忌产生的,在IE6的时候它没有被广泛支持。使用position实现这样的布局需要配合javascript修正,在某些场景它比float强,因为float模拟的流动布局不是多行连续布局,一些浮动元素经常因为意外的尺寸改变被卡在我们不希望它出现的位置。所以我们可以看到像pinterest这样的网站使用了javascript配合absolute position的方式,讲布局引擎的任务完全交给javascript来实现。从表现与行为分离的角度它不太合理,但是从结果上来说它很让人满意。
但是,我写这段的意思是说,很多时候我们希望控制的布局流问题不需要float和position实现,而应该通过显示模型定义来解决。比如现在的column layout、flex box等等,都是在这个角度解决我们遇到的问题,它们应该才是正解。而我们犯这个错误的最初原因也许就是对像inline-block这样的显示模型的不信任开始的。
希望CSS3的进化能够让我们重建这样的信任。
UPDATE: 我忘记说的就是如果你做移动的Web开发,那么你就知道为啥float很少在布局上使用。Android和iOS里面的flex box已经非常稳定了,很低版本(Android 1.6,iOS 3)就已经很好支持了,用这些布局模型在窄小且多样的手机屏幕上面相当可靠,而float在这些情况下则问题层出不穷。所以我现在相信mobile first,也相信移动设备的Web能够更好的推广CSS3的众多新特性的采用。比如新的CSS3 background and box module在移动设备里面几乎是必备的,因为background-size是retina display必用的,而border-image则是解决复杂的按钮和面板的最佳解决方案。如果你做Mobile Web,那么你就会爱上CSS3新特性,也会享受它带来的标准化的世界的好处。

来源: <http://www.zhihu.com/question/19588854>

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。