使用 CSS Grid 和 Flexbox 做工作台需求的布局

本文将介绍一个针对管理端 Web 界面的基础布局方案,使用

  • Grid
  • Flexbox

布局预期要达到的效果:


使用 Grid 布局实现页眉、页脚、导航和正文的框架布局#

Grid 布局介绍#

Grid 布局

  • 是一种二维布局,通过行和列布局界面元素
  • 功能强大,可以用于构建复杂布局
  • 使用 Grid 可简化以往的界面布局

最简单的示例#

这是一个简单的示例:

1
2
3
4
5

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="grid-container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>

<style>
.grid-container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-gap: 0.5rem;

background-color: #ffffcc;
padding: 1rem;
}

.grid-container div {
background-color: #cccc99;
padding: 0.5rem;
}
</style>

在 devtools 下检查 Grid 布局#

在 devtools 中检查 grid 布局很方便:

Grid 的基本概念#

  • column 列
  • row 行
  • gap 行或者列的间距
    • grid-gap: 1rem;,行列相同的间距
    • grid-row-gap: 10px;, 可以分别设置 row 和 column 的间距
  • 在 css 父元素创建 grid,display: grid;
  • 定义一行有几个列,grid-template-columns: 1fr 1fr;
    • fr, fraction,分子数,分母是所有 fr 的和,用来取行的比例宽度
    • 可以用 px 等其他单位
    • 如果宽度相同,可以用函数 grid-template-columns: repeat(3, 1fr)
    • 甚至是任意多的,grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  • 默认情况下,grid 布局容器内的元素,会按照从左上到右下顺序排列
  • 可基于 column 和 row 的序号指定容器内元素的位置

    • 需要在 css 子元素做设置,下面代码表示,header 标记将占据 1 到 3 列,第 1 行

      1
      2
      3
      4
      header {
      grid-column: 1/3;
      grid-row: 1;
      }
    • 可以用 -1 表示最后一行/列,grid-column: 1/-1;

  • 可以通过更直观的模版方式,定义行列元素位置,grid-template-areas

    • 这种方式经常用于网页框架布局
    • 在 css 容器元素

      1
      2
      3
      4
      5
      6
      7
      8
      .container {
      display: grid;
      grid-template-areas:
      "header header"
      "sidebar content"
      "footer footer";
      grid-template-columns: 1fr 3fr;
      }
    • 在子元素

      1
      2
      3
      #header {
      grid-area: header;
      }
    • 使用规则

      • 应为每个单元格定义 grid
      • 单元格为空,要用点来表示,”.”
      • 跨多个单元格,通过重复命名表示
      • 元素的区域必须是矩形,不能是比如 L 型
      • 区域的重复位置必须相邻

工作台管理最基本布局#

实现效果和源代码#

实现效果截图:

代码:https://github.com/MarshalW/simple-site/tree/m1

基本思路和简化的代码#

下面用基本思路简化实现一个示例:

