【面试必备】CSS盒模型的点点滴滴
从接触CSS布局开始,就一直在听盒模型的概念了,网上的文章有很多,深浅不一。有些人会认为盒模型很简单,不就是border、margin、padding、content嘛,一个元素所占的空间就是把它们都加起来~仅仅如此吗?当然不是,盒模型的概念其实挺好理解,但难的是与其他属性一块使用时产生的现象。下面把我知道的一些特性梳理一下,这也是css中最基础的知识,面试常会问的东西。
盒模型的基本概念
正如上面说的,盒子模型的几个要素就是border、margin、padding、content,相信你已经听过很多次了,就像下面这张百看不厌的图一样:
不过要明确的是,这里所说的盒子是指块级(block-level)元素,行内元素有自己的一套标准,正如给行内元素设置margin-top无效一样,不在这个盒子的讨论范围之内。本篇文章所说的盒子就是针对块级元素。一个盒子其实是包含了四层,分别是content-box,padding-box,border-box,margin-box,它们的分界线就是上面画出的那四个轮廓。这四个概念非常重要,后面我们要进行的各种边界区分,就以它们为标准来讨论。
一个盒子在没有被定位时,即没有加position也没有float,在普通流中所占的空间就是这些值的总和。即横向空间为:marginLeft + borderLeftWidth + paddingLeft + width + paddingRight + borderRightWidth + marginRight,纵向的同理。
jQuery用多了,竟然忘记了如何用原生js来取这些值,所以在这里也提一下。首先如果css样式是写在行内的,即元素的style属性中,那么直接通过element.style.marginLeft这样就可以取到。如果样式不在行内(通常情况都不在),通过style是无法取到的。IE和opera支持currentStyle属性,可以取到定义在外部的样式,其他浏览器则需要通过window.getComputedStyle来取,所以完整的获取属性的代码应该如下:
var element = document.getElementById('id');
var currentStyle = null;
if(element.currentStyle){
currentStyle = element.currentStyle;
}
else{
currentStyle = window.getComputedStyle(element);
}
console.log(currentStyle.marginTop);
宽度的计算
从简单的开始,我们给一个盒子指定样式width:100px,是给上述四层盒子的哪一层来指定的呢?是content-box,即最内层的内容区域。另外我们也知道,元素的宽度会被它的padding撑开,实际的宽度会是width + padding。那border会不会撑开元素的宽度呢?这个。。平时写边框大多数就是1个像素宽,基本忽略了。。。其实border也是会撑开宽度的。那margin会不会呢?都是外边距了,已经在盒子外头了怎么会撑开呢,少年你想多了~
这样来看,光一个宽度就会有三种值,我们来举个栗子:
<style>
#container{
position: relative;
width: 400px;
height: 400px;
background-color: lightgreen;
overflow:hidden;
}
#box1{
width: 100px;
height: 100px;
margin: 20px;
padding: 20px;
border:20px dotted;
background-color: lightblue;
}
</style>
<div id="container">
<div id="box1"></div>
</div>
getComputedStyle(box1).width : 100px
box1.clientWidth : 140
box1.offsetWidth : 180
我这里姑且把它们分别叫做“指定宽度”、“实际宽度”、“偏移宽度”。指定宽度就是css样式中的width值,实际宽度是被padding撑开后的宽度,由clientWidth属性可访问到,偏移宽度是被border撑开后的宽度,由offsetWidth可以访问到。这里我又想到了jQuery,jq中有两种方式可以取到元素的宽度,它们取到的是哪个值呢,来看一下:
var $width = $('#box1').width();
console.log($width);// var csswidth = $('#box1').css('width');
console.log(csswidth);//100px
可以看到两者都是取到了指定宽度,不同的是.width()返回一个数字100,可以直接参与数值运算。而.css('width')返回了字符串100px。
上面是指定了宽度值的情况,如果不指定宽度的盒子是怎样的呢?首先对于一个只有content-box的盒子,它会沾满父元素的整行宽度,就像是指定了width:100%一样,如下图:
如果指定了margin值,那么这个content-box的宽度就变成了父容器的宽度减去margin值,即除了外边距剩下的宽度:
看来默认宽度挺好理解的,就是父容器减去margin值后剩余的宽度,是能自适应的~
但情况远不是这么简单。当元素有float属性或position为absolute时,宽度就不是自适应的了,而是会收缩起来,包裹住内容。例如我给粉色区域加了position:absolute,就变成这样了:
事实上,在给粉色元素加上display:inline-block时,也会收缩起来像上面一样。inline-block的内容谈起来也不是一篇文章能说清的,在本篇就不探讨了。我们还是继续聊宽度。
我们在进行自适应布局时,会使用百分比作为宽度单位,这样页面可以适应不同大小的屏幕。然而我们常常还需要设置一些比较小的间距,我在看响应式设计那本书时作者建议无论多小的长度都使用百分比,即你可能会写出这样的css代码:margin-left:0.3212332%; 当然这数值你用计算器算下的,如果能除尽,你可以把小数位数全写出来,尽管不好看,但可以保证精确。但总有除不尽的时候,当我们进行四舍五入的时候,有时候稍稍大了那么一点,就会出现元素被挤到下一行的尴尬场面。这个时候你多么希望,那5px的边距直接写成5px就好,再也不必计算什么百分比。
啰嗦了这么多,我其实就是想介绍一个css3的新特性而已。。。它就是calc,让你的宽度值通过计算得出。最关键的时,它支持百分比和像素混合计算,简直太酷了,话不多说,上栗子:
#box3,#box4{
height: 100px;
padding: 10px;
background-color: orange;
border:5px solid;
float: left;
}
#box3{
width: 40%;
}
#box4{
width: 60%;
}
<div id="container">
<div id="box3">box3</div>
<div id="box4">box4</div>
</div>
在上面这种情况下,由于padding和border的存在,实际两个div的宽度加起来要比100%大,所以box4就被挤到下一行了。下面我们来试试这个calc的威力,把box3和box4的宽度修改为:
#box3{
width: -webkit-calc(40% - 30px);
}
#box4{
width: -webkit-calc(60% - 30px);
}
这下就不会换行了。需要注意的是calc是css3的新属性,现在支持度还不高,需要加私有前缀使用。另外要注意的一点是,运算符号+-(加减)与数值之间一定要留有空格,否则会被认为是非法的取值。而*/(乘除)运算符则不需要。
background的覆盖区域
设置背景色我们平时用的太多了,不知你是否注意过,元素的背景到底是以哪个区域为边界的呢,border-box?padding-box?还是content-box?不着急回答,我们需要分两种情况,设置背景色和背景图片。
先说背景色,通过background-color设置的背景色总是填充满border-box,我们用一个虚线框的元素就可以看出来,就像上面的box1一样:
下面来看背景图片的情况,通过background-image设置的背景图片默认填充padding-box,看下面的代码:
<style>
#box5{
width: 200px;
height: 300px;
margin: 20px;
padding: 20px;
border:30px dotted;
background-image: url(http://images.cnblogs.com/cnblogs_com/lvdabao/507840/o_Img347406026.jpg);
background-repeat: no-repeat;
}
</style>
<div id="box5">box5</div>
左上方从padding-box的区域开始填充,右侧和下侧超出后会超到border-box的区域,但不会超到margin-box,这也是合理的。
在背景图片中,我之所以说“默认”而不是“总是”,是因为现在我们可以通过background-origin来设置背景图片的填充区域了,这是css3的一个新属性,用于设置了background-repeat为no-repeat的元素。它的取值有三种:padding-box、border-box、content-box,分别指定背景图片的填充区域。这三个值正好对应我前边说的盒子模型的概念。效果你应该能想象到,我们来试一下吧:
border-box
padding-box
content-box
overflow:hidden;隐藏了哪里?
我们都知道overflow:hidden;可以隐藏掉内容超出元素的部分,但是你有没有细细探究过到底是超出哪里的部分呢?具体来说就是,超出content-box被隐藏?超出padding-box被隐藏?还是超出border-box?通过下面的例子便可一探究竟:
<style>
#box1{
width: 100px;
height: 100px;
margin: 20px;
padding: 20px;
border:20px dotted;
background-color: lightblue;
overflow: hidden;
}
#box1_1{
width: 200px;
height: 200px;
background-color: red;
}
</style>
<div id="box1">
<div id="box1_1"></div>
</div>
效果如下:
可以看到红色盒子被隐藏掉了padding-box以外的部分,子元素的内容并不会延伸到父元素的边框上,这也是符合常规逻辑的。
left/top的定位参照点
当给一个元素指定position:absolute;后,即绝对定位,便可以参照它的包含块(containing block)进行定位。所谓包含块就是指父级元素中最近的拥有定位属性的元素,即position值不为static的元素。通过left和top值来指定相对包含块的左上角的偏移距离。那么这个“左上角”具体是指哪里呢?是下面ABCD四个点中的哪一个?同样,元素自己的点又是取哪一个呢?
通过下面的例子来探究一下:
<style>
#container2{
position: relative;
width: 400px;
height: 400px;
margin: 20px;
padding:20px;
border: 20px dotted;
background-color: lightgreen;
}
#box6{
position: absolute;
width: 100px;
height: 100px;
padding: 20px;
border: 10px dotted;
background-color: red;
}
</style>
<div id="container2">
<div id="box6"></div>
</div>
left/top为0left/top为默认值
通过点击上面的按钮,我们可以得出以下几个结论:
- 元素自身的参照点是最外围的盒子,即margin-box,如果没有margin就以border-box,以此类推。
- left/top值为默认值(auto),元素还在原来的位置上,即紧贴父元素的content-box区域左上侧。
- left/top指定值后,参照父元素的padding-box左上角,即我们上面图中的C点。
取负值的情况
border、padding取负值都是非法的,而margin取负值是合法的,而且还大有所用。简单来说,margin会影响元素的宽高,使元素往回“缩”一定的长度。看下面的例子:
<style>
#box7,#box8{
width: 200px;
height: 200px;
background-color: red;
border: 1px solid;
}
#box7{
background-color: green;
margin-bottom: -100px;
}
</style>
<div id="box7">box7</div>
<div id="box8">box8</div>
尽管box7的高度指定为200px,但因为margin-bottom:-100px让它缩回去100px,所以只剩100px的高度了。关于margin负值的应用场景非常的经典,我这里就不一一列举了,可参考瑶姐的这篇文章:http://blog.doyoe.com/~posts/css/2013-12-06-margin%E7%B3%BB%E5%88%97%E4%B9%8B%E5%86%85%E7%A7%80%E7%AF%87.md
BFC
BFC同样也是盒模型中非常重要的一个概念,出于篇幅的原因,我不能详细的解释了,有一篇文章介绍的非常好,可参考http://blog.melonhuang.gitpress.org/~docs/css/1formattingContext.md
【面试必备】CSS盒模型的点点滴滴的更多相关文章
- 前端面试必备技巧(二)css盒模型及BFC
CSS盒模型 基本概念:标准模型+IE模型及区别 CSS如何设置这两种模型? JS如何设置获取盒模型对应的宽和高? 实例题(根据盒模型解释边距重叠) BFC边距重叠解决方案 (1)BFC的基本概念:b ...
- 面试汇总——说一下CSS盒模型
本文是面试汇总分支——说一下CSS盒模型. 基本概念:W3C标准盒模型和IE盒模型 CSS如何设置这两种模型 JS如何获取盒模型对应的宽和高 根据盒模型解释边距重叠 BFC(边距重叠解决方案) 一. ...
- 大前端学习笔记整理【一】CSS盒模型与基于盒模型的6种元素居中方案
概览 CSS盒模型,规定了元素框来处理元素的 内容.内边距.边框和外边距的方式 元素部分是指内容部分,也是最实际的内容,包围内容的称之为内边距,内边距外围是边框,边框外围就是外边距:且外边距是透明的, ...
- CSS盒模型的深度思考及BFC
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 题目:谈一谈你对CSS盒模型的认识 专业的面试,一定会问 CSS 盒模型 ...
- 前端笔记(关于css盒模型知识整理)
我以前整理的文章可能也不是特别深入.所以现在开始尝试即使多花点时间收集整理,也不只发浅层知识,这样对技术的深入理解是很有帮助的. 废话不多说,我们现在开始. 说到css盒模型,这是大多面试基础中会经常 ...
- CSS盒模型
CSS盒模型是CSS 可视化格式化系统的基石,它是理解样式表如何工作的核心概念.盒模型用于元素定位和页面布局.元素框的最内部分是实际的内容,直接包围内容的是内边距.内边距呈现了元素的背景.内边距的边缘 ...
- 第 16 章 CSS 盒模型[下]
学习要点: 1.元素可见性 2.元素盒类型 3.元素的浮动 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS 盒模型,学习怎样了解元素的外观配置以及文档的整体布局. 一.元素可见性 使用 vis ...
- 第 16 章 CSS 盒模型[上]
学习要点: 1.元素尺寸 2.元素内边距 3.元素外边距 4.处理溢出 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS 盒模型,学习怎样了解元素的外观配置以及文档的整体布局. 一.元素尺寸 C ...
- 【前端盲点】DOM事件流论证CSS盒模型是否具有厚度
前言 很久没有扯淡了,我们今天来扯淡吧. 我今天思考了一个问题,我们页面的dom树到底是如何渲染的,而CSS盒模型与javascript是否有联系,于是便想到一个问题: CSS的盒模型具有厚度么??? ...
随机推荐
- python os模块
import os path = "路径" os.getcwd() #获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname" ...
- cassandra的写过程
如下: Message, get a new request,type:QUERY //channelRead0函数 Message, get a new request,customPay ...
- CentOS系统下安装配置ftp服务
安装配置步骤: rpm -ivh /opt/bak/vsftpd-2.2.2-11.el6.x86_64.rpm --本地安装vsftpd ll /etc/vsftpd/ --查看vsftpd的配置 ...
- C# Form.Close 的释放问题
今天使用From窗口Close后,发现From的资源还存在,并没有释放资源,只有在程序关闭的时候才去释放. Form1:button按钮 private void button1_Click(obje ...
- 1214 - Large Division -- LightOj(大数取余)
http://lightoj.com/volume_showproblem.php?problem=1214 这就是一道简单的大数取余. 还想还用到了同余定理: 所谓的同余,顾名思义,就是许多的数被一 ...
- ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法
ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法 语法 第一种: 通过使用Oracle语句块 --指定文档所有部门都能查看 declare cursor TABLE_DEPT and ...
- Web系统大规模并发——电商秒杀与抢购 【转】
电商的秒杀和抢购,对我们来说,都不是一个陌生的东西.然而,从技术的角度来说,这对于Web系统是一个巨大的考验.当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要.这次我们 ...
- js queue dequeue clearQueue stop
一.queue( [queueName ], newQueue ) 操作欲执行队列方法 第一个参数是队列名称,不写的话默认是fx 第二个参数可以是一个函数数组,存放所有队列函数,也可以是一个回掉函 ...
- 置入式模型inclusion model和显示具现化
1.置入式模型 链接错误: 大多数非模板程序代码的组织如下:A,类声明在头文件中: B:全局变量和非inline函数在cpp文件中定义 但是,如果模板程序也这样组织,则会出错.原因在于:函数模板的定义 ...
- 彻底弄懂js循环中的闭包问题
来源:http://www.108js.com/article/article1/10177.html?id=899 第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然 ...