⛳️

Grid Layout

Grid

CSS Grid Layout excels at dividing a page into major regions or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.

display: grid;

first

.container {
    display: grid;
    grid-template-columns: 100px auto 100px;
    grid-template-rows: 50px 50px;
    grid-gap: 3px;
}
.container {
    display: grid;
    grid-template-columns: 100px auto;
    grid-template-rows: 50px 50px 200px;
    grid-gap: 3px;
}

fraction unit

.container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    grid-template-rows: 50px 50px;
    grid-gap: 3px;
}

repeat

grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 50px);
grid-template: repeat(2, 50px) / repeat(3, 1fr); // same above

position items

.container {
    display: grid;
    grid-gap: 3px;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 40px 200px 40px;
}
.header {    
    grid-column: 1 / -1;
}
.menu {
    grid-row: 1 / 3;
}
.content {
    grid-column: 2 / -1;
}
.footer {
    grid-column-start: 1;
    grid-column-end: 13;
    // the same
    // grid-column: 1 / span 12;
    // the same
    // grid-column: 1 / -1;
}

summary

以上例子的 container 是不指定宽高的, 但 container 的宽总是等于父控件, container 的高是子控件高度之和. 不指定宽高的 div, 在横向布局中, 设置为 1fr 或 auto 是会撑满横向的, 但在竖直方向设置 1fr 或 auto 是不起作用的, 此时子控件总是最矮.

如果设置了宽高, 那么 fr 或 auto 会按比例布局.

.container {
    height: 100%;
    display: grid;
    grid-gap: 3px;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 40px auto 40px;
}

Template areas

.container {
    height: 100%;
    display: grid;
    grid-gap: 3px;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 40px auto 40px;
    grid-template-areas: 
        "m h h h h h h h h h h h"
        "m c c c c c c c c c c c"
        "f f f f f f f f f f f f";
}

.header {
    grid-area: h;
}

.menu {
    grid-area: m;
}

.content {
    grid-area: c;
}

.footer {
    grid-area: f;
}

使用点来占位:

grid-template-areas: 
        ". h h h h h h h h h h ."
        "m c c c c c c c c c c c"
        ". f f f f f f f f f f .";

Autofit and minmax

grid-template-columns: repeat(6, 100px);
grid-template-rows: repeat(2, 100px);

这种布局子控件大小 100x100, 一排6个, 共2排.

grid-template-columns: repeat(6, 1fr);

使用 fr 那么子控件将会一排6个平均父控件宽度, 但这种还是不够 responsive, 如果屏幕父控件太小那么每个缩的都很小, 如果父控件很长, 那么每个也很宽.

grid-template-columns: repeat(auto-fit, 100px);

使用 auto-fit 可以解决自动 wrap 的问题, 如下图. 但还不完美, 宽度是死的, 不够 responsive, 图中明显可以看到右侧有余地.

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

使用 auto-fitminmax() 搭配完美解决这个问题, 每个 div 最窄 100px 最宽 1fr, 分别是在 刚好分配n个时候 和 刚好不够分配n个时候.

implicit rows

上一节解决了横向布局, 纵向布局没有做适配.

grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
grid-template-rows: 100px 150px;

这样第一行 100px 高度, 第二行 150px 高度. 那么往下的所有行都是最矮.

grid-template-rows: 100px 150px;
grid-auto-rows: 100px;

设置 grid-auto-rows 会让剩余的每行都是 100px.

awesome image grid

上两节学的 responsive 都是指定子控件大小, 如果子控件有多种样式呢? 有的很宽, 有的很高, 有的很大?

.horizontal {
    grid-column: 1 / span 2;
}

这种横向的图片 grid-column-start 不知道填几? 那么使用 auto 吧.

.horizontal {
    grid-column: auto / span 2;
}
.horizontal {
    grid-column: span 2;
}

省略第一个, 相同的效果.

同样的, 纵向也如此设置:

.vertical {
    grid-row: span 2;
}

对于大图, 采用相同方法:

.big {
    grid-column: span 2;
    grid-row: span 2;
}

呃, 有问题了吧~

为了解决这个问题, 需要在 container 中设置 grid-auto-flow, 默认值是 row, 在这里应该使用 dense.

.container {
    display: grid;
    grid-gap: 5px;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    grid-auto-rows: 75px;
    grid-auto-flow: dense;
}

Named lines

.container {
    ...
    grid-template-columns: [main-start] 1fr [content-start] 5fr [content-end main-end];
    ...
}
.header {
    grid-column: main-start / main-end;
}
.content {
    grid-column: content-start / content-end;
}

这里给 line 起名中间有个 dash -, 有神奇作用:

.header {
    grid-column: main;
}
.content {
    grid-column: content;
}

同样 rows 也可以这样使用:

.container {
    ...
    grid-template-columns: [main-start] 1fr [content-start] 5fr [content-end main-end];
    grid-template-rows: [main-start] 40px [content-start] auto [content-end] 40px [main-end]; 
}
grid-row: content;
grid-column: content;

同样可以省略:

grid-area: content;

Justify-content & align-content

justify-content: center;
align-content: center;

flex 一样的效果:

对应的, justify-items, align-items, justify-self, align-self 也有, 个人感觉使用场景不多.

auto-fit vs auto-fill

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

在我们一生中,命运赐予我们每个人三个导师,三个朋友,三名敌人,三个挚爱。但这十二人总是不以真面目示人,总要等到我们爱上他们、离开他们、或与他们对抗时,才能知道他们是其中哪种角色。