flex 双飞翼实现

双飞翼又叫做圣杯布局。简单的说,双飞翼是中国叫法,圣杯是老外叫的。这是由: Matthew Levine 提出的。简而言之有几点注意事项:

双飞翼又叫做圣杯布局。简单的说,双飞翼是中国叫法,圣杯是老外叫的。这是由: Matthew Levine 提出的。简而言之有几点注意事项:

  • 中间一栏最先渲染
  • 允许任意一栏放最上面
  • 只需一个额外 div 标签
  • 少用 HACK

实际上,强制要求就是前 3 个。他给的实现方式已经有了,我就简单的讲解一下他的实现吧。

原始双飞翼实现

完整demo,可以参考: 双飞翼布局

他的基本 HTML 为:

<div id="header">#header</div>

<div id="container">

<div id="center" class="column">#center</div>

<div id="left" class="column">#left</div>

<div id="right" class="column">#right</div>

</div>

<div id="footer">#footer</div>

没啥特殊的。这里就满足了任意一栏放上面的要求。因为 container 里面包括了圣杯布局的基本实现。使用 div 来包裹他,防止影响到其他元素。 主要还是 CSS (因为这里根本就没用 JS) header 和 footer 随便大家怎么放了,就是用到了 clear:both 清楚浮动。我们来观摩 container 里面的内容。

#container {

padding-left: 200px;

padding-right: 150px;

}

#container .column {

height: 200px;

position: relative;

float: left;

}

#center {

background-color: #000;

width: 100%;

}

#left {

background-color: red;

width: 200px;

right: 200px;

margin-left: -100%;

}

#right {

background-color: blue;

width: 150px;

margin-right: -150px;

}

// IE6 的 HACK 可以不用管

* html #left { // 定位 右边 container 的盒模型位置

left: 150px;

}

最最重要的是前面两个。

#container {

padding-left: 200px; // 定义 #left 的宽度

padding-right: 150px; // 定义 #right 的宽度

}

#container .column {

height: 200px;

position: relative; // 设置相对布局,便于调整位置

float: left; // 让包裹元素脱离文档流

}

ok, 也就是说,#container 里面的属性,应该是至关整个页面布局的属性。这里,可以根据单一职责原则,再进行优化,将清除浮动这个 trick 让他本身自己实现。即:

#container::after{

display:block;

content:'';

clear:both;

}

后面,我就挑 left 来进行简单说明(这篇想说的是 flexbox)。

#left {

background-color: red;

width: 200px;

right: 200px;

margin-left: -100%;

}

主要属性就是 margin-left:-100%; ,用来将自己吃掉。那么此时,看起来他的宽度就为0,这就意味着,他可以上移了。对应于 right 就是:

#right {

background-color: blue;

width: 150px;

margin-right: -150px;

}

但,这有一个问题,right 怎么会浮动到最右边呢?感觉他应该是紧挨着 left。我们现在讲 margin-right 给忽略,会得到:

flex 双飞翼实现

关键的秘密在于,使用 margin-left 是不会当前层的文档流,更直观的就是,他们是在一个 Layer 上。

flex 双飞翼实现

right 跟着上移时,会根据上面那一行进行布局。so,他就会到右边去了。补充一下: margin 为负值的 problem

  • 没有设置 width: 使用 margin 负值,会向指定方向拖动
  • 设置 width: 会让元素内部塌陷,原来的样子不变。也就是说,其他元素会覆盖到它。

基本内容就是这些,MDZZ,一个双飞翼能扯出这么多。。。怪不得很多公司都喜欢问。。。主要的考点就是,margin 负值,position,left,清除浮动。 不过,我们这里,不扯这些,我们就用 flexbox。纯原生,快速实现。

flexbox 实现

这里,再说一下要求吧:

  • 中间一列自适应
  • 左右永远固定

对比与 flex 实现方式来说,这简直 so easy。我直接上代码吧:

// HTML

<div id="header">#header</div>

<div id="container">

<div id="left" class="column">#left</div>

<div id="center" class="column">#center</div>

<div id="right" class="column">#right</div>

</div>

<div id="footer">#footer</div>

// CSS

body {

min-width: 550px;

}

#container{

display: flex;

justify-content: center;

align-items: flex-start;

}

.column{

height: 200px;

color:white;

}

#center{

flex-grow: 1;

background-color: black;

}

#left{

flex-basis: 200px;

background-color: red;

}

#right{

flex-basis: 200px;

background-color: blue;

}

里面主要用到的就是 justify-content 和 align-items 来进行布局设置。 具体可以参考: holy grail 那两者有没有什么差异呢? 查看了 timeLine 发现, flexbox 渲染的层数也是一层:

flex 双飞翼实现

ok… 这当然说明不了什么,我们具体来看一下渲染完成时间就 ok:

  • flexbox: ~80ms
  • 原始 css: ~120ms

ok, 这下你知道该用哪一个了吧。

当然 flex 实际上就为了各种各样比较 HACK 的布局方式实现的。比如,侧边栏布局,多列布局等等。

flex 双飞翼实现

侧边栏布局,我就不多说了,关键是掌握 flexbox 的基本属性。直接看 源码 就 ok。 当然,flexbox 最适合做的就是多列布局,而且你多列的顺序可以随意切换,只要简单修改 order 就 ok。

flexbox 兼容处理

当然,说了这么多,兼容性肯定是个大问题,因为从第一版的 box 到现在 W3C 标准的 flex。中间经历了很多让人费解的阶段,那使用 flex 的时候,非要让你手动加上每一个时代的 flexbox,这估计就疯了。所以,编译 flex 的插件就出来了。我经常使用的就是 flexboxfixer 。简单的说,他就是将以前的 flexbox 的tip 给加上。它源码里也很清楚的写明了 flexbox 怎样做映射。

var mappings = {

'display': {

valueMap: {

'box': 'flex',

'flexbox': 'flex',

'inline-box': 'inline-flex',

'inline-flexbox': 'inline-flex'

}

},

'box-align': {

newName: 'align-items',

valueMap: {

'start': 'flex-start',

'end': 'flex-end'

}

},

'flex-direction': {

valueMap: {

'lr': 'row',

'rl': 'row-reverse',

'tb': 'column',

'bt': 'column-reverse'

}

},

'box-pack': {

newName: 'justify-content',

valueMap: {

'start': 'flex-start',

'end': 'flex-end',

'justify': 'space-between'

}

},

'box-ordinal-group': {

newName: 'order',

valueMap: {}

},

'box-flex': {

newName: 'flex',

valueMap: {}

}

};

这里就不过多赘述了。用的话也很简单,直接 postcss([flexboxfixer]) 即可。放一个我常用的 gulp 配置:

gulp.task('css', () => {

var processors = [ //这里就是中间件

autoprefix({

browsers: ['last 3 Safari versions', "last 2 Explorer versions", 'last 2 Explorer versions', "iOS 5"],

cascade: true,

remove: true

}),

flexpost

];

return gulp.src(["xx/*.css"]) // 引入CSS

.pipe(postcss(processors)) // 处理相关 css

.pipe(gulp.dest('dev/styles'));

});

未登录用户
全部评论0
到底啦