布局&栅格

布局方式


先聊聊布局方面的知识,先列据一个实现三栏水平布局(左右定宽,中间自适应)案列,目前有圣杯布局、双飞翼布局、Flex布局和绝对定位布局的几种经典布局。

圣杯布局 & 双飞翼布局(都是三列左右栏固定中间栏自适应的网页布局)。

相同点:

  • 三列布局,两边定宽,中间自适应;
  • 中间栏要在浏览器中优先展示渲染;
  • 允许任意列的高度最高;

差异点:

  • 双飞翼布局比圣杯布局多创建了一个div,但不用相对布局了

DOM节点结构:

圣杯布局:

<!-- html -->
<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
<!-- css -->
<style>
.container {
    <!-- padding位置出左右盒子,main盒子宽度为父盒子宽度减padding -->
    padding: 0 300px 0 200px;
}
.left, .main, .right {
    <!-- 差异点,需设置定位使盒子左右移动位置 -->
    position: relative;
    <!-- 保持高度一致 -->
    min-height: 130px;
    <!-- 向左浮动 -->
    float: left;
}
.left {
    <!-- 左盒子向左偏移 -->
    left: -200px;
    <!-- 负的margin-left会让元素沿文档流向左移动,如果负的数值比较大就会一直移动到上一行 -->
    margin-left: -100%;
    background: green;
    width: 200px;
}
.right {
    <!-- 盒子向右偏移 -->
    right: -300px;
    margin-left: -300px;
    background-color: red;
    width: 300px;
}
.main {
    background-color: blue;
    width: 100%;
}
</style>

双飞翼布局:

<!-- html -->
<div class="container"> 
  <div class="main">
      <div class="content">main</div> 
    </div>
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
<!-- css -->
<style type="text/css">
.left, .main, .right {
    <!-- 三者浮动 -->
    float: left;
    min-height: 130px;
    text-align: center;
}
.left {
    <!-- 利用 maigin-left 使盒子浮在 main 之上且左边位置 -->
    margin-left: -100%;
    background: green;
    width: 200px;
}

.right {
    <!-- 使盒子浮动于 main 之上右边位置 -->
    margin-left: -300px;
    background-color: red;
    width: 300px;
}
.main {
    background-color: blue;
    width: 100%;
}
.content{
    <!-- 左右外边距到需求位置 -->
    margin: 0 300px 0 200px;
}
</style>

双飞翼布局比圣杯布局多使用了一个div,少用大致4个css属性,比圣杯布局思路更直接和间接一点。

Flex弹性布局

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局, Flex 布局将成为现代浏览器的首选方案。

<!-- html -->
<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
<!-- css -->
<style>
.container{
    <!-- 父盒子指定为flex布局方式,main、left和 right这三个子元素自动成为容器成员 -->
    display: flex;
    min-height: 130px;
}
.main{
    <!-- 填充空余空间,分配比列为 1(只有一个 item 的话多少都是一样) -->
    flex-grow: 1;
    background-color: blue;
}
.left{
    <!-- 可以通过Flex容器下的项目的属性“order”属性来设置排序位置,越小越靠前 -->
    order: -1;
    <!-- 设置固定宽度 -->
    flex-basis: 200px;
    background-color: green;
}
.right{
    <!-- 设置固定宽度 -->
    flex-basis: 300px;
    background-color: red;
}
</style>
绝对定位布局

绝对定位position: absolute使元素的位置与文档流无关,因此不占据空间。PS:这一点与相对定位不同,相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。

<!-- html -->
<div class="container"> 
  <div class="main">main</div> 
  <div class="left">left</div> 
  <div class="right">right</div> 
</div>
<!-- css -->
<style type="text/css">
.container{
    <!-- 父盒子设置相对定位设定位置 -->
    position: relative;
}
.main,.right,.left{
    top: 0;
    height: 130px;
}
.main{
    <!-- 偏移相对位置自适应 -->
    margin: 0 300px 0 200px;
    background-color: blue;
}
.right{
    <!-- 设置绝对定位 -->
    position: absolute;
    width: 300px;
    <!-- 设置右边位置 -->
    right: 0;
    background-color: red;
}
.left{
    <!-- 设置绝对定位 -->
    position: absolute;
    width: 200px;
    background-color: green;
    <!-- 设置左边位置 -->
    left: 0;
}
</style>

