Open chunpu opened 6 years ago
经典布局完整实现 App.vue
<template>
<row id="app">
<column class="sidebar main-cross-center">
sidebar
</column>
<column class="flex-1">
<row class="header main-cross-center">
header
</row>
<column class="main flex-1 main-cross-center">
main
</column>
<row class="footer main-cross-center">
footer
</row>
</column>
</row>
</template>
<script>
export default {
name: 'app'
}
</script>
<style scoped>
.sidebar {
width: 210px;
background: #d3dce6;
}
.main {
/* 滚动容器 */
overflow: auto;
background: #e9eef3;
}
.header {
background: #b3c0d1;
height: 60px;
}
.footer {
background: #b3c0d1;
height: 60px;
}
</style>
<style>
@import 'flex.css';
* {
margin: 0;
padding: 0;
}
html, body, #app {
height: 100%;
font-size: 24px;
color: #333;
}
</style>
/* flex 工具类 */
.flex-col {
display: flex;
flex-direction: column
}
.flex-row {
display: flex;
flex-direction: row
}
.flex-1 {
flex: 1
}
.main-align-start {
justify-content: flex-start
}
.main-align-end {
justify-content: flex-end
}
.main-align-center {
justify-content: center
}
.main-align-space-between {
justify-content: space-between
}
.main-align-space-around {
justify-content: space-around
}
.main-cross-center {
justify-content: center;
align-items: center
}
.cross-align-start {
align-items: flex-start
}
.cross-align-end {
align-items: flex-end
}
.cross-align-center {
align-items: center
}
.cross-align-baseline {
align-items: baseline
}
.cross-align-stretch {
align-items: stretch
}
.cross-align-inherit {
align-items: inherit
}
如果说 Flexbox 之前的布局都是错的...
这张图非常经典
首先解释一下为什么叫交叉轴而不是副轴次轴这样的, 主轴很容易理解, 就是 direction 的方向
交叉轴, 就是和主轴垂直的线, 可以理解为十字交叉口, 如果叫次轴的话并不能明确表达方向的语义
谁说盒子只能竖着排
在 flexbox 出现之前, 盒子默认都是竖着排的, 文字才是横着排的
flexbox 的字面意思是弹性伸缩盒, 但 flexbox 附赠了 direction, 这个缺失已久的属性
这使我们可以轻松写出一个竖着排盒子的容器, 而不再是用各种 trick 技巧
之前的各种布局写法
float
float 设计之初是为了做 图文环绕 这种经典的文章排版的, 没想到被各种 hack 作为 layout 系统
但 float 自己写始终很麻烦, 总是要想着 清除浮动
inline-block
总是要想着解决 inline 本身排列的
3px
间隙问题table
大部分布局都是简单的一维布局的组合, table 是一个二维布局, 使用场景较为单一, 不过 table 自带了简单的剩余空间填充问题
栅格系统
栅格系统的问题在于, 现实中其实很少有等分布局, 也很少有 offset 偏移布局, 换句话说, 有个设计稿后, 我根本没机会用栅格系统
Flex 的痛点
Flex 的属性太多了, 同时对应的值也很多, 会让人看了经常放弃
有的朋友只用其中2-3个特性, 我见过最多的就是
space-between
和以及默认flex-direction: column
space-between 过于强大, 彻底解决了元素间隙问题, 而且不再需要单独处理首尾元素, 简直是排版仔的福音
但事实上, 我建议所有布局都用 flex
Flex Container 上有6个属性
Flex Item 上也有6个属性
这么多的属性看的头大, 但我建议只用其中 四个属性, 其他属性如果不是面试的话建议暂时忽略
flex-direction
这个附赠的属性太关键了, 布局本应该可以指定是横向布局还是纵向布局, 从此告别 float 脏实现
justify-content
等同于
text-align
text-align
作用是文字, 而且有继承性, 现在有了justify-content
只是把之前缺失的功能补上align-items
和
vertical-align
非常像, 但vertical-align
使用场景非常复杂, 概念很容易混淆flex
这个是 flex 最核心的属性, 设置 flex item 的弹性
你可以把 flex item 想象为蚁人, 可大可小, 可伸可缩
flex: none
的话则没有弹性,flex: 1
则弹性为1flex 属性是一个简写属性, 就好比 background 属性是一系列属性的组合
初始值是
0 1 auto
也就是说默认的 flex item 是自动缩小的布局
问题来了, 什么时候会用 flex-shrink 呢?
答案是几乎没有
因为我们排版时通常是在处理剩余空间的问题, 很少去解决多余空间的问题
我猜这也是 CSS 工作组推荐大家使用 flex 组合属性的原因 (因为你用不到 flex-shrink, 逃..
虽然 flex-basis 的默认值是 auto, 但
flex: number
会把 flex-basis 设为0%
很简单, 当我们算权重的时候, 不会去考虑 item 本身的长度, 我们需要一起回到起跑线, 从头再来
因此, 我们不用 flex-shrink, 也会把 flex-basis 设为 0, 以及只会使用 flex-grow
那正好, 官方提供的
flex: number
简写就是此功能, 完美事实上 css 工作组直接在文档里说了鼓励使用 flex 这个简写, 因为标准已经帮我们适配好了常用场景
另外所有多行属性都不建议使用, 比如
flex-wrap
,flex-flow
,align-content
完全可以使用单行 flexbox 组合的方式来实现, 这样理解起来更容易
order 自定义顺序非常反人类, 会造成歧义, 也不建议使用
假设之前的布局都是错的
由于时代的局限性, 假设任何之前的 layout 写法都是错的, 我们要推翻桌子重来
我们不关心标签的语义性, 忘掉之前 display inline 和 block 的设定, 忘掉 BFC, IFC!
我们把所有容器都写成 column 和 row 的组合, 因为一个容器, 我们只关心它内部是竖排还是横排
封装 css 工具类
封装我们的 flex 布局工具类
先封装三大基本类, 解决横排和竖排和剩余空间的基本问题
其次封装5种主轴的分布方式
封装6种交叉轴的分布方式(多了一个继承)
复合属性
如果你用的也是 Vue 的话, 可以封装两个基本的容器
横排容器
row.vue
竖排容器
column.vue
在
main.js
加入这两个属性尝试实现一个最经典的带 sidebar 的页面布局
几乎不需要写任何布局相关的代码, 写完后只需要补充一些 margin, 字体相关的属性即可
兼容性问题
IE10不支持 flex-wrap, flex-flow, align-content
不过没关系, 如果我们坚持使用单行 flex 布局, 我们永远都用不到这些属性
事实上, 我认为如果你要使用二维布局, 应该使用多个 flex 布局嵌套组合的方式, 这样容易理解多了
因此我们认为 IE10+ 都支持 flex 布局
直到有同事分享之后才发现 Flex 也是可以 polyfill 的...可以兼容到IE8, IE9~
具体参见此项目, 截至目前已经4000+ star
https://github.com/jonathantneal/flexibility
我们可不可以直接像 border-box 那样直接写
* {display: flex}
呢?不行的, 因为 flex 毕竟是容器布局, 不应该给所有元素加上
只支持 Flexbox 的快应用
最近在学习快应用, 突然发现快应用的样式只支持 Flexbox, 不支持
block
,inline
这些属性值, 可以说是英雄所见略同了也就是说, 怎么排盒子, 竖着排还是横着排, 应该由容器来决定, 而不是元素自己来决定
忘掉 inline, block 这些历史局限, 全面拥抱 flex 才是正解
Flexbox 的定义解决明了, 对开发者和使用者都是好事, 是一个 win-win 的 happy ending, 甚至在 Android, Canvas 等平台里面都可以查到 Flex Layout 相关的开源实现