天地玄黃,宇宙洪荒,日月盈昃,辰宿列張,寒來暑往,秋收冬藏, 閏餘成歲,律呂調陽,雲騰致雨,露結為霜,金生麗水,玉出昆岡, 劍號巨闕,珠稱夜光,果珍李柰,菜重芥姜,海咸河淡,鱗潛羽翔, 龍師火帝,鳥官人皇,始製文字,乃服衣裳,推位讓國,有虞陶唐, 吊民伐罪,周發殷湯,坐朝問道,垂拱平章,愛育黎首,臣伏戎羌, 遐邇壹體,率賓歸王,鳴鳳在竹,白駒食場,化被草木,賴及萬方, 蓋此身發,四大五常,恭惟鞠養,豈敢毀傷,女慕貞潔,男效才良, 知過必改,得能莫忘,罔談彼短,靡恃己長,信使可覆,器欲難量, 墨悲絲染,詩贊羔羊,景行維賢,克念作聖,德建名立,形端表正, 空谷傳聲,虛堂習聽,禍因惡積,福緣善慶,尺璧非寶,寸陰是競, 資父事君,曰嚴與敬,孝當竭力,忠則盡命,臨深履薄,夙興溫清, 似蘭斯馨,如松之盛,川流不息,淵澄取映,容止若思,言辭安定, 篤初誠美,慎終宜令,榮業所基,籍甚無竟,學優登仕,攝職從政, 存以甘棠,去而益詠,樂殊貴賤,禮別尊卑,上和下睦,夫唱婦隨, 外受傅訓,入奉母儀,諸姑伯叔,猶子比兒,孔懷兄弟,同氣連枝, 交友投分,切磨箴規,仁慈隱惻,造次弗離,節義廉退,顛沛匪虧, 性靜情逸,心動神疲,守真誌滿,逐物意移,堅持雅操,好爵自縻, 都邑華夏,東西二京,背邙面洛,浮渭據涇,宮殿盤鬱,樓觀飛驚, 圖寫禽獸,畫彩仙靈,丙舍傍啟,甲帳對楹,肆筵設席,鼓瑟吹笙, 升階納陛,弁轉疑星,右通廣內,左達承明,既集墳典,亦聚群英, 杜稿鐘隸,漆書壁經,府羅將相,路俠槐卿,戶封八縣,家給千兵, 高冠陪輦,驅轂振纓,世祿侈富,車駕肥輕,策功茂實,勒碑刻銘, 磻溪伊尹,佐時阿衡,奄宅曲阜,微旦孰營,桓公匡合,濟弱扶傾, 綺回漢惠,說感武丁,俊乂密勿,多士寔寧,晉楚更霸,趙魏困橫, 假途滅虢,踐土會盟,何遵約法,韓弊煩刑,起翦頗牧,用軍最精, 宣威沙漠,馳譽丹青,九州禹跡,百郡秦并,岳宗泰岱,禪主雲亭, 雁門紫塞,雞田赤城,昆池碣石,巨野洞庭,曠遠綿邈,岩岫杳冥, 治本於農,務資稼穡,俶載南畝,我藝黍稷,稅熟貢新,勸賞黜陟, 孟軻敦素,史魚秉直,庶幾中庸,勞謙謹敕,聆音察理,鑒貌辨色, 貽厥嘉猷,勉其祗植,省躬譏誡,寵增抗極,殆辱近恥,林皋幸即, 兩疏見機,解組誰逼,索居閒處,沉默寂寥,求古尋論,散慮逍遙, 欣奏累遣,戚謝歡招,渠荷的歷,園莽抽條,枇杷晚翠,梧桐蚤凋, 陳根委翳,落葉飄搖,游鶤獨運,凌摩絳霄,耽讀玩市,寓目囊箱, 易輶攸畏,屬耳垣牆,具膳餐飯,適口充腸,飽飫烹宰,饑厭糟糠, 親戚故舊,老少異糧,妾御績紡,侍巾帷房,紈扇圓絜,銀燭煒煌, 晝眠夕寐,藍筍象床,弦歌酒宴,接杯舉觴,矯手頓足,悅豫且康, 嫡後嗣續,祭祀烝嘗,稽顙再拜,悚懼恐惶,箋牒簡要,顧答審詳, 骸垢想浴,執熱願涼,驢騾犢特,駭躍超驤,誅斬賊盜,捕獲叛亡, 布射僚丸,嵇琴阮嘯,恬筆倫紙,鈞巧任釣,釋紛利俗,並皆佳妙, 毛施淑姿,工顰妍笑,年矢每催,曦暉朗曜,璇璣懸斡,晦魄環照, 指薪修祜,永綏吉劭,矩步引領,俯仰廊廟,束帶矜莊,徘徊瞻眺, 孤陋寡聞,愚蒙等誚,謂語助者,焉哉乎也。

使用:

  • 使用 grid-template-areas 做页面组件的定位和布局
  • 通过 grid-template-rowsgrid-template-columns 设置各行的高度和各列的宽度

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<div class="container">
<div class="s-header"></div>
<div class="s-nav"></div>
<div class="s-main">
天地玄黃,...
</div>
<div class="s-footer"></div>
</div>

<style>
.container {
display: grid;
grid-template-rows: 40px 1fr 40px;
grid-template-columns: 130px 1fr;
grid-template-areas:
"header header"
"nav main"
"footer footer";

height: 300px;
}

.s-header {
grid-area: header;

background-color: #f9faed;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
z-index: 100;
}

.s-nav {
grid-area: nav;

background-color: #ff9900;
}

.s-main {
grid-area: main;

overflow-y: auto;
-webkit-overflow-scrolling: touch;
background-color: #ffffcc;
padding: 0.5rem;
}

.s-footer {
grid-area: footer;

background-color: #336699;
}
</style>

运用 Flexbox 布局#

Flexbox 布局介绍#

