资讯专栏INFORMATION COLUMN

css布局基础总结

PrototypeZ / 3256人阅读

摘要:想写出高效合理的布局,必须以深厚的基础为前提。现在布局方式主要分为三种传统布局方案等配合。弹性布局,实现方便,兼容性较好。在环境中的元素按照如下规则渲染和文档流一样,元素按照自己类型的布局特性从左到右,从上往下依次排列。

前端css布局知识繁杂,实现方式多种多样。想写出高效、合理的布局,必须以深厚的css基础为前提。为了方便记忆和复习,将css布局要点记录如下。内容较多,应用方面说的不太详细,但都是很实用的点。

所谓布局,就是指将元素设置为我们想要的大小,放置于我们想要的位置,位置尺寸是核心两要素。这些元素其实就是一些方块,页面就是由各种方块拼凑而成。现在布局方式主要分为三种:

传统css布局方案(position,float,line-height等配合)。实现复杂,需要多种属性配合使用,兼容性最好。

flex布局方案。弹性布局,实现方便,兼容性较好。

gird布局方案。

使用哪种布局方式,看项目具体要求,如果不需要兼容IE,建议使用flex或者grid,这两种是未来趋势。如果要考虑兼容,则最好使用传统css布局方案。

传统css布局方案 css标准盒模型

前面提过,一个html元素,就是一个方块,讲究一点的话就是盒模型。盒模型长这样:

我们可以在chrome开发者工具的styles中查看:

css盒模型,分为4部分:

content:显示元素内容区域,包含子孙元素的地方

padding:内容区域到边框的距离,也称内边距

border:显示自身轮廓

margin: 用于设置元素自身和同级元素或者父级元素的距离

规则

无规矩不成方圆。所有的html元素都是按照一定规则去排列渲染的。在html中,不只有一种规则,是多种规则的混合。了解这些渲染规则和这些规则生效的条件对于我们理解css有很大帮助。

文档流

文档流可以理解为所有元素的默认渲染规则。它的规则很简单:元素按照自己的类型的布局特性从左到右,从上往下依次排列。

元素在布局上分为三种类型:

块级元素:默认占据一整行,即时设置宽度也还是占据一整行,由margin来补充(霸道总裁),有block、table、flex、grid、list-item

内联元素:宽度由内容撑开,只占据自己的位置,即时设置了宽度也不起作用,margin也是左右起作用,上下不起作用(大家闺秀),有inline

内联块级元素: 宽度由内容撑开,只占据自己的位置,可以设置自己的宽度(两个人的孩子?),有inline-block、inline-table、inline-flex、inline-grid

上面内联元素其实说的不太正确,这里需要特殊说一下,内联元素又分为两种:

可置换内联元素:该元素展示的内容不在css作用域范围之内,典型比如img、video、object、input、textarea等,展示内容由src、value等决定,这种元素可以设置宽高

不可置换内联元素:普通的内联元素,比如span、a、i、em等

有两种方式可以脱离文档流,绝对定位和浮动,我们下面再详细说。

BFC

BFC全称是Block Formatting Context,块级格式化上下文。在BFC环境中的元素按照如下规则渲染:

和文档流一样,元素按照自己类型的布局特性从左到右,从上往下依次排列。

BFC是一个独立、封闭的渲染区域。子元素的样式对BFC外部产生影响。

BFC可以识别浮动子元素。

BFC可以识别浮动的同级元素。利用这一点可以制作弹性布局。

那么什么样的渲染区域是一个BFC哪?下列几种方式可以显示声明一个BFC的渲染区域:

根元素或包含根元素的元素

float的值不为none

position为absolute或者fixed

overflow的值不为visible

display为inline-block、table-cell、table-caption

尺寸

元素的尺寸有两种情况:

默认情况: 块级元素宽度默认为100%,高度由内容撑开;内联元素和内联块级元素宽度和高度默认由内容撑开。

开发者设置: 主动设置width、height、line-height等

我们先来明确一下元素的尺寸概念,我们都知道元素的盒模型,元素由content、padding、border、margin四个区域组成。那么尺寸具体是指什么?我们可以把尺寸分为三类:

元素尺寸:由content、padding、border组成,在原生的DOM API中用offsetWidth、offsetHeight获取

