evantianx / Bloooooooog

Place to record what I thought and learned
0 stars 0 forks source link

关于 Grid 的一切 #38

Open evantianx opened 7 years ago

evantianx commented 7 years ago

26 ⏎ 关于 flex 的一切

参考文章:

A Complete Guide to Grid CSS Grid Application Layout in Production

evantianx commented 7 years ago

基本概念

无特殊说明,均以下列 HTML 和 CSS 为模版:

<div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>
.grid {
  display: grid;
  /* grid-gap 是 grid-column-gap 和 grid-rows-gap 的简写*/
  grid-gap: 20px;
}
.grid div {
  background: #41B883;
}

容器属性

定义 display

有三个属性可以定义该容器为 grid 容器

grid-template-rowsgrid-template-columns

可以直接设置像素值(或者相对单位也可以)作为行高或列宽:

.grid {
  grid-template-rows: 100px 50px;
  grid-template-columns: 100px 100px 200px;
}

2017-05-20 10 13 15

由于没有设置第三行行高,故第三行的高度由子元素内容高度确定。

也可以设置 fractions 来进行响应式布局:

.grid {
  grid-template-rows: 2fr 1fr 1fr;
  grid-template-columns: 1fr 2fr 1fr;
}

2017-05-20 10 31 04 当然,两者结合也是 ok 的:

.grid {
  grid-template-columns: 100px 25% 1fr 2fr;
}

2017-05-20 10 42 24

此时的 1fr = ((容器宽度) - 100px - 25%(容器宽度)) /3

若容器没有设置该方向的尺寸且如 grid-template-columns: repeat(4, 1fr) 设置时,将按照元素实际占用宽高来决定宽高尺寸

利用minmax()也可以进行响应式设计布局: 该函数接受两个参数,第一个是最小值,第二个是最大值。(参数可以为百分比,像素值或者 auto)

利用repeat()来减少书写量 接受两个参数,第一个是重复次数,第二个为宽度或高度

.grid {
  grid-template-rows: repeat(4, 100px);
  grid-template-columns: repeat(3, 1fr);
}

2017-05-20 12 58 24

repeat()也可以和其他值进行组合

可以对 lines 进行命名:

.grid {
  /* 是可以有多个命名的 */
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

命名可以运用于repeat()中:

.grid {
   grid-template-columns: repeat(3, 20px [col-start]);
 }

grid-template-areas

Repeating the name of a grid area causes the content to span those cells.

值可以为某个子元素的 grid-area 值,或者 . (表示一个空位),或者 none

<div class="grid">
<div class="item-a">1</div>
<div class="item-b">2</div>
<div class="item-c">3</div>
<div class="item-d">4</div>
</div>

.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}

.grid { display: grid; grid-template-columns: 50px 50px 50px 50px; grid-template-rows: auto; grid-template-areas: "header header header header" "main main . sidebar" "footer footer footer footer"; }

