垂直外边距合并--CSS的Margin属性:详解margin属性
你真的了解margin吗?你知道margin有什么特性吗?你知道什么是垂直外边距合并?margin在块元素、内联元素中的区别?什么时候该⽤padding⽽不是margin?你知道负margin吗?你知道负margin在实际⼯作中的⽤途吗?常见的浏览器下margin出现的bug有哪些?……
写css,你少不了与margin打交道,⽽对于这个平时我们最常⽤的css属性我们并⾮⼗分了解。介于此我打算写下这篇⽂章,⼀来是⾃⼰⼯作中的总结,也是对⾃⼰知识的⼀次梳理。
Margin是什么
CSS 边距属性定义元素周围的空间。通过使⽤单独的属性,可以对上、右、下、左的外边距进⾏设置。也可以使⽤简写的外边距属性同时改变所有的外边距。——W3School
边界,元素周围⽣成额外的空⽩区。“空⽩区”通常是指其他元素不能出现且⽗元素背景可见的区域。——CSS权威指南
我⽐较喜欢使⽤“外边距”这个词来解释margin(同理padding可以称之为“内边距”,但是我⼜恰恰喜欢称呼padding为“补⽩”或者“留⽩”),我们可以很清楚的了解到margin的最基本⽤途就是控制元素周围空间的间隔,从视觉⾓度上达到相互隔开的⽬的。
Margin的特性
margin始终是透明的。
margin通过使⽤单独的属性,可以对上、右、下、左的外边距进⾏设置。即:margin-top、margin-right、margin-bottom、margin-left。
外边距的 margin-width 的值类型有:auto | length | percentage
也可以使⽤简写的外边距属性同时改变所有的外边距:margin: top right bottom left;(eg: margin:10px 20px 30px 40px) 记忆⽅式是元素周围正上⽅顺时针“上右下左”记忆。
并且规范还提供了省略的数值写法,基本如下:
1、如果margin只有⼀个值,表⽰上右下左的margin同为这个值。例如:margin:10px; 就等于 margin:10px 10px 10px 10px;
2、如果 margin 只有两个值,第⼀个值表⽰上下margin值,第⼆个值为左右margin的值。例如:margin:10px 20px; 就等于 margin:10px 20px 10px 20px;
3、如果margin有三个值,第⼀个值表⽰上margin值,第⼆个值表⽰左右margin的值,第三个值表⽰下margin的值。例如:margin:10px
20px 30px; 就等于 margin:10px 20px 30px 20px;
4、如果margin有四个值,那这四个值分别对应上右下左这四个margin值。例如:margin:10px 20px 30px 40px;
在实际应⽤中,个⼈不推荐使⽤三个值的margin,⼀是容易记错,⼆是不容易⽇后修改,⼀开始如果写成margin:10px 20px 30px;⽇后需求改动为上10px,右30px,下30px,左20px,你不得不还是得把这个margin拆开为margin:10px 30px 30px 20px;费⼒且不讨好,不如⼀开始就⽼⽼实实的写成margin:10px 20px 30px 20px;来的实在,不要为了现在节省俩个字节⽽让⽇后再次开发的成本上升。
垂直外边距合并问题
别被上⾯这个名词给吓倒了,简单地说,外边距合并指的是,当两个垂直外边距相遇时,它们将形成⼀个外边距。合并后的外边距的⾼度等于两个发⽣合并的外边距的⾼度中的较⼤者。你可以查看CSS外边距合并了解这个基本知识。
实际⼯作中,垂直外边距合并问题常见于第⼀个⼦元素的margin-top会顶开⽗元素与⽗元素相邻元素的间距,⽽且只在标准浏览器下(FirfFox、Chrome、Opera、Sarfi)产⽣问题,IE下反⽽表现良好。例⼦可以查看下⾯代码(IE下表现“正常”,标准浏览器下查看出现“bug”):
<html xmlns="/1999/xhtml">
<head>
<title>垂直外边距合并</title>
<style>
.top{width:160px; height:50px; background:#ccf;}
.middle{width:160px; background:#cfc;}
.middle .firstChild{margin-top:20px;}
</style>
</head>
<body>
<div class="top"></div>
<div class="middle">
<div class="firstChild">我其实只是想和我的⽗元素隔开点距离。</div> <div class="secondChild"></div>
</div>
</body>
</html>
如果按照CSS规范,IE的“良好表现”其实是⼀个错误的表现,因为IE的hasLayout渲染导致了这个“表现良好”的外观。⽽其他标准浏览器则会表现出“有问题”的外观。好了,如果你读过了上⾯W3Shcool的CSS外边距合并的⽂章后,就很容易讨论这个问题了。这个问题发⽣的原因是根据规范,⼀个盒⼦如果没有上补⽩(padding-top)和上边框(border-top),那么这个盒⼦的上边距会和其内部⽂档流中的第⼀个⼦元素的上边距重叠。
再说了⽩点就是:⽗元素的第⼀个⼦元素的上边距margin-top如果碰不到有效的border或者padding.就会不断⼀层⼀层的⾃⼰“领导”(⽗元素,祖先元素)的⿇烦。只要给领导设置个有效的 border或者padding就可以有效的管制这个⽬⽆领导的margin防⽌它越级,假传圣旨,把⾃⼰的margin当领导的margin执⾏。
对于垂直外边距合并的解决⽅案上⾯已经解释了,为⽗元素例⼦中的middle元素增加⼀个border-top或者padding-top即可解决这个问题。
⼀般说来这个问题解释到这⾥,⼤多数⽂章就不会再深⼊下去了,但作为⼀名实战开发者,最求的是知其然知其所以然,原本使⽤margin-top就是为了与⽗元素隔开距离,⽽按照你这么⼀个解法,其实是⼀种“修复”,为了“弥补修复”这个⽗⼦垂直外边距合并这个CSS规范“Bug”,⽽强制在⽗元素上使⽤border-top和padding-top,不舒服,也不容易记住,下次再发⽣这样的情况还是会忘记这条准则,⽽且在页⾯设计稿⾥如果不需要border-top加个上边框,这么⼀加反⽽画蛇添⾜,为以后修改留下隐患。
为什么⼀定要⽤border-top,padding-top去为了这么⼀个所谓的标准规范⽽多写这么⼀⾏代码呢?答案你可以参考另外⼀篇⽂章⽤Margin还是⽤Padding⾥到答案。
⽤Margin还是⽤Padding
何时应当使⽤margin:
需要在border外侧添加空⽩时。
空⽩处不需要背景(⾊)时。
上下相连的两个盒⼦之间的空⽩,需要相互抵消时。如15px + 20px的margin,将得到20px的空⽩。
何时应当时⽤padding:
需要在border内测添加空⽩时。
空⽩处需要背景(⾊)时。
上下相连的两个盒⼦之间的空⽩,希望等于两者之和时。如15px + 20px的padding,将得到35px的空⽩。
个⼈认为:margin是⽤来隔开元素与元素的间距;padding是⽤来隔开元素与内容的间隔。margin⽤于布局分开元素使元素与元素互不相⼲;padding⽤于元素与内容之间的间隔,让内容(⽂字)与(包裹)元素之间有⼀段“呼吸距离”。
这⾥我截取了部分另外⼀篇⽂章的内容,详细内容请见⽤Margin还是⽤Padding
margin在块元素、内联元素中的区别
HTML(这⾥说的是html标准,⽽不是xhtml)⾥分两种基本元素,即block和inline。顾名思义,block元素就是以”块”表现的元素(block-like elements),inline元素即是以”⾏”表现的元素(character level elements and text strings)。⼆者表现的主要差别在于,在页⾯⽂档中block 元素另起⼀⾏开始,并独占⼀⾏。inline元素则同其他inline元素共处⼀⾏。
block元素(块元素)⼤致有:P|H1|H2|H3|H4|H5|H6|UL|OL|PRE| DL | DIV | NOSCRIPT | BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS(随着html5标准的推进,⼀些元素将被废除,⽽⼀些新的元素将被引⼊)注意的是并⾮所有的block元素的默认display 属性都是block,像table这种display:table的元素也是block元素。
inline元素(内联元素)⼤致有:#PCDATA(即⽂本)| TT | I | B | BIG | SMALL|EM | STRONG | DFN | CODE |SAMP | KBD | VAR | CITE | ABBR | ACRONYM|A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO|INPUT | SELECT | TEXTAREA | LABEL | BUTTON
其中有类特殊的元素:如img|input|select|textarea|button|label等,他们被称为可置换元素(Replaced element)。他们区别⼀般inline元素(相对⽽⾔,称non-replaced element)是:这些元素拥有内在尺⼨(intrinsic dimensions),他们可以设置width/height属性。他们的性质同设置了display:inline-block的
元素⼀致。
或许有朋友对⾮置换元素(non-replaced element)有点疑惑,稍微帮助⼤家理解⼀下。⾮置换元素,W3C 中没有给出明确的定义,但我们从字⾯可以理解到,⾮置换元素对应着置换元素(replaced element),也就是说我们搞懂了置换元素的含义,就懂了⾮置换元素。置换元素,W3C中给出了定义:
“An element that is outside the scope of the CSS formatter, such as an image, embedded document, or applet”
从定义中我们可以理解到,置换元素(replaced element)主要是指 img, input, textarea, select, object 等这类默认就有 CSS 格式化外表范围的元素。进⽽可知,⾮置换元素(non-replaced element)就是除了 img, input, textarea, select, object 等置换元素以外的元素。
margin在块级元素下,他的性能可以完全体现,上下左右任你设定。且记住块级元素的margin的参照基准是前⼀个元素即相对于⾃⾝之前的元素有margin距离。如果元素是第⼀个元素,则就是相对于⽗元素的margin距离(但第⼀个元素相对于⽗元素margin-top⽽⽗元素⼜没有设定padding-top/border-top的话要需要印证上⾯的垂直外边距合并的知识)
margin也能⽤于内联元素,这是规范所允许的,但是margin-top和margin-bottom对内联元素(对⾏)的⾼度没有影响,并且由于边界效果(margin效果)是透明的,他也没有任何的视觉影响。
这是因为边界应⽤于内联元素时不改变元素的⾏⾼度,如果你要改变内联元素的⾏⾼即类似⽂本的⾏间距,那么你只能使⽤这三个属性:line-height,fong-size,vertical-align。请记住,这个影响内联元素⾼度的是line-height⽽不是height,因为内联元素是⼀⾏⾏的,定⼀个height的话,那这到底是整段inline元素的⾼呢?还是inline元素⼀⾏的⾼呢?这都说不准,所以统⼀都给每⾏定⼀个⾼,只能是line-height 了。
margin-top/margin-bottom对内联元素没有多⼤实际效果,不过margin-left/margin-right还是能够对内联元素产⽣影响的。应⽤margin:10px 20px 30px 40px;,左边这个css如果写在inline元素上,他的效果⼤致是,上下⽆效果,左边离他相邻元素或者⽂本距离为40px,右边离他相邻元素或者⽂本距离为20px。你可以⾃⾏尝试⼀番。
最后在内联元素中还有上⽂我们提到的⾮可置换inline元素(non-replaced element),这些个元素img|input|select|textarea|button|label 虽然是内联元素,但margin依旧可以影响到他的上下左右!
总结下来margin 属性可以应⽤于⼏乎所有的元素,除了表格显⽰类型(不包括 table-caption, table and inline-table)的元素,⽽且垂直外边距对⾮置换内联元素(non-replaced inline element)不起作
⽤。
负margin技术及其应⽤
在margin所有的实际应⽤中,负margin技术是我学习css路上最重要⼀课之⼀,许多⾼级应⽤和页⾯上的疑难杂症都可以⽤负margin技术来实现。margin技术是那么的有⽤,限于篇幅我⼜不想草草了事,所以我决定专门为他写⼀篇⽂章,详细的说明他的效果、原理、及其应⽤。
常见的浏览器下margin出现的bug
林林总总写了那么多,最后总结⼀些浏览器中常见的margin Bug吧,以后遇到margin下的布局问题可以查看这⾥到解决的⽅案,如果你还发现其他关于浏览器下margin的Bug你可以发表留⾔,核对采纳后我会及时添加进去,感谢你的分享:
IE6中双边距Bug:
发⽣场合:当给⽗元素内第⼀个浮动元素设置margin-left(元素float:left)或margin-right(元素float:right)时margin加倍。
解决⽅法:是给浮动元素加上display:inline;CSS属性;或者⽤padding-left代替margin-left。
原理分析:块级对象默认的display属性值是block,当设置了浮动的同时,还设置了它的外边距就会出现这种情况。也许你会问:“为什么之后的对象和第⼀个对象之间就不存在双倍边距的Bug”?因为浮动都有其相对应的对象,只有相对于其⽗对象的浮动对象才会出现这样的问题。第⼀个对象是相对⽗对象的,⽽之后对象是相对第⼀个对象的,所以之后对象在设置后不会出现问题。为什么display:inline可以解决这个双边距bug,⾸先是inline元素或inline-block元素是不存在双边距问题的。然后,float:left等浮动属性可以让inline元素haslayout,会让inline元素表现得跟inline-block元素的特性⼀样,⽀持⾼宽,垂直margin和padding等,所以div class的所有样式可以⽤在这个display inline 的元素上。
IE6中浮动元素3px间隔Bug:
发⽣场合:发⽣在⼀个元素浮动,然后⼀个不浮动的元素⾃然上浮与之靠近会出现的3px的bug。
解决⽅法:右边元素也⼀起浮动;或者为右边元素添加IE6 Hack _margin-left:-3px;从⽽消除3px间距。
原理分析:IE6浏览器缺陷Bug。
IE6/7负margin隐藏Bug:
发⽣场合:当给⼀个有hasLayout的⽗元素内的⾮hasLayout元素设置负margin时,超出⽗元素部分不
可见。
解决⽅法:去掉⽗元素的hasLayout;或者赋hasLayout给⼦元素,并添加position:relative;
解决⽅法:去掉⽗元素的hasLayout;或者赋hasLayout给⼦元素,并添加position:relative;
padding是外边距还是内边距原理分析:IE6/7独有的hasLayout产⽣问题。
IE6/7下ul/ol标记消失bug:
发⽣场合:当ul/ol触发了haslayout并且是在ul/ol上写margin-left,前⾯默认的ul/ol标记会消失。
解决⽅法:给li设置margin-left,⽽不是给ul/ol设置margin-left。
原理分析:IE6/7浏览器Bug
IE6/7下margin与absolute元素重叠bug:
发⽣场合:双栏⾃适应布局中,左侧元素absolute绝对定位,右侧的margin撑开距离定位。在IE6/7下左侧应⽤了absolute属性的块级元素与右边的⾃适应的⽂字内容重叠。
解决⽅法:把左侧块级元素更改为内联元素,⽐如把div更换为span。
原理分析:这是由于IE6/IE7浏览器将inline⽔平标签元素和block⽔平的标签元素没有加以区分⼀视同仁渲染了。属于IE6/7浏览器渲染Bug。
IE6/7/8下auto margin居中bug:
发⽣场合:给block元素设置margin auto⽆法居中
解决⽅法:出现这种bug的原因通常是没有Doctype,然后触发了ie的quirks mode,加上Doctype声明就可以了。在《打败IE的葵花宝典》⾥给出的⽅法是给block元素添加⼀个width能够解决,但根据本⼈亲测,加with此种⽅法是⽆效的,如果没有Doctype即使给元素添加width也⽆法让block元素居中。
原理分析:缺少Doctype声明。
IE8下input[button | submit] 设置margin:auto⽆法居中
发⽣场合:ie8下,如果给像button这样的标签(如button input[type="button"] input[type="submit"])设置{ display: block; margin:0 auto; }如果不设置宽度的话⽆法居中。
解决⽅法:可以给为input加上宽度
原理分析:IE8浏览器Bug。
IE8百分⽐padding垂直margin bug:
发⽣场合:当⽗元素设置了百分⽐的padding,⼦元素有垂直的margin的时候,就好像⽗元素被设置了margin⼀样。
解决⽅法:给⽗元素加⼀个overflow:hidden/auto。
原理分析:IE8浏览器Bug。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论