[TOC]css
没错,题目就是模仿《那些年,咱们一块儿清除过的浮动》而来的。html
相信不少人和我在学习前端差很少的时候就据说过了圣杯布局与双飞翼布局。关于取名无非是以为长得像圣杯,或者是长得像小鸟。至于其中的区别也只有一小点,其中主要的思想可谓是基本一致!前端
这两个布局要实现的样式都是下面的这种形式:git
也就是中间的那一部分,长得像圣杯或者是飞翔的小鸟,left 和 right 宽度已知,中间自适应填充。通常状况下,若是这样写代码,显然是很好实现布局的。github
<div class="head">head</div> <div class="content"> <div class="left">left</div> <div class="main">main</div> <div class="right">right</div> </div> <div class="foot">foot</div>
可是相应的按照 DOM 的加载顺序,content 部分依次会加载 left、main、right。这对于有洁癖的人多是没法忍受的,甚至是以为不符合常理。工具
正常状况下,咱们但愿先加载的是主要部分,而后再开始加载 left 和 right 两个相对来讲不是很重要的东西。因此 HTML 代码应该这样写:布局
<div class="head">head</div> <div class="content"> <div class="main">main</div> <div class="left">left</div> <div class="right">right</div> </div> <div class="foot">foot</div>
另一方面来讲,咱们倡导语义化的 HTML,也就是说在编写 HTML 的时候不该该受制于 CSS 的干扰,因此这样的写法来达到上面的布局也应该是必要的。学习
那么若是这样写应该如何去写 CSS 样式呢?spa
首先咱们的想法多是先搭建起 head content 和 foot,content 里面的东西所有用左浮动解决,对 content 要清除浮动让他撑起高度。代码以下:3d
* { margin: 0; padding: 0; } .cleanfix { clear: both; } .cleanfix:after { content: '.'; clear: both; display: block; visibility: hidden; height: 0; zoom: 1; } .head, .foot { width: 100%; height: 80px; } .head { background-color: #4eb5f7; } .foot { background-color: #999999; } .left, .right, .main { float: left; } .left { width: 40px; height: 60px; background-color: #B9E078; } .right { width: 60px; height: 80px; background-color: #FF9900; } .main { background-color: crimson; }
这样的话就能实现下面的布局:
咱们要的目的是 main 布局自适应,这样的话咱们给 main 100% 的宽度:
.main { 100%; }
这样的话布局就会变成这样:
接下来,咱们想要 left 跑上去,这个时候就可使用奇妙的负边距了。
main, left, right 咱们均可以看作是在一个浮动流中,依次的顺序也是 main left right。目前是由于 main 占了100% 从而致使 left 与 right 不能和 main 浮在同一行了,这个时候咱们能够利用负边距来让 left 向前移动 (即 margin-left 为正的时候就是和左边的盒子的外边距,那么为负的时候就是像前移动了)。加上下面的特技
.left { margin-left: 100%; }
那么移动多少呢?为了让 left 跑到最左边,那么就像上面的同样移动到 -100% ,也就是向左移动的最大值了。这样,会获得下面的布局:
咱们看到 left 移动到最左边了,那 right 是否是也能够模仿 left 一块儿移动呢?移动多少?right 只须要向前移动right的宽度个距离,即 60px
.right { margin-left: -60px; }
获得下面的结果
和咱们想象中的同样, right 也移动上去了,而且跑到了咱们想要的位置。
可是稍微细心点就能发现上面的结果仍是存在问题的,红色中间部分的 main 跑到哪里去了?
打开开发者工具审查元素就能看见好像是 left 和 right 覆盖到上面去了。
那么如何去使得 main 部分往里面收收呢?这也就是圣马布局与双飞翼布局根本区别了
圣杯布局的思想就是给包裹着三个元素的 content 加一个 padding, 让 padding-left 和 padding-right 的数值是 left 和 right 的宽度,而后利用相对定位把他们再移动在两旁。
首先,给 content padding
.content { padding: 0 60px 0 40px; }
而后利用相对定位移动 left 和 right
.left { position: relative; left: -40px; } .right { position: relative; right: -60px; }
这样也就完美的解决了问题:
最后 CSS 的全部样式是这样的:
* { margin: 0; padding: 0; } .cleanfix { clear: both; } .cleanfix:after { content: '.'; clear: both; display: block; visibility: hidden; height: 0; zoom: 1; } .head, .foot { width: 100%; height: 80px; } .head { background-color: #4eb5f7; } .foot { background-color: #999999; } .left, .right, .main { float: left; } .left { width: 40px; height: 60px; background-color: #B9E078; margin-left: -100%; } .right { width: 60px; height: 80px; background-color: #FF9900; margin-left: -60px; } .main { background-color: crimson; width: 100%; } .content { padding: 0 60px 0 40px; } .left { position: relative; left: -40px; } .right { position: relative; right: -60px; }
HTML 是这样的:
<div class="head">head</div> <div class="content cleanfix"> <div class="main">main</div> <div class="left">left</div> <div class="right">right</div> </div> <div class="foot">foot</div>
延续到上面的状况,圣马布局是这样作的
圣马布局的思想就是给包裹着三个元素的 content 加一个 padding, 让 padding-left 和 padding-right 的数值是 left 和 right 的宽度,而后利用相对定位把他们再移动在两旁。
而双飞翼布局是在 main 里面再添加一个 div, 而后对这个 div 进行 margin-left 和 margin-right. 即
<div class="head">head</div> <div class="content cleanfix"> <div class="main"> <div class="wrap">main</div> </div> <div class="left">left</div> <div class="right">right</div> </div> <div class="foot">foot</div>
CSS 部分对 wrap 进行处理:
.wrap { background-color: darkmagenta; margin-left: 40px; margin-right: 60px; }
最后咱们的CSS代码是这样的:
* { margin: 0; padding: 0; } .cleanfix { clear: both; } .cleanfix:after { content: '.'; clear: both; display: block; visibility: hidden; height: 0; zoom: 1; } .head, .foot { width: 100%; height: 80px; } .head { background-color: #4eb5f7; } .foot { background-color: #999999; } .left, .right, .main { float: left; } .left { width: 40px; height: 60px; background-color: #B9E078; margin-left: -100%; } .right { width: 60px; height: 80px; background-color: #FF9900; margin-left: -60px; } .main { background-color: crimson; width: 100%; } .wrap { background-color: darkmagenta; margin-left: 40px; margin-right: 60px; }
总结一下,圣马布局和双飞翼的流程大致上是这样的
搭建 head content foot, content 内部的三个元素所有左浮动,而后清除浮动防止影响 foot
给 main 100% 的宽度让他占满一行
给 left -100% 的margin-left 让他移动到最左边,给 right 和他宽度同样的负 margin 让他移动到最右边
针对移动后 main 的两边会被 left 和 right 重合覆盖掉作出不一样的改变,这儿也就是两个布局的本质区别
圣杯布局会给 content 内边距,左右分别为 left 和 right的宽度,而后再利用相对定位移动 left 和 right
双飞翼布局会在 main 里面再加一层 wrap ,而后把内容都写在 wrap 里面,正对 wrap 设置他的 margin, 左右外边距和 left 与 right 同样
相信在上面的圣马布局与双飞翼布局中已经见识到了负边距的奇妙之处了,这就是他的第一奇妙之处
整个浮动能够看是有一个浮动流的存在,利用负边距可让他在这个流中移动,而且会叠加到相应元素的上面
普通元素的位置是相对于文档流而发生变化的。负边距也会使元素在文档流中发生位移。不一样于相对定位的是,这些元素移动以后不会占据原来的空间。他往前移动以后,文档流也会跟着移动
负边距能够增长元素的宽度,对于没有 width 的元素,负边距能够加宽他们。
这样就可以很好的利用负边距实现 一寸照片排列 的那种难题了。对于这种问题,比较麻烦的办法是浮动以后 margin-right, 而后对每一行的最后一个元素设置 margin-right: 0。这样就存在一个如何给最后一个元素设定这个margin-right的问题了。
利用负边距,咱们能够加大子元素的margin, 而后浮动里面全部的元素,等他们都浮动起来的时候利用 overflow: hidden消除最右边的边距。
绝对定位就是相对于父亲系元素的最近的一个定位元素的边界来决定的,这个边界也就是margin。
若是是负边距的话就能机智的实现元素垂直水平居中了
.con { width: 100px; height: 100px; position: absolute; top: 50%; left: 50% margin-left: -50px; margin-top: -50px; }
https://github.com/rccoder/blog/issues/6
欢迎 start 与 watch