blog/source/_posts/responsive-flex.md
2021-04-27 14:55:08 +08:00

3.7 KiB
Raw Blame History

title tags categories date
一套通用的响应式布局
前端
CSS
Less
响应式布局
Responsive
Flex
前端
CSS
2021-04-27 14:49:29

响应式布局通常都是使用@media媒体查询来完成但是要实现每一套查询都需要编写大量重复的CSS代码借用Less预处理器提供的函数功能可以非常有效的将它们抽象出来。

公共函数代码

.flex(@media) {
    display: flex;
    &.row-@{media} {
        flex-direction: row;
    }
    &.row-@{media}-inv {
        flex-direction: row-reverse;
    }
    &.col-@{media} {
        flex-direction: column;
    }
    &.col-@{media}-inv {
        flex-direction: column-reverse;
    }
    @main-axis-align: {
        start: flex-start;
        center: center;
        end: flex-end;
        space: space-around;
        even: space-evenly;
        between: space-between;
        baseline: baseline;
    }
    each(@main-axis-align, {
        &.rm-@{key}-@{media} {
            justify-content: @value;
        }
        &.cm-@{key}-@{media} {
            align-content: @value;
        }
    });
    @cross-axis-align: {
        start: flex-start;
        center: center;
        end: flex-end;
        stretch: stretch;
        baseline: baseline;
    }
    each(@cross-axis-align, {
        &.rc-@{key}-@{media} {
            align-items: @value;
        }
        .as-@{key}-@{media} {
            align-self: @value;
        }
    });
    each(range(1, 10), .(@i) {
        .extend-@{i}-@{media} {
            flex-grow: @i;
        }
        .shrink-@{i}-@{media} {
            flex-shrink: @i;
        }
    });
    @special-width: {
        min: min-content;
        max: max-content;
        fit: fit-content;
    };
    each(@special-width, {
        .w-@{key}-@{media} {
            width: @value;
        }
    });
    @basis-percent: 2, 3, 4, 5, 8, 10, 12, 16, 20, 24;
    each(@basis-percent, .(@max) {
        each(range(1, @max), .(@i) {
            .b-@{i}-@{max}-@{media} {
                flex-basis: percentage(@i / @max);
            }
            .w-@{i}-@{max}-@{media} {
                width: percentage(@i / @max);
            }
        });
    });
    @wrap-modes: {
        none: nowrap;
        wrap: wrap;
        inv: wrap-reverse; 
    }
    each(@wrap-modes, {
        &.w-@{key}-@{media} {
            flex-wrap: @value;
        }
    });
}

使用方法

假设上面这段Less代码存放在common.less文件里,那么可以构建出以下响应式样式定义。

@import "common.less";

/* 全局样式部分 */
.flex {
    .flex(a);
}

/* 小尺寸屏幕样式 */
@media screen and (max-width: 639px) {
    .flex {
        .flex(s);
    }
}

/* 中等尺寸屏幕样式 */
@media screen and (min-width: 640px) and (max-width: 959px) {
    .flex {
        .flex(m);
    }
}

/* 大尺寸屏幕样式 */
@media screen and (min-width: 960px) {
    .flex {
        .flex(l);
    }
}

HTML示例

下面通过一个简单的HTML示例来说明这段响应式布局的使用。这个HTML示例可以达到小屏幕采用纵向排列中等屏幕采用水平可换行排列大屏幕采用水平不换行排列所有元素均采用两端对齐。

<div class="flex col-n row-a w-wrap-m rm-between-a rc-center-a">
    <div class="squre w-2-2-n w-1-3-m w-2-12-l">Squre 1</div>
    <div class="squre w-2-2-n w-1-3-m w-2-12-l">Squre 2</div>
    <div class="squre w-2-2-n w-1-3-m w-2-12-l">Squre 3</div>
    <div class="squre w-2-2-n w-1-3-m w-2-12-l">Squre 4</div>
    <div class="squre w-2-2-n w-1-3-m w-2-12-l">Squre 5</div>
    <div class="squre w-2-2-n w-1-3-m w-2-12-l">Squre 6</div>
</div>