Open shenxuxiang opened 4 years ago
通过修改某个属性值呈现的内容就可以被替换的元素就被称为 “替换元素”。<img>、<object>、<vedio>、<iframe>、<textarea>、<input> 等都是典型的替换元素
<img>、<object>、<vedio>、<iframe>、<textarea>、<input>
内容的外观不受页面上的 CSS 的影响
有自己的尺寸:在不设置尺寸的时候,这些元素会有一个默认的尺寸(300 * 150),如: <video>、<canvas>、<iframe>。<img> 图片默认展示的就是图片的原始尺寸。
<video>、<canvas>、<iframe>
<img>
在很多 CSS 属性上有自己的一套表现规则。比较有代表性的就是 vertical-align 属性。对于字符而言,vertical-align 的默认值就是 baseline,也就是字母 “x” 的下边缘。但是,对于替换元素而言就不一样了。对于图片来说 vertical-align 的默认值就是图片的下边缘。
vertical-align
baseline
可以将替换元素的尺寸从内到外分为:“固有尺寸”、“HTML尺寸”、“CSS尺寸”
固有尺寸:指的就是替换内容原本的尺寸。例如,图片、视频作为一个单独的文件存在的时候,都有着自己的宽度和高度,这个宽度和高度就是“固有尺寸”
HTML尺寸:一些替换元素存在 width 和 height 的 HTML 属性,例如 <img> 和 <canvas> 元素。这个称为 HTML 尺寸
width
height
HTML
<canvas>
CSS尺寸:指的是可以通过 CSS 的 width 和 height 或者 max-width/min-width 和 max-height/min-height 设置元素的尺寸。这种称为 CSS 尺寸
max-width/min-width
max-height/min-height
如果 ”固有尺寸“ 含有固有的宽度比例,同时仅设置了宽度或者仅设置了高度,则元素依然按照固有比例宽高显示
<div style="height: 32px; line-height: 32px; background: #444"> xxxx<span style="background: #999; padding: 20px 0; border: 5px solid #fff">我是谁</span>xxxx </div> <div style="height: 32px; line-height: 32px; background: #555"> xxxx的是非得失丰富的水分是我的 </div>
先看看上面这个 demo,可以看出来,对于内联元素来说,padding 和 border 对内联元素的文字对齐没有影响。(其实内联元素的 padding/border 不计算在行框盒子的高度内)
padding
border
注意:padding 不能出现负值
块级元素的 padding 的百分比值无论是水平方向和垂直方向都是相对于宽度进行计算的
内联元素的 padding 的计算规则就有一点点的差异了
<div style="width: 100px; border: 2px dashed #444"> <span style="background: #999; padding: 50% 0;">我是谁我是谁我是谁我是谁</span> </div>
<ol>|<ul> 列表内置 padding-left,但是单位不是 px,而是 em。
<ol>|<ul>
padding-left
表单元素内置的 padding
<input>、<textarea> 输入框内部内置 padding
<input>、<textarea>
<button> 按钮内置 padding
<button>
部分浏览器 <select> 下拉内置 padding
<select>
<radio>、<checkbox> 单选框和复选框无内置 padding
<radio>、<checkbox>
<div style="height: 300px; background: #ccc; margin: 20px"> <div class="circle"></div> <div class="three-line"></div> <div class="triangle"></div> </div>
.circle { width: 20px; height: 20px; padding: 5px; background: #fff; background-clip: content-box; border: 2px solid #fff; border-radius: 50%; } .three-line { width: 20px; height: 25px; border: 3px solid #fff; border-left-width: 0; border-right-width: 0; padding: 8px 0; background: #fff; background-clip: content-box; box-sizing: border-box; } .triangle { display: inline-block; background: transparent; border: 10px solid transparent; border-top-color: #333; }
先介绍几个概念术语
元素尺寸:包含 padding、borde、content 部分的尺寸,可以通过 offsetWidth、offsetHeight 获取。也被称为 “元素偏移尺寸”
padding、borde、content
offsetWidth、offsetHeight
元素内部尺寸:包含 padding 不包含 border ,也就是元素的 padding box 尺寸。通过 clientWidth、clientHeight 获取。同时也被称为 “元素可视尺寸”(不含滚动条的宽度)
padding box
clientWidth、clientHeight
元素外部尺寸:包含 padding、border、margin、content,也就是元素的 margin box 尺寸。
padding、border、margin、content
margin box
当元素设置了 width 属性或者当元素具有 “包裹性” 的时候,margin 对尺寸是没有影响的。只有当元素是 “充分利用可用空间” 的时候,margin 才可以改变元素的可视尺寸。
margin
<div style="margin-left: 100px;"> <div style="background: #ccc">123</div> </div>
同样,垂直方向也是可以的
<div style="position: relative; width: 100px; height: 100px; background: #333"> <div style="background: #ccc; position: absolute; top: 0; bottom: 0; margin-top: 30px;">123</div> </div>
上面的 demo 可以看出来,当前元素表现为 “格式化宽高” 的时候,元素自动充满父容器的宽度和高度,这个时候 margin\border\padding\content 自动分配水平和垂直方向空间。当元素表现为正常流特性的时候,和 “格式化宽度” 是一样的。
margin\border\padding\content
看看下面的几个 demo
<div style="background: #ccc; overflow: hidden"> <img src="./static/images/timg.jpg" alt="" class="right"> <div class="left">1234567890</div> </div>
.left { margin-right: 100px; } .right { float: right; width: 100px; }
<div style="background: #ccc; overflow: hidden"> <img src="./static/images/timg.jpg" alt="" class="left"> <div class="right">1234567890</div> </div>
.right { margin-left: 100px; } .left { float: left; width: 100px; }
<div style="background: #ccc; overflow: hidden"> <div class="middle"> <div class="con">1234567890</div> </div> <img src="./static/images/timg.jpg" alt="" class="left"> <img src="./static/images/timg.jpg" alt="" class="right"> </div>
.right { float: left; width: 100px; margin-left: -100px; } .left { float: left; width: 100px; margin-left: -100%; } .middle { /*margin: 0 100px;*/ float: left; width: 100%; } .con { margin: 0 100px; }
<div style="background: #ccc; overflow: hidden"> <img src="./static/images/timg.jpg" alt="" class="left"> <img src="./static/images/timg.jpg" alt="" class="right"> <div class="middle"> <div class="con">1234567890</div> </div> </div>
.right { float: right; width: 100px; } .left { float: left; width: 100px; } .middle { width: 100%; } .con { margin: 0 100px; }
注意: 这个时候当 margin 为负值的时候,容器的 width 会增加
<div style="margin-right: -30px; background: #333; text-align: right">1234567890</div>
在 CSS 世界中很多棘手的问题都是需要借助 margin 的外部尺寸特性来实现的。比方说, FireFox 浏览器下,设置了 overflow: auto/scroll 的容器会忽略 padding-bottom 值。
overflow: auto/scroll
padding-bottom
<div style="padding: 50px; background: #ccc; height: 200px; overflow: scroll;"> <img src="./static/images/timg.jpg" alt="" height="300px"> </div>
注意:如果 padding-bottom 属性的数值设置的过小,则看不出是否被忽略的效果,所以这里我设置的是 50px
那么对于上面的问题,我们可以在最后一个子元素中设置 margin-bootom 来替换就可以了。
margin-bootom
当 margin 为负值的时候,“元素尺寸” 就会变大。这个时候,如果 padding/border 是固定的数值,那么 content (这里的 width 的值为 auto)就会随着 margin 负值的增加而变大,但对于 height 来说,没有任何影响(不会影响 height 值)。
padding/border
content
auto
注意:不是定位方向的 margin 是不会对元素的定位产生影响的,只能对该元素后面相邻的元素定位产生影响。
我们这里有一个需求是:一个盒子内部需要让左右两栏的背景高度一致,取最高那部分的高度。(使用 margin 和 padding 互补)
<div style="max-height: 200px; overflow: hidden;"> <div style="float: left; width: 50%;background: #ccc; padding-bottom: 500px; margin-bottom: -500px;"> <p>1213r</p> <p>1213r</p> <p>1213r</p> <p>1213r</p> <p>1213r</p> <p>1213r</p> <p>1213r</p> <p>1213r</p> </div> <div style="float: left; width: 50%; background: #444; padding-bottom: 500px; margin-bottom: -500px;"> 456 </div> </div>
padding 和 margin 互补部分的尺寸是不会计算到布局定位中的
margin 的百分比值 和 padding 一样都是相对于父容器的 width 进行计算的
块级元素的上、下外边距有时候是会发生合并的,发生 “margin合并” 必须满足两点重要信息
相邻兄弟元素 margin 合并
父容器和第一个字元素的 margin 合并(子元素大于1个,发生 margin-top 合并)
margin-top
<div style="height: 200px; background: #444"> <div style="width: 50%; height: 50px; background: #ccc; margin-top: 100px"> </div> </div>
这个时候的 margin 会合并到父元素上,也就是说 margin-top 实际上是作用在父元素上
父容器和最后一个子元素的 margin 合并(子元素大于1个,发生 margin-bottom 合并)
margin-bottom
<div style="background: #444"> <div style="width: 50%; height: 50px; background: #ccc; margin-bottom: 100px"> </div> </div>
这个时候的 margin 会合并到父元素上,也就是说 margin-bottom 实际上是作用在父元素上。注意:这个时候父元素不能设置 height 属性
父容器只含有一个子元素的时候,且父元素没有设置 height 属性,那么 margin-top、margin-bottom 都可能与父元素发生 “margin合并”。如果设置了 height 属性,那么就不会发生 margin-bottom 的合并。注意,这里的合并最终效果都是作用在了父元素身上。
margin-top、margin-bottom
<div style="background: #444"> <div style="width: 50%; height: 50px; background: #ccc; margin: 100px"> </div> </div>
父元素设置 BFC 块级格式化上下文
父元素设置 border-top
父元素设置 padding-top
在父元素和第一个字元素之间添加一个 内联元素 进行分隔
父元素设置 height 、min-height 或者 max-height
父元素设置 border-bottom
父元素设置 padding-bottom
在父元素和最后一个字元素之间添加一个 内联元素 进行分隔
margin-top/margin-bottom
margin: auto
正常流 ** 对于 margin-left、margin-right,如果一侧定值一侧为 auto,那么 auto 为剩余空间大小
margin-left、margin-right
<div style="width: 100px; margin: 0 0 0 auto; background: #ccc">123</div> <div style="width: 100px; margin: 0 auto 0 0; background: #444">123</div>
** 对于 margin-left、margin-right,如果都为 auto,那么 平分剩余空间
<div style="width: 100px; margin: 0 auto; background: #444">123</div>
格式化宽高
** margin-left、margin-right 或者 margin-top、margin-bottom,如果一侧定值一侧为 auto,那么 auto 为剩余空间大小
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 200px; height: 200px; margin: 100px auto 0; background: #444">123</div> <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 200px; height: 200px; margin: auto auto 0; background: #444">123</div>
** 对于 margin-left、margin-right 或者 margin-top、margin-bottom,如果都为 auto,那么 auto 为剩余空间大小
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 200px; height: 200px; margin: 0 auto; background: #444">123</div> <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 200px; height: 200px; margin: auto auto; background: #444">123</div>
下面的这个案例就可以完美的解释 margin: auto
<div style="width: 300px; background: #ccc"> <div style="width: 200px; margin-left: auto; margin-right: 80px; background: #455">123</div> </div>
display 计算值为 inline 的非替换元素的 margin-top、margin-bottom。内联替换元素的垂直 margin 是有效的,并且没有 margin 合并的问题,所以图片不会发生 “margin合并”
display
inline
表格中的 <tr>、<td> 元素或者设置 display: table-cell | table-row 的元素的 margin 都是无效的
<tr>、<td>
display: table-cell | table-row
margin 合并的时候,更改 margin 值可能是没有效果的(只有当更改的那个 margin 值大于另外一个 marin 值时才会生效)。
marin
绝对定位元素非定位方位的 margin 值 “无效”。其实并不是 margin 没有生效,实际上,绝对定位元素任意方位的 margin 值无论在什么场景下都是一直有效的,比如下面的 demo 。这种情况,margin-bottom: 80px 其实增加了元素的外部尺寸。所以在元素的底部和父元素的底部间隔 80px。
margin-bottom: 80px
<div style="width: 300px; height: 100px; background: #ccc; overflow: auto; position: relative;"> <div style="position: absolute; top: 0; left: 0; height: 100px; margin-top: 100px; margin-bottom: 80px; background: #455">123</div> </div>
正常流水平方向上的 margin-right 或者 margin-bottom 都是 “无效”。对元素的定位是不起作用的。但是这种情况和上面的 demo 一样,会增加元素的外部尺寸。
margin-right
<div style="width: 300px; background: #ccc; overflow: auto;"> <div style="height: 100px; margin-top: 100px; margin-bottom: 80px; background: #455">123</div> </div>
这种情况也可以该改变。给元素设置 float: right 后,那么这个时候 right 就成了定位方向了,这个时候 margin-right 就起作用了。
float: right
right
border-width
thin - 薄薄的,等于1px;
thin
medium - 薄厚均匀,等于3px;默认值。
medium
thick - 厚厚的,等于4px
thick
border-style
none
border-color
border-style: solid
none - 无,默认值
solid - 实线边框
solid
dashed - 虚线边框
dashed
dotted - 虚点边框
dotted
doubble - 双线边框:当 border-width 小于 3px 的时候,展示的只有一条边框线。
doubble
inset - 内凹槽
inset
outset - 外凸槽
outset
groove - 沟槽
groove
ridge - 山脊
ridge
color
盒尺寸四大家族
替换元素
通过修改某个属性值呈现的内容就可以被替换的元素就被称为 “替换元素”。
<img>、<object>、<vedio>、<iframe>、<textarea>、<input>
等都是典型的替换元素替换元素除了内容可替换以外,还有哪些特性:
内容的外观不受页面上的 CSS 的影响
有自己的尺寸:在不设置尺寸的时候,这些元素会有一个默认的尺寸(300 * 150),如:
<video>、<canvas>、<iframe>
。<img>
图片默认展示的就是图片的原始尺寸。在很多 CSS 属性上有自己的一套表现规则。比较有代表性的就是
vertical-align
属性。对于字符而言,vertical-align
的默认值就是baseline
,也就是字母 “x” 的下边缘。但是,对于替换元素而言就不一样了。对于图片来说vertical-align
的默认值就是图片的下边缘。替换元素的尺寸计算规则
可以将替换元素的尺寸从内到外分为:“固有尺寸”、“HTML尺寸”、“CSS尺寸”
固有尺寸:指的就是替换内容原本的尺寸。例如,图片、视频作为一个单独的文件存在的时候,都有着自己的宽度和高度,这个宽度和高度就是“固有尺寸”
HTML尺寸:一些替换元素存在
width
和height
的HTML
属性,例如<img>
和<canvas>
元素。这个称为HTML
尺寸CSS尺寸:指的是可以通过 CSS 的
width
和height
或者max-width/min-width
和max-height/min-height
设置元素的尺寸。这种称为 CSS 尺寸计算规则
如果 ”固有尺寸“ 含有固有的宽度比例,同时仅设置了宽度或者仅设置了高度,则元素依然按照固有比例宽高显示
padding
先看看上面这个 demo,可以看出来,对于内联元素来说,
padding
和border
对内联元素的文字对齐没有影响。(其实内联元素的 padding/border 不计算在行框盒子的高度内)注意:padding 不能出现负值
padding 的百分比值
块级元素的
padding
的百分比值无论是水平方向和垂直方向都是相对于宽度进行计算的内联元素的
padding
的计算规则就有一点点的差异了HTML标签内置的 padding
<ol>|<ul>
列表内置padding-left
,但是单位不是 px,而是 em。表单元素内置的
padding
<input>、<textarea>
输入框内部内置padding
<button>
按钮内置padding
部分浏览器
<select>
下拉内置padding
<radio>、<checkbox>
单选框和复选框无内置padding
同背景属性结合绘制特殊的图形
margin 与元素尺寸以及相关布局
先介绍几个概念术语
元素尺寸:包含
padding、borde、content
部分的尺寸,可以通过offsetWidth、offsetHeight
获取。也被称为 “元素偏移尺寸”元素内部尺寸:包含
padding
不包含border
,也就是元素的padding box
尺寸。通过clientWidth、clientHeight
获取。同时也被称为 “元素可视尺寸”(不含滚动条的宽度)元素外部尺寸:包含
padding、border、margin、content
,也就是元素的margin box
尺寸。margin 与元素的内部尺寸
当元素设置了
width
属性或者当元素具有 “包裹性” 的时候,margin
对尺寸是没有影响的。只有当元素是 “充分利用可用空间” 的时候,margin
才可以改变元素的可视尺寸。同样,垂直方向也是可以的
上面的 demo 可以看出来,当前元素表现为 “格式化宽高” 的时候,元素自动充满父容器的宽度和高度,这个时候
margin\border\padding\content
自动分配水平和垂直方向空间。当元素表现为正常流特性的时候,和 “格式化宽度” 是一样的。看看下面的几个 demo
注意: 这个时候当
margin
为负值的时候,容器的width
会增加margin 与元素的外部尺寸
在 CSS 世界中很多棘手的问题都是需要借助
margin
的外部尺寸特性来实现的。比方说, FireFox 浏览器下,设置了overflow: auto/scroll
的容器会忽略padding-bottom
值。注意:如果
padding-bottom
属性的数值设置的过小,则看不出是否被忽略的效果,所以这里我设置的是 50px那么对于上面的问题,我们可以在最后一个子元素中设置
margin-bootom
来替换就可以了。margin 和 padding 之间的相互作用
当
margin
为负值的时候,“元素尺寸” 就会变大。这个时候,如果padding/border
是固定的数值,那么content
(这里的width
的值为auto
)就会随着margin
负值的增加而变大,但对于height
来说,没有任何影响(不会影响height
值)。注意:不是定位方向的
margin
是不会对元素的定位产生影响的,只能对该元素后面相邻的元素定位产生影响。我们这里有一个需求是:一个盒子内部需要让左右两栏的背景高度一致,取最高那部分的高度。(使用 margin 和 padding 互补)
padding
和margin
互补部分的尺寸是不会计算到布局定位中的margin
的百分比值 和padding
一样都是相对于父容器的width
进行计算的margin 的合并
块级元素的上、下外边距有时候是会发生合并的,发生 “margin合并” 必须满足两点重要信息
哪些场景会发生合并:
相邻兄弟元素
margin
合并父容器和第一个字元素的
margin
合并(子元素大于1个,发生margin-top
合并)这个时候的
margin
会合并到父元素上,也就是说margin-top
实际上是作用在父元素上父容器和最后一个子元素的
margin
合并(子元素大于1个,发生margin-bottom
合并)这个时候的
margin
会合并到父元素上,也就是说margin-bottom
实际上是作用在父元素上。注意:这个时候父元素不能设置height
属性父容器只含有一个子元素的时候,且父元素没有设置
height
属性,那么margin-top、margin-bottom
都可能与父元素发生 “margin合并”。如果设置了height
属性,那么就不会发生margin-bottom
的合并。注意,这里的合并最终效果都是作用在了父元素身上。如何消除 margin-top 合并
父元素设置 BFC 块级格式化上下文
父元素设置 border-top
父元素设置 padding-top
在父元素和第一个字元素之间添加一个 内联元素 进行分隔
如何消除 margin-bottom 合并
父元素设置 BFC 块级格式化上下文
父元素设置 height 、min-height 或者 max-height
父元素设置 border-bottom
父元素设置 padding-bottom
在父元素和最后一个字元素之间添加一个 内联元素 进行分隔
如果一个元素是一个空元素(没有任何内容),那么如果同时设置了
margin-top
和margin-bottom
。那么这个时候margin-top
和margin-bottom
是会发生合并的。所以实际定位时只计算一个margin-top/margin-bottom
的值(谁的值大取谁)。如何消除这种情况的margin
合并margin 合并的计算规则:
margin
都是正值,那么取最大的那个margin
一正一负,那么取正负相加后的值margin
都是负值,那么取最负的那个margin: auto
作用机制正常流 ** 对于
margin-left、margin-right
,如果一侧定值一侧为auto
,那么auto
为剩余空间大小** 对于
margin-left、margin-right
,如果都为auto
,那么 平分剩余空间格式化宽高
**
margin-left、margin-right
或者margin-top、margin-bottom
,如果一侧定值一侧为auto
,那么auto
为剩余空间大小** 对于
margin-left、margin-right
或者margin-top、margin-bottom
,如果都为auto
,那么auto
为剩余空间大小下面的这个案例就可以完美的解释
margin: auto
什么情况下设置的
margin
无效display
计算值为inline
的非替换元素的margin-top、margin-bottom
。内联替换元素的垂直margin
是有效的,并且没有margin
合并的问题,所以图片不会发生 “margin合并”表格中的
<tr>、<td>
元素或者设置display: table-cell | table-row
的元素的margin
都是无效的margin
合并的时候,更改margin
值可能是没有效果的(只有当更改的那个margin
值大于另外一个marin
值时才会生效)。绝对定位元素非定位方位的
margin
值 “无效”。其实并不是margin
没有生效,实际上,绝对定位元素任意方位的margin
值无论在什么场景下都是一直有效的,比如下面的 demo 。这种情况,margin-bottom: 80px
其实增加了元素的外部尺寸。所以在元素的底部和父元素的底部间隔 80px。正常流水平方向上的
margin-right
或者margin-bottom
都是 “无效”。对元素的定位是不起作用的。但是这种情况和上面的 demo 一样,会增加元素的外部尺寸。这种情况也可以该改变。给元素设置
float: right
后,那么这个时候right
就成了定位方向了,这个时候margin-right
就起作用了。border
border-width
thin
- 薄薄的,等于1px;medium
- 薄厚均匀,等于3px;默认值。thick
- 厚厚的,等于4pxborder-style
默认值就是none
。所以当我们设置border-width
和border-color
没有显示边框的原因。但是当我们只设置border-style: solid
就会出现边框。none
- 无,默认值solid
- 实线边框dashed
- 虚线边框dotted
- 虚点边框doubble
- 双线边框:当border-width
小于 3px 的时候,展示的只有一条边框线。inset
- 内凹槽outset
- 外凸槽groove
- 沟槽ridge
- 山脊border-color
有一个很重要的特性就是border-color
的默认值就是color
色值。当没有设置border-color
颜色值的时候,会使用当前元素的 `color 计算值作为边框色。