元素内部尺寸: 由content、padding组成,在原生的DOM API中用clientWidth和clientHeight获取

元素外部尺寸: 由content、padding、border、margin组成,没有对应的DOM API,但是理解这个,对布局很有帮助

而我们在css中设置的width、height代表哪部分区域是有歧义的,我们通过设置box-sizing,可以切换width、height所代表的区域。

box-sizing

box-sizing,可以切换width、height所代表的区域。box-sizing主流浏览器有两个值:

content-box: width、height设置的是content的宽高

border-box: width、height设置的是content、padding、border加起来的宽高

box-sizing的这两个属性,造成width、height的二义性,而且很多情况下是全局设置的,隐蔽性很强,对于新手来说很容易懵。这两个属性的产生有一定的历史原因,最开始的盒模型默认采用的border-box,早期的IE就是这种,也叫IE盒模型。后来W3C觉得content-box更好,又把盒模型默认改为content-box模式。后来的后来,随着弹性布局的流行,border-box的优势越来越明显,大家都更愿意使用border-box来布局,W3C又想把border-box搞回来。但是已经有好多基于content-box的网站,为了兼容性也不能随便改。于是,W3C就想出了box-sizing这种方式,支持了border-box,但是默认还是content-box。使用box-sizing应注意的几点:

加入要全局设置box-sizing: border-box,要注意对第三方组件库的侵入,因为第三方组件很可能是基于content-box来布局的

设置所有元素的box-sizing属性为inherit:

*, *:before, *:after {
    box-sizing: inherit;
}

这样我们可以设置父元素的box-sizing,就可以控制所有子元素的box-sizing属性,对于我们封装组件,设置整个组件环境很方便,只有我们在封装组件时强设置box-sizing,就不怕全局的样式侵入了。

content-box模式在设置弹性布局时,可以使用calc属性辅助实现,或者弄两层div实现

尺寸的百分比设置
包含块

我们知道width, height都是可以设置百分比,那这个百分比的参照物是谁?这里引出一个概念,叫做包含块(CB, Contanining Block),一个元素的包含块就是该元素的width、height百分比的参照物。

很多新手同学,在设置宽高百分比的时候,有时候觉得莫名其妙,各种奇怪现象,怎么设置都不起作用。其实就是没有包含块的概念。一个元素的包含块是谁,主要取决于该元素的position属性,总结如下:

position为static和relative的元素,包含块为其父元素的content-box

position为absolute的元素,包含块为其最近的定位非static的祖先元素的padding-box,如果没有定位非static的祖先元素,则为初始包含块(后面解释)

position为fixed的元素,包含块为视口viewport

position为absolute和fixed时,包含块也可能是由满足以下条件的最近父级元素的padding-box:

A transform or perspective value other than none

A will-change value of transform or perspective

A filter value other than none or a will-change value of filter (only works on Firefox)

这条比较特殊,遇到的情况比较少,多带带拿出来

除了width, height的百分比相对于包含块设置外,margin、padding的百分比也是相对于包含块设置,只不过margin、padding百分比相对于包括块的宽度设置(水平模式下)。绝对定位的偏移属性top、left、right、bottom也是相对于包含块设置,后面再详细说。

初始包含块

元素的包含块都是自己的祖先元素,那hmtl元素没有祖先元素,它的百分比设置相对于谁那?就是初始包含块,根元素(hmtl)所在的包含块是一个被称为初始包含块的矩形。这个矩形的大小就是浏览器视口的大小。有一点需要注意,那些没有定位非static祖先元素的参照物是初始包含块,而非html元素。

margin

因为margin在布局中有一些重要特性和特殊情况,所以多带带拿出来讲一下。

margin:auto

我们知道,块级元素即使设置了宽度,也会占满一行,为什么会这样?剩余的空间被谁占了?

这里要明确一点,块级元素占据一行,是指块级元素的外部尺寸占据一行,就是margin-box。当margin设置为auto的时候,margin会自动占满剩余空间。

margin-left: 默认为0,为auto时,自动充满剩余空间

margin-right: 默认为0,为auto时,自动充满剩余空间

margin-top: 默认为0,为auto时,值还是为0

margin-bottom: 默认为0,为auto时,值还是为0