栅格布局


栅格

以规则的网格阵列来指导和规范网页中的版面布局以及信息分布,通俗一点的就是在一个特定区域内划分出有规律的格子,并依靠这些格子进行有规律的版面布局。

栅格布局的作用

  • 提高生产力 ;通过在网格的划分,元素更容易堆放而且在跨浏览器上面具有一致性,使我们可以专心的注意布局而不是兼容上。
  • 具有灵活性 ;无论是什么样的布局,都可以拆分到粒度为一个网格的大小。
  • 支持响应式设计 ;栅格系统本身能很好的和响应式设计结合在一起,或者说,我们的栅格系统是基于响应式设计的。

栅格布局的使用

现大多数UI框架设计上都会设计栅格化系统,比如bootstrap(jquery)element(vue)antD(react)等。

Bootstarp

Bootstrap 的栅格化系统采用将页面布局分为12列,再根据页面宽度采用预定义类控制模块占用宽度比例(宽度百分比)的思想,实现响应式布局。

工作规范
  1. container (.container-fluid)> .row > .column ;采用容器内行 (row)(column) 布局方式,.column 必须包含在 .row 中,.row 必须包含在 .container 中;.container 可以包含多个 .row.row 可以包含多个 .column
  2. 展示的内容应当放置于 .column类中,并且只有.column可以作为.row的子元素;
  3. 使用类似于.row.col-xs-4等预定义类,快速创建栅格化布局;
  4. 栅格类适用于屏幕宽度大于或等于分界点大小的设备,并且针对小屏幕设备覆盖栅格化类,比如.col-md-*.container-fludid宽度≥992px时生效;
媒介分类

Bootstrap将屏幕大小分为4类,主要关键点是媒体查询 @media

/* xs 屏幕大小小于768px */
@media (max-width: 767px) { ... }

/* sm 屏幕最小宽度为768px */
@media (min-width: 768px) { ... }

/* md 屏幕最小宽度为992px */
@media (min-width: 992px) { ... }

/* lg 屏幕最小宽度为1200px */
@media (min-width: 1200px) { ... }
实例
<!-- 每一个col-md-* 必须在row之内 -->
<div class="row">
    <!-- col-md-* *值加起来等于 12 ,bootstarp栅格为 12 格-->
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
    <div class="col-md-1">.col-md-1</div>
</div>
<div class="row">
    <div class="col-md-8">.col-md-8</div>
    <div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
    <div class="col-md-4">.col-md-4</div>
    <div class="col-md-4">.col-md-4</div>
    <div class="col-md-4">.col-md-4</div>
</div>
<div class="row row4">
    <div class="col-md-6">.col-md-6</div>
    <div class="col-md-6">.col-md-6</div>
</div>

elementUI

官网中对Layout 布局的定义是: 通过基础的 24 分栏,迅速简便地创建布局.Element是基于vue.js开发的UI框架,其设计的栅格系统也与Bootstrap类似,可选flex方式满足现代浏览器,组件开发的目的都是为了解决基本布局定位的问题。

工作规范

主要组件为 RowCol , 其中 Row 为行布局容器, Col 为列布局容器.

  1. Row 是行布局容器,从功能上来说它的作用是控制内部元素的排列方式,提供 gutter 属性来指定每一栏之间的间隔,将 type 属性赋值为 flex,可以启用 flex 布局;
  2. Col 是列布局容器,通过 Col 组件的 span 属性我们就可以自由地组合布局,提供 offset 属性指定分栏偏移的栏数等。
媒介分类

参照了 Bootstrap 的 响应式设计,预设了五个响应尺寸:

xs  <768px
sm  ≥768px
md  ≥992px
lg  ≥1200px
xl  ≥1920px
实列
<el-row :gutter="20">
  <el-col :span="6">
    <div class="grid-content bg-purple"></div>
  </el-col>
  <el-col :span="6" :offset="6">
    <div class="grid-content bg-purple"></div>
  </el-col>
</el-row>
<el-row :gutter="20">
  <el-col :span="6" :offset="6">
    <div class="grid-content bg-purple"></div>
  </el-col>
  <el-col :span="6" :offset="6">
    <div class="grid-content bg-purple"></div>
  </el-col>