Flexbox 布局

  • 得到浏览器广泛支持
  • 和 Grid 布局不同,前者是二维的,后者是一维的,可以按照行或者列的方向平铺元素
  • Flexbox 让 floatsposition 布局难于实现的场景变得简单,比如基于父元素的垂直居中

最简单的示例#

横向排列 3 个元素#

横向排列 3 个元素,即以行为主轴:

1
2
3

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div class='flex-container'>
<div>1</div>
<div>2</div>
<div>3</div>
</div>

<style>
.flex-container{
display: flex;
align-items:center;

height: 70px;
background-color: #FFFFCC;
}

.flex-container div{
flex: 1;

background-color: #cccc99;
margin: .5rem 0 .5rem .5rem;
padding:.3rem;
}

.flex-container div:nth-of-type(3){
flex: 2;
margin-right: .5rem;
}

虽然是一维,但是可以折行#

比如:

1
2
3
4
5
6
7

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div class='flex-wrap-container'>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
</div>

<style>
.flex-wrap-container{
display: flex;
flex-wrap: wrap;

background-color: #FFFFCC;
}

.flex-wrap-container div{
flex: 120px;

background-color: #cccc99;
margin: .5rem;
padding:.3rem;
}

Flexbox 基本概念#

  • 主轴(排列的方向)和交叉轴
  • flex-direction,默认是 row,水平方向,垂直方向是 column
  • flex-wrap: wrap; 可换行,前提是容器内元素不是按比例分配的
  • flex属性
    • flex: 200px;,隐含为 flex: 1 1 200px;,即
      • 初始宽度(横向排列的情况)是 200px,也就是flex-basis是 200px
      • 当总体宽度大于每个元素分配 200px 的情况,剩余空间按照 1/n(n 为总元素数)分配,即,200px + 剩余空间 * 1/n
      • 当总体宽度小于每个元素分配 200px 的情况,短缺空间按照 1/n(n 为总元素数)减少,即,200px - 短缺空间 * 1/n
    • flex 属性是以下属性的缩写形式
      • flex-grow,对剩余空间分配,默认是 1,0 表示不分配
      • flex-shrink,对短缺空间减少,默认是 1,0 表示即使不够,也不减少
      • flex-basis,初始宽度(横向排列时)
  • 水平和垂直对齐
    • Flexbox 可以很容易的实现水平和垂直居中/对齐
    • align-items: center;,针对交叉轴方向的居中
    • justify-content: center;,针对主轴方向的居中
  • 容器内元素排序,order: 1;

页眉的布局#

页眉基本布局,Logo 和工具条#

页眉左侧是 Logo,右侧是工具条,布局示例如下:

为演示方便,增加了元素的 margin,实际使用是 margin: 0;,示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div class="example-header">
<div class="example-logo"></div>
<div class="example-toolbar"></div>
</div>

<style>
.example-header {
display: flex;

height: 70px;
background-color: #ffffcc;
border: 1px solid #ecf0f1;
}

.example-logo {
flex: 0 0 150px;
background-color: #dc5a60;
margin: 0.3rem;
}

.example-toolbar {
flex: 1;
background-color: #ecf0f1;
margin: 0.3rem;
}
</style>

嵌套 Flexbox 布局,页眉工具条内部的布局#

页眉右侧的工具条,由两部分组成,左侧的快捷按钮区,右侧的登录/登出区。

在上面布局的基础上,嵌套使用 Flexbox,实现如下:

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<div class="example-header2">
<div class="example-logo2"></div>
<div class="example-toolbar2">
<div class="toolButton"></div>
<div class="logout"></div>
</div>
</div>

<style>
.example-header2 {
display: flex;

height: 70px;
background-color: #ffffcc;
border: 1px solid #ecf0f1;
}

.example-logo2 {
flex: 0 0 150px;
background-color: #dc5a60;
margin: 0.3rem;
}

.example-toolbar2 {
flex: 1;
background-color: #ecf0f1;
margin: 0.3rem;

display: flex;
justify-content: space-between;
align-items: center;
}

.toolButton {
height: 30px;
width: 100px;
background-color: #56bf89;
margin: 0.3rem;
}

.logout {
height: 30px;
width: 100px;

background-color: #bdc3c7;
margin: 0.3rem;
}
</style>

需要注意的是,justify-content: space-between;,起到了让 按钮区登出区 之间留出空白的作用。

最终实现效果#

实现的截图:

代码见:https://github.com/MarshalW/simple-site/tree/m2

参考#