当margin-left和margin-right同时为auto,就会平分剩余空间,这就是margin:auto会使元素水平居中的原因。然后margin: auto却不能使元素垂直居中,这是因为在垂直方向上,块级元素不会自动扩充,它的外部尺寸没有自动充满父元素,也没有剩余空间可说。如果我们在父元素上设置writing-mode: vertical-lr,这时margin:auto就会使子元素垂直居中,而水平居中无效。

那有没有什么办法使用margin:auto让元素同时水平垂直居中?答案是有的,就是绝对定位的情况下。

.father {
    width: 300px; height:150px;
    position: relative;
}
.son {
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    width: 200px;
    height: 200px;
    margin: auto;
}

此时的son的外部尺寸,就会自动充满它的包含块,效果和块级元素类似。这时候设置.son元素的宽高,就会有剩余空间出来,margin:auto会自动平分剩余空间,使.son水平垂直居中。

margin对布局影响

margin对元素的影响有2个:

影响内部尺寸

影响外部尺寸

影响元素内部尺寸

块级元素这种宽度方向自动充满空间的布局特性,当没有设置宽度,设置margin-left和margin-right为对元素的内部空间有影响。margin为正值时,元素尺寸缩小;margin为负值时,元素尺寸增大。因为元素的外部尺寸大小已经定了,就是其包含块的尺寸,而外部尺寸等于元素尺寸加上margin,如果margin为负,元素尺寸自然就增大了。利用内部尺寸增大、外部尺寸不变这个特点,我们可以进行等间隔列表的布局。比如我们实现一个一行三列,两侧无间隙,中间间隙为20px的布局:

.father{
    margin-right: -20px;
}
.son{
    width: calc( calc(100% - 20px * 3) / 3);
    margin-right: 20px;
}
影响元素外部尺寸

在元素宽高固定的时候,相当于元素尺寸固定了,margin开始影响元素的外部尺寸。正margin会使元素元素的外部尺寸增大,负margin会使元素元素的外部尺寸缩小。正值很好理解,就不说了。主要说一下负值,这时候margin-top、margin-left和margin-right、margin-bottom的表现看起来是有区别的,实质是一样。margin-top、margin-left为负值时,表现为元素向上或者向左移动,margin-right、margin-bottom为负值时,表现为其右侧元素或者下面元素都会相应地向左或者向上移动。仔细想想,这都是元素外部尺寸缩小的表现。margin-top、margin-left使左侧上上侧尺寸缩小,就会自然向左或者向上移动。margin-right、margin-bottom使右侧和下侧尺寸缩小,旁边和下面的元素自然就会往左或者往上占位。

margin合并

块级元素的上边距和下边距在某些场景下会发生合并行为。需要注意的是浮动元素和绝对定位元素不会发生合并,且合并只发生在垂直方向。有以下3中合并场景

相邻兄弟元素

父元素和第一个/最后一个元素

元素内容为空时,height为0,自己的上边距和下边距会发生合并

margin合并的计算规则

正正取大

正负相加

负父取小(-20px, -50px合并取-50px)

阻止margin合并的方法

把合并元素变成BFC,比如设置display: inline-block,overflow: hidden, float: left等

父子合并/空元素合并时,给父元素/空元素设置border、padding都能阻止合并

内联元素尺寸

主要想说line-height,vertical-align两个属性,这两个属性对高度有重要的影响,而且如果没有理解这两个属性的作用,会经常碰到一些不好解决的诡异的布局问题。

幽灵空白节点

这个名字是张鑫旭大神定义的,在W3C规范中也是可以找到根据的。在《CSS世界》这本书中,为了证明幽灵空白节点的存在,举了一个例子:

div {
    background-color: #cd0000;
}
span {
    display: inline-block;
}

你可能猜到了,div的高度不为0,我在chrome下试了试高度为21px,这个高度猜测应该和div的字体、字体大小、行高有关。这个幽灵空白节点的存在,会引起一些怪异现象,比如:

我是文字,我要环绕你

.img-wrap因为高度塌陷,实际上不识别float元素,高度为0,p元素与其重合,从而实现文字环绕效果。

高度塌陷特性在实现布局的时候是不合理的,而现在文字环绕的场景很少,float基本都用来布局使用了。这现在实际上已经成为了一个“bug”的存在。所以css又提供了一个属性用来清除浮动:clearfix。