</el-row>
<el-row :gutter="20">
  <el-col :span="12" :offset="6">
    <div class="grid-content bg-purple"></div>
  </el-col>
</el-row>
<!-- 五种尺寸 -->
<el-row :gutter="20">
  <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">
    <div class="grid-content bg-purple"></div>
  </el-col>
</el-row>

antD

antD是Ant Design 团队基于 React 开发的一套企业级后台UI框架,其栅格整个设计建议区域按照 24 等分的原则进行划分

工作规范

支持 Flex 布局,允许子元素在父节点内的水平对齐方式 - 居左、居中、居右、等宽排列、分散排列。子元素与子元素之间,支持顶部对齐、垂直居中对齐、底部对齐的方式。同时,支持使用 order 来定义元素的排列顺序

  • 通过 row 在水平方向建立一组 column(简写col)
  • 你的内容应当放置于 col 内,并且,只有 col 可以作为 row 的直接元素
  • 栅格系统中的列是指1到24的值来表示其跨越的范围。例如,三个等宽的列可以使用 .col-8 来创建
  • 如果一个 row 中的 col 总和超过 24,那么多余的 col 会作为一个整体另起一行排列
媒介规范

参照 Bootstrap 的 响应式设计,预设六个响应尺寸:

xs   <576px
sm   ≥576px
md   ≥768px
lg   ≥992px
xl   ≥1200px
xxl  ≥1600px
实例
import { Row, Col } from 'antd';

ReactDOM.render(
  <div>
    <Row>
      <Col span={8}>col-8</Col>
      <Col span={8} offset={8}>col-8</Col>
    </Row>
    <Row>
      <Col span={6} offset={6}>col-6 col-offset-6</Col>
      <Col span={6} offset={6}>col-6 col-offset-6</Col>
    </Row>
    <Row>
      <Col span={12} offset={6}>col-12 col-offset-6</Col>
    </Row>
  </div>,
  mountNode
);

怎么实现一个基本栅格化?

1. 首先思考栅格的组成?

通常一个基本的栅格化系统包括:

  • container: 包裹整个栅格系统的容器
  • rows: 行
  • columns: 列
  • gutters: 各列的间的空隙
2. 创建容器 (The Container)

为了给整个栅格系统设置宽度,我们需要一个容器。容器的宽度通常为100%,但你可能希望为更大的显示器设置最大宽度max-width

.grid-container {
    width : 100%;
    max-width : 1200px; 
}
3. 创建行 (The Row)

行元素用于防止里面的列( column )溢出到其他的行。通常会使用clearfix来清除浮动,因为我们是通过浮动来制作栅格系统的。


/*-- 清除浮动 -- */ 
.row:before, 
.row:after {
    content:"";
    display: table;
    clear: both;
}
4. 创建列 (The Column)

列元素是栅格系统的核心,也是最复杂的一部分。因为列的定位可以有很多实现方式,同时还需要考虑它的宽度以及响应式设计等因素。

列的位置

Floatsinline-blocksdisplay-tabledisplay-flex 他们都可以实现栅格布局中,列的定位。先选取使用float,如果列都是空的,浮动的列都会贴在彼此的顶部。为了避免这种情况:

[class*='col-'] {
    float: left;
    min-height: 1px; 
}

列的宽度

由于容器总宽度是100%,我们想要6列,所以每列宽度为:100 / 6 = 16.66

[class*='col-'] {
    float: left;
    min-height: 1px; 
    width: 16.66%; 
}

这里我们把一行分成六列,通过简单的计算,还可以定义列的多种宽度。

.col-1 {
    width: 16.66%; 
}
.col-2 {
    width: 33.33%; 
}
.col-3 {
    width: 50%; 
}
.col-4 {
    width: 66.664%;
}
.col-5 {
    width: 83.33%;
}
.col-6 {
    width: 100%;
}

列的间隙 (Column Gutters)

由于列的宽度单位是响应式的百分比(%),我们给列元素的间距是固定单位的padding(px单位),为了避免复杂的计算,我们规定所有的盒子模型为 border-box 类型。