![2017-05-20 1 34 32](https://cloud.githubusercontent.com/assets/17511710/26273337/19b2990e-3d61-11e7-907d-f534f5e5af62.png)
> .表示空位
> Notice that you're not naming lines with this syntax, just areas. When you use this syntax the lines on either end of the areas are actually getting named automatically. If the name of your grid area is foo, the name of the area's starting row line and starting column line will be foo-start, and the name of its last row line and last column line will be foo-end. This means that some lines might have multiple names, such as the far left line in the above example, which will have three names: header-start, main-start, and footer-start

#### `grid-column-gap` / `grid-row-gap`

设定 cell 间隙

> The gutters are only created between the columns/rows, not on the outer edges.
> **不在外边缘产生间隙**

#### `justify-items`

调整**水平**方向上 cell 的位置,会作用于 container 内所有 cell

可取值有: `start` 、`center`、`end`、`stretch`(默认)

> 单个 grid-item 可以采用 `justify-self` 单独调整

#### `align-items`

调整竖直方向上 cell 的摆放位置,类似于 `justify-items`。

> 对应 grid-item 属性为 `align-self`

#### `justify-content` / `align-content`

有时候如果只采用绝对单位如 `px`, 可能父容器未被子项目填满,那么 `justify-content` 和 `align-content` 就是用来调整整体 grid-item 在父级中的位置的

可取值: `start`、`center`、`end`、`stretch`、`space-between`、`space-around`、`space-evenly`

> 已经确定尺寸的不会受到影响
> 那还有啥意义呢??❓ 
### grid-item 属性
#### `grid-column-start` / `grid-column-end` / `grid-row-start` / `grid-row-end`
确定 grid-item 的位置

#### `grid-area`
不仅仅可以传名字,也可以传界限: 顺序为(`grid-row-start` + `grid-column-start` + `grid-row-end`+ `grid-column-end`) **逆时针顺序**

```css
.item-d {
  grid-area: 1 / col4-start / last-line / 6
}

关于 grid-item 内容定位

.grid {
  /* 每个子元素水平方向定位,默认为 stretch */
  justify-items: start | end | center | stretch;
  /* 每个子元素竖直方向定位,默认为 stretch */
  align-items: start | end | center | stretch;
  /* 整体子元素水平方向定位 */
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
  /* 整体子元素竖直方向定位 */
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
evantianx commented 6 years ago

缩写

grid-template

grid-template-columnsgrid-template-rowsgrid-template-areas三者的缩写

grid-template-areas 中写的例子可以简写为:

.grid {
  display: grid;
  grid-template: 
    [row1-start] "header header header header"  40px [row1-end]
    [row2-start] "main main . sidebar" auto [row2-end]
    [row3-start] "footer footer footer footer" 30px [row3-end]
    / repeat(4, 50px);
}

经测试,后面的 repeat(4, 50px) 在 Chrome 中无效,只能用 50px 50px 50px 50px

grid-gap

grid-row-gapgrid-column-gap 的简写

若有一个不存在则赋予两者相同值

grid

grid-template 更为强大,增加了 grid-auto-flow 的简写

.container {
  grid: column 1fr / auto;
}

grid-column / grid-row

简写 grid-column-start / grid-column-end / grid-row-start / grid-row-end

.item-a {
  grid-row: 1/3;
  grid-column: 2/7;
}

类似 grid-row: 2 这样的写法表示从 2 开始占一个 cell

grid-column: 1/-1 代表该子项目列占位从头开始到尾,数字代表 Grid tracks。-1 始终代表最后的那个 grid line。

evantianx commented 6 years ago

父子相关属性

grid-auto-columns / grid-auto-rows

声明一个 track 的 size,如:

.container {
  grid-auto-columns: 60px;
  grid-auto-rows: 60px;
}

然后在 grid-item 中可以根据 line 定位,如:

.item-b {
  /* item-b 占位竖直线1-2,水平线4-7 */
  grid-column: 1/2;
  grid-row: 4/7;
}

grid-auto-flow

确定当没有指定位置时,grid item 的填充方式

即优先填充水平列还是竖直列

可取值为: rowcolumndense

evantianx commented 6 years ago

auto-fill vs auto-fit

参考自:Auto-Sizing Columns in CSS Grid: auto-fill vs auto-fit

Grid 布局中有 repeat 功能来方便我们避免书写重复的属性值,如:

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
}

这样浏览器根据视口自适应调整每个 grid item 的大小,弊端在于当视口很小时, grid item 也会变得非常窄,不甚美观,好在我们有 minmax()

grid-template-columns: repeat(12, minmax(250px, 1fr));

问题又来了, 小屏幕上这样做会溢出,排版很乱,此时祭出 auto-fitauto-fill(会自动 wrap)

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

两者区别在于:

auto-fill FILLS the row with as many columns as it can fit. So it creates implicit columns whenever a new column can fit, because it's trying to FILL the row with as many columns as it can. The newly added columns can and may be empty, but they will still occupy a designated space in the row.

auto-fit FITS the CURRENTLY AVAILABLE columns into the space by expanding them so that they take up any available space. The browser does that after FILLING that extra space with extra columns (as with auto-fill ) and then collapsing the empty ones.

个人理解:

auto-fill 遵循的原则: 添加尽可能多的 column 无论它是否被某个元素占据 auto-fit 遵循的原则:没有元素占据的 column 保持为空,有元素占据的 column 占据尽可能大的空间

evantianx commented 6 years ago

兼容性讨论

目前在 IE11 上支持,但必须添加前缀,且有一些意外情况:

grid-columngrid-row 问题

1_cdhblcgfhfh64i2jvd90pw

IE requires you to manually specify start and span values using specific properties. Autoprefixer sadly doesn't do this transformation automatically so we have to take care of it ourselves.

<main> 元素不支持将其设置为 grid 子项目

解决方法:

<div role="main"></div>
evantianx commented 6 years ago

技巧

A Collection of Interesting Facts about CSS Grid Layout Another Collection of Interesting Facts About CSS Grid

evantianx commented 6 years ago

最佳实践

Best Practices With CSS Grid Layout