普通流(Normal Flow)javascript
在普通流中,元素按照其在 HTML 中的前后位置至上而下布局,在这个过程当中,行内元素水平排列,直到当行被占满而后换行,块级元素则会被渲染为完整的一个新行, 除非另外指定,不然全部元素默认都是普通流定位,也能够说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
浮动 (Floats)css
在浮动布局中,元素首先按照普通流的位置出现,而后根据浮动的方向尽量的向左边或右边偏移,其效果与印刷排版中的文本环绕类似。
绝对定位 (Absolute Positioning)html
在绝对定位布局中,元素会总体脱离普通流,所以绝对定位元素不会对其兄弟元素形成影响(若是看了上文的童鞋,会发现这点与浮动元素会影响兄弟元素是不一样的),而元素具体的位置由绝对定位的坐标决定。
BFC 正是属于普通流的,所以它对兄弟元素也不会形成什么影响。java
块格式化上下文(block formatting context) 是页面 CSS 视觉渲染的一部分。它是用于决定块盒子的布局及浮动相互影响的一个区域。 --MDN 块格式上下文segmentfault
个人理解是,BFC是一个环境,在这个环境中的元素不会影响到其余环境中的布局,也就是说,处于不一样BFC中的元素是不会互相干扰的。浏览器
根元素或其它包含它的元素ide
浮动元素,float除none之外的值布局
绝对定位元素 (元素的 position 为 absolute 或 fixed)学习
display为如下其中之一的值:inline-block,table-cell,table-captionflex
overflow 的值不为 visible的元素
弹性盒子 flex boxes (元素的 display: flex 或 inline-flex)
其中,最多见的就是overflow:hidden、float:left/right、position:absolute。也就是说,每次看到这些属性的时候,就表明了该元素以及建立了一个BFC了。
内部的盒会在垂直方向一个接一个排列(能够看做BFC中有一个的常规流);
处于同一个BFC中的元素相互影响,可能会发生margin collapse;
每一个元素的margin box的左边,与容器块border box的左边相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此;
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
计算BFC的高度时,考虑BFC所包含的全部元素,连浮动元素也参与计算;
浮动盒区域不叠加到BFC上;
阻止外边距折叠
两个相连的块级元素在垂直上的外边距会发生叠加,有些把这种状况看做是bug,但我以为多是出于段落排版的考虑,为了令行间距一致才有的这一特性。咱们先来看看例子:
<p>first</p> <p>second</p>
*{margin: 0px;padding: 0px} p { color: red; background: #eee; width: 100px; height: 100px; line-height: 100px; text-align: center; margin: 10px; border: solid 1px red; }
从上面能够看出,咱们给两个p元素都设置margin
,但中间的间距却发生了折叠。而后举个BFC的例子:
.ele{ overflow: hidden; border: solid 1px red; }
<div class="ele"> <p>first</p> </div> <div class="ele"> <p>second</p> </div>
从上面能够看出,咱们为每一个div元素设置overflow
的值为hidden
,产生一个块级格式上下文,由于外边距不会相互重叠。
BFC能够包含浮动的元素
//html <div class = "box"> <div class= "floatL">float</div> <div class= "floatL">float</div> </div> <br style="clear:both"> <div class = "box BFC"> <div class= "floatL">float</div> <div class= "floatL">float</div> </div>
*{margin: 0px;padding: 0px} .floatL{ float: left; width: 100px; height: 100px; background-color: red; text-align: center; line-height: 100px; } .box{ border: 1px solid red; width: 300px; margin: 100px; padding: 20px; } .BFC{ overflow: hidden; *zoom: 1; }
从运行结果能够看出,若是块级元素里面包含着浮动元素会发生高度塌陷,可是将它变成一个BFC后,BFC在计算高度时会自动将浮动元素计算在内。
BFC能够阻止元素被浮动元素覆盖
<div class="box1">box1</div> <div class="box2">box2</div>
*{margin: 0px; padding: 0px} .box1{ width: 100px; height: 100px; line-height: 100px; text-align: center; background-color: rgba(0, 0, 255, 0.5); border: 1px solid #000; float: left; } .box2{ width: 200px; height: 200px; line-height: 100px; text-align: center; background-color: rgba(255, 0, 0, 0.5); border: 1px solid #000; /* overflow: hidden; */ /* *zoom: 1; */ }
从上面看出,当元素浮动后,会与后面的块级元素产生相互覆盖。那怎么解决这个问题,只要为后面的元素建立一个BFC。添加overflow
属性到box2
上。
overflow: hidden; *zoom: 1;
这样子阻止了浮动元素重叠的问题。
hasLayout
除了使用 overflow: hidden
触发 BFC 外,还使用了一个 *zomm: 1
的属性,这是 IEhack ,由于 IE6-7 并不支持 W3C 的 BFC ,而是使用私有属性 hasLayout
。从表现上来讲,hasLayout
跟 BFC 很类似,只是 hasLayout
自身存在不少问题,致使了 IE6-7 中一系列的 bug 。触发 hasLayout 的条件与触发 BFC 有些类似,推荐为元素设置 IE 特有的 CSS 属性 zoom: 1
触发 hasLayout
,zoom
用于设置或检索元素的缩放比例,值为“1”即便用元素的实际尺寸,使用 zoom: 1
既能够触发 hasLayout 又不会对元素形成其余影响,相对来讲会更为方便。
拓展阅读:
Block formatting context(块级格式化上下文)
经典的清除浮动:
//利用伪元素清除浮动 .clearfix:after { content:"."; display:block; height:0; visibility:hidden; clear:both; } .clearfix { *zoom:1; }
拓展阅读:
那些年一块儿清除过的浮动
各类各样的布局,无非就是用了浮动 float,负边距,相对定位,经过这三者的巧妙组合跟拼凑来实现的。用好这些,布局就会很简单。
还没学会布局时,就听到有圣杯布局和双飞翼布局,这布局都有这么风骚的名字,就以为很酷,事实也如此,了解了圣杯布局和双飞翼布局,才发现挺深奥的。
传统的布局中,当咱们须要改变两栏的互换,就会很麻烦。由于还要涉及到 HTML 代码的修改,不能彻底从 CSS 上更改,这叫 HTML 和 CSS 的耦合。而圣杯布局跟双飞翼布局就是可以不考虑主体的位置,可以只经过 CSS 代码就改变相应的布局,这也是优势之一。
试试这样的HTML结构:
<div class="header">header</div> <div class="container"> <div class="main">main</div> <div class="sub">sub</div> <div class="extra">extra</div> </div> <div class="footer">footer</div>
给它加上CSS样式:
body{ margin: 0; padding: 0; font-size: 1.5em; font-weight: bold; min-width: 500px;} .header,.footer{ text-align: center;} .header{ height: 50px; background-color: #76ffff;} .footer{ height: 50px; background-color: #ff7676;} .main{ background-color: #666;} .sub{ background-color: #44fa44;} .extra{ background-color: #3dbdff;} /*start*/ .main{ width: 100%; float: left; } .sub{ width: 100px; float: left; margin-left: -100%; } .extra{ width: 200px; float: left; margin-left: -200px; } .container{ overflow: hidden; }
结果以下:
会发现,main的位置不正确,因此再给container
加上 padding: 0 200px 0 100px
;
虽然 main 的位置正确了,但是 sub 和 extra 位置优势不对,因此咱们再用上相对定位,为 sub
和 extra
加上以下代码:
.sub{ position: relative;; left: -100px; } .extra{ position: relative; right: -200px; }
效果就出来了,
噢耶,这就是圣杯布局。若是在圣杯布局的基础上,给它一个多余的标签,把 mian 包起来,这就是双飞翼布局。
HTML结构:
<div class="header">header</div> <div class="container"> <div class="main"> <div class="main-wrap">main</div> </div> <div class="sub">sub</div> <div class="extra">extra</div> </div> <div class="footer">footer</div>
CSS结构:
body{ margin: 0; padding: 0; font-size: 1.5em; font-weight: bold; min-width: 500px;} .header,.footer{ text-align: center;} .header{ height: 50px; background-color: #76ffff;} .footer{ height: 50px; background-color: #ff7676;} .main{ background-color: #666;} .sub{ background-color: #44fa44;} .extra{ background-color: #3dbdff;} /*start*/ .main{ width: 100%; height: 100px; float: left; } .sub{ width: 100px; height: 100px; float: left; margin-left: -100%; } .extra{ width: 200px; height: 100px; float: left; margin-left: -200px; } .main-wrap{ margin: 0 200px 0 100px; } .container{ height: 100px; overflow: hidden; *zoom: 1; }
能够看到,只要为包住 main-wrap 设置 margin,连相对定位都没用到,效果就出来了。
若是把三栏布局比做一只大鸟,能够把main当作是鸟的身体,sub和extra则是鸟的翅膀。这个布局的实现思路是,先把最重要的身体部分放好,而后再将翅膀移动到适当的地方。所以请允许我给这个布局实现取名为双飞翼布局(Flying Swing Layout).
就如上图中的鸟有各类姿式同样,利用双飞翼布局,咱们也能够实现各类布局。这里有个尝试页面,利用双飞翼,实现了一套栅格化布局系统。
优势:
实现了内容与布局的分离,这是渐进式加强布局的思想,从内容出发,不考虑布局。
main部分是自适应宽度的,很容易在定宽布局和流体布局中切换。
任何一栏均可以是最高栏,不会出问题。
须要的hack很是少(就一个针对ie6的清除浮动hack:_zoom: 1;)
在浏览器上的兼容性很是好,IE5.5以上都支持。
缺点:
main须要一个额外的包裹层。
normalize 的理念则是尽可能保留浏览器的默认样式,不进行太多的重置。
reset 的目的,是将全部的浏览器的自带样式重置掉,这样更易于保持各浏览器渲染的一致性。
/* reset */ html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;} header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;} table{border-collapse:collapse;border-spacing:0;} caption,th{text-align:left;font-weight:normal;} html,body,fieldset,img,iframe,abbr{border:0;} i,cite,em,var,address,dfn{font-style:normal;} [hidefocus],summary{outline:0;} li{list-style:none;} h1,h2,h3,h4,h5,h6,small{font-size:100%;} sup,sub{font-size:83%;} pre,code,kbd,samp{font-family:inherit;} q:before,q:after{content:none;} textarea{overflow:auto;resize:none;} label,summary{cursor:default;} a,button{cursor:pointer;} h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:bold;} del,ins,u,s,a,a:hover{text-decoration:none;} body,textarea,input,button,select,keygen,legend{font:12px/1.14 arial,\5b8b\4f53;color:#333;outline:0;} body{background:#fff;} a,a:hover{color:#333;}
以上reset来自NEC的css reset。
拓展阅读:
Normalize.css 和 Reset CSS 有什么本质区别?
IE条件注释是一种特殊的HTML注释,这种注释只有IE5.0及以上版本才能理解。好比普通的HTML注释是:
<!--This is a comment--> 而只有IE可读的IE条件注释是: <!--[if IE]> <![endif]--> “非IE条件注释”: <!--[if !IE]>--> non-IE HTML Code <!--<![endif]--> “非特定版本IE条件注释”(不多用到): <!--[if ! lt IE 7]> <![IGNORE[--><![IGNORE[]]> Code for browsers that match the if condition <!--<![endif]-->
简而言之,除了“Windows上的IE”以外的全部浏览器都会认为条件注释只是一段普通的HTML注释。你不能在CSS代码中使用条件注释。IE条件注释是颇有用的对IE隐藏或者展示特定代码的方法,比起在CSS中用诡异的_/制造bug,利用IE条件注释来写CSS “hacks”是更合理的方法。通俗点,条件注释就是一些if判断,但这些判断不是在脚本里执行的,而是直接在html代码里执行的。
条件注释的基本结构和HTML的注释(<!– –>)是同样的。所以IE之外的浏览器将会把它们看做是普通的注释而彻底忽略它们。
IE将会根据if条件来判断是否如解析普通的页面内容同样解析条件注释里的内容。
条件注释使用的是HTML的注释结构,所以他们只能使用在HTML文件里,而不能在CSS文件中使用。
从语法上看这是至关合法的普通HTML注释。任何浏览器都会认为<!–和–>之间的部分是注释从而忽略它。可是IE也会看到其中[if IE]>,从而开始解释接下来的代码直到遇到<![endif]。因此,下面这些代码不会显示在任何其余浏览器中面。
经过“比较操做符”能够更灵活地对IE版本进行控制,用法是在IE前面加上“比较操做符”。合法的操做符以下:
lte:就是Less than or equal to的简写,也就是小于或等于的意思。
lt :就是Less than的简写,也就是小于的意思。
gte:就是Greater than or equal to的简写,也就是大于或等于的意思。
gt :就是Greater than的简写,也就是大于的意思。
! :就是不等于的意思,跟javascript里的不等于判断符相同
<!–[if gt IE 5.5]> / 若是IE版本大于5.5 / <!–[if lte IE 6]> / 若是IE版本小于等于6 / <!–[if !IE]> / 若是浏览器不是IE /
经常使用的IE条件注释
<!--[if !IE]>除IE外均可识别<![endif]--> <!--[if IE]> 全部的IE可识别 <![endif]--> <!--[if IE 5.0]> 只有IE5.0能够识别 <![endif]--> <!--[if IE 5]> 仅IE5.0与IE5.5能够识别 <![endif]--> <!--[if gt IE 5.0]> IE5.0以及IE5.0以上版本均可以识别 <![endif]--> <!--[if IE 6]> 仅IE6可识别 <![endif]--> <!--[if lt IE 6]> IE6以及IE6如下版本可识别 <![endif]--> <!--[if gte IE 6]> IE6以及IE6以上版本可识别 <![endif]--> <!--[if IE 7]> 仅IE7可识别 <![endif]--> <!--[if lt IE 7]> IE7以及IE7如下版本可识别 <![endif]--> <!--[if gte IE 7]> IE7以及IE7以上版本可识别 <![endif]-->
要实现行内元素的水平居中,只需把行内元素包裹在块级父层元(<div>、<li>、<p>
等)中,而且在父层元素CSS设置以下:
.container{ text-align: center; }
要实现块状元素(display:block)的水平居中,咱们只须要将它的左右外边距margin-left和margin-right设置为auto,便可实现块状元素的居中,要水平居中的块状元素CSS设置以下:
.container{ margin: 0 auto; }
利用绝对定位,将元素的top和left属性都设为50%,再利用margin边距,将元素回拉它自己高宽的一半,实现垂直居中。核心CSS代码以下:
.container{ position: relative; } .center{ position: absolute; left: 50%; top: 50%; margin: -50px 0 0 -50px; }
.container{ position: relative; } .center{ position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto; }
inline
或者inline-block
元素能够巧妙的将父级容器设置为display:table-cell
,配合text-align:center
和vertical-align:middle
便可以实现水平垂直居中。
.container{ width: 600px; height: 600px; background: #eee; display: table-cell; text-align: center; vertical-align: middle; } .center{ background: blue; }
利用C3的transform,能够轻松的在未知元素的高宽的状况下实现元素的垂直居中。
.container{ width: 100%; height: 400px; background: #eee; position: relative; } .center{ background: blue; position:absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
使用flex布局,无需绝对定位等改变布局的操做,能够轻松实现元素的水平垂直居中。
.container{ width: 100%; height: 400px; background: #eee; /* flex 布局解决水平居中 */ display: flex; justify-content: center; align-items: center; } .center{ width: 100px; height: 100px; background: blue; text-align: center; }
notes:CSS3的transform和flex有兼容性问题。ie11+才支持flexbox布局。