[class*='col-'] {
    /*-- 将栅格系统里的列元素设为 border box --*/
    box-sizing: border-box; 
    float: left;
    min-height: 1px; 
    width: 16.66%; 
    /*-- 设置间隙 --*/
    padding: 12px;
}
5. 增加响应式

为了适配更多分辨率的布局,我们只需改变列的宽度。

比如当屏幕宽度小于1000px时,为了布局更简洁,我们使用两倍列的宽度,一行六列变为了一行三列。

@media all and (max-width:1000px){
    .col-1{ width: 33.33%; }
    .col-2{ width: 50%; }
    .col-3{ width: 100%; }
    .col-4{ width: 100%; }
    .col-5{ width: 100%; }
    .col-6{ width: 100%; }

    .row .col-2:last-of-type{
        width: 100%; 
    }

    .row .col-5 ~ .col-1{
        width: 100%; 
    }
}

当屏幕宽度比1000px还小时

@media all and (max-width:700px){
    .col-1{ width: 50%; }
    .col-2{ width: 100%; }
    .col-3{ width: 100%; }
    .col-4{ width: 100%; }
    .col-5{ width: 100%; }
    .col-6{ width: 100%; }
}
6. 完成Completed!
<!DOCTYPE html>
<html lang="zn">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .grid-container {
      width: 100%;
      max-width: 1200px;
    }

    /*-- 使用 cleafix 清除浮动 -- */
    .row:before,
    .row:after {
      content: "";
      display: table;
      clear: both;
    }

    [class*='col-'] {
      float: left;
      min-height: 1px;
      width: 16.66%;
      /*-- 设置列的左右间隙 -- */
      padding: 12px;
      box-sizing: border-box;
      background-color: #FFDCDC;
    }

    .col-1 { width: 16.66%; }
    .col-2 { width: 33.33%; }
    .col-3 { width: 50%; }
    .col-4 { width: 66.66%; }
    .col-5 { width: 83.33%; }
    .col-6 { width: 100%; }
    .outline,
    .outline * {
      outline: 1px solid #F6A1A1;
    }

    /*-- 列的额外内容样式 --*/
    [class*='col-']>p {
      background-color: #FFC2C2;
      padding: 0;
      margin: 0;
      text-align: center;
      color: white;
    }

    @media all and (max-width:1000px) {
      .col-1 { width: 33.33%; }
      .col-2 { width: 50%; }
      .col-3 { width: 100%; }
      .col-4 { width: 100%; }
      .col-5 { width: 100%; }
      .col-6 { width: 100%; }
      .row .col-2:last-of-type { width: 100%; }
      .row .col-5~.col-1 { width: 100%; }
    }

    @media all and (max-width:700px) {
      .col-1 { width: 50%; }
      .col-2 { width: 100%; }
      .col-3 { width: 100%; }
      .col-4 { width: 100%; }
      .col-5 { width: 100%; }
      .col-6 { width: 100%; }
    }

  </style>
</head>

<body>
  <div class="grid-container outline">
    <!-- col-1 -->
    <div class="row">
      <div class="col-1"><p>col-1</p></div>
      <div class="col-1"><p>col-1</p></div>
      <div class="col-1"><p>col-1</p></div>
      <div class="col-1"><p>col-1</p></div>
      <div class="col-1"><p>col-1</p></div>
      <div class="col-1"><p>col-1</p></div>
    </div>
    <!-- col-2 -->
    <div class="row">
      <div class="col-2"><p>col-2</p></div>
      <div class="col-2"><p>col-2</p></div>
      <div class="col-2"><p>col-2</p></div>
    </div>
    <!-- col-3 -->
    <div class="row">
      <div class="col-3"><p>col-3</p></div>
      <div class="col-3"><p>col-3</p></div>
    </div>
    <!-- col-4 -->
    <div class="row">
      <div class="col-4"><p>col-4</p></div>
      <div class="col-2"><p>col-2</p></div>
    </div>
    <!-- col-5 -->
    <div class="row">
      <div class="col-5"><p>col-5</p></div>
      <div class="col-1"><p>col-1</p></div>
    </div>
    <!-- col-6 -->
    <div class="row">
      <div class="col-6"><p>col-6</p></div>
    </div>
  </div>
</body>

</html>

>1000px

<1000px

<700px

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342