clearfix

clearfix在mdn上的解释为指定一个元素是否可以在它之前的浮动元素旁边(我觉得这里用重合更贴切),或者必须向下移动(清除浮动) 在它的下面。

注意上面这句话,指定一个元素表示clearfix的作用目标是元素自身,在它之前的浮动元素表示clearfix的作用条件是它前面有浮动元素,而clearfix的作用效果是让元素换行显示。所以clearfix的作用是,如果元素前面有浮动元素,可以指定该元素换行显示,或者说是识别前面的浮动元素。clearfix有3个值:

left: 清除左浮动

right: 清除右浮动

both: 清除左右浮动

一般情况下采用clearfix: both。清除浮动一个重要应用就是解决float高度塌陷的问题。通用的解决方案是设置.clearfix类:

.clearfix {
    display: block;
    zoom: 1;
    &:after {
        content: "";
        display: block;
        font-size: 0;
        height: 0;
        clear: both;
        visibility: hidden;
    }
}

在包含浮动元素的父元素上设置该类即可。

博客地址

参考

张鑫旭 《CSS世界》

https://mp.weixin.qq.com/s/8e...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/116935.html

相关文章

  • 前端-CSS3&H5

    摘要:高度模型浅识为的简写,简称为块级格式化上下文,为浏览器渲染某一区域的机制,中只有和中还增加了和。并非所有的布局都会在开发中使用,但是其中也会涉及一些知识点。然而在不同的纯制作各种图形纯制作各种图形多图预警 一劳永逸的搞定 flex 布局 寻根溯源话布局 一切都始于这样一个问题:怎样通过 CSS 简单而优雅的实现水平、垂直同时居中。记得刚开始学习 CSS 的时候,看到 float 属性不...

    xiaolinbang 评论0 收藏0
  • GitBook《拥抱未来的CSS布局方式:flex与grid布局》全教程

    摘要:拥抱未来的布局方式与布局全教程本书系列文章为对中布局与布局的详细介绍,已在同步更新,如您在阅读过程中发现描述有误或错别字的情况,您可以向本项目提出或。主要是对于标准里的布局方式草案中的布局方式进行一些总结。 GitBook《拥抱未来的CSS布局方式:flex与grid布局》全教程 本书(系列文章)为对CSS中flex布局与grid布局的详细介绍,已在GitHub同步更新,如您在阅读过程...

    zebrayoung 评论0 收藏0
  • CSS布局

    摘要:经过半年的打磨,正式发布,主要是新增了一些常用组件,并使用命名,为接下来的微信小程序开发做好准备。这两种方式实现的瀑布流式布局均支持首屏和网页窗口大小改变时的列数自适应。主要是对于标准里的布局方式草案中的布局方式进行一些总结。 一劳永逸的搞定 flex 布局 寻根溯源话布局 一切都始于这样一个问题:怎样通过 CSS 简单而优雅的实现水平、垂直同时居中。记得刚开始学习 CSS 的时候,看...

    jaysun 评论0 收藏0
  • 移动端布局与适配

    摘要:实战之微信钱包腾讯服务界面网格布局是让开发人员设计一个网格并将内容放在这些网格内。对于移动端适配,不同的公司不同的团队有不同的解决方案。栅格系统用于处理页面多终端适配的问题。 grid实战之微信钱包 腾讯服务界面 CSS3网格布局是让开发人员设计一个网格并将内容放在这些网格内。而不是使用浮动制作一个网格,实际上是你将一个元素声明为一个网格容器,并把元素内容置于网格中。 移动端页面适配—...

    Clect 评论0 收藏0
  • 前端开发周报: CSS 布局方式与JavaScript数据结构和算法

    摘要:如果没有学习过计算机科学的程序员,当我们在处理一些问题时,比较熟悉的数据结构就是数组,数组无疑是一个很好的选择。 showImg(https://segmentfault.com/img/bVTSjt?w=400&h=300); 1、常见 CSS 布局方式详见: 一些常见的 CSS 布局方式梳理,涉及 Flex 布局、Grid 布局、圣杯布局、双飞翼布局等。http://cherryb...

    huhud 评论0 收藏0

发表评论

0条评论

PrototypeZ

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<