实现一个最小的 CSS 响应式布局系统

2023-05-16

阳光里她在院子中央晾晒着衣裳 / 在四季的风中她散着头发安慰着时光

——赵雷《南方姑娘》

响应式布局系统,在现在流行的 CSS 框架中已经非常常见了。它主要由容器类和约定一行列数的栅格系统组成,组成了一个框架的骨架。

在流行的前端框架 Bootstrap 和 Bulma CSS 中,就有体现。像 Bootstrap 的 .container.row.col;还有 Bulma CSS 的 .containercolumnscolumn 都是表示这类布局系统。虽然名称不一样,但原理都是相同的。

随着 Flex 布局的普及,几乎现代的栅格系统的实现都选择使用这一灵活的布局方式。

现在就来看一下,怎样实现一个最小的 CSS 响应式布局系统吧。

首先从容器说起。

为了保证实现代码的简洁,本文将使用 SCSS 来写。如果你对 SCSS 还不熟悉,没有关系,行文中会对使用到的知识点做介绍。

容器

容器主要用来包裹网页的主要内容,常见效果就是将内容居中地显示在屏幕中间。

我们使用 .container 来约定容器。

首先,容器是水平居中的,这一块样式较为容易:

.container {
    margin-left: auto;
    margin-right: auto;
}
复制代码

所谓的响应式容器,就是根据不同的断点(breakpoints),也就是当前的视口宽度,来决定容器使用的 max-width 值。

这里我们借鉴了 Bootstrap 中对断点的定义,根据视口宽度,分为以下几类设备:

  1. 超小屏(Extra small screen),平常手机,范围是 [0, 576px)
  2. 小屏(Small screen),大手机,范围是 [576px, 768px)
  3. 中屏(Medium screen),平板电脑,范围是 [768px, 992px)
  4. 大屏(Large screen),桌面电脑,范围是 [992px, 1200px)
  5. 超大屏(Extra large screen),大桌面电脑,范围是 [1200px, +∞)

针对断点定义,声明一个变量 $breakpoints

$breakpoints: (
    // Extra small screen / phone
    xs: 0,
    // Small screen / phone
    sm: 576px,
    // Medium screen / tablet
    md: 768px,
    // Large screen / desktop
    lg: 992px,
    // Extra large screen / wide desktop
    xl: 1200px
);
复制代码

$breakpoints 称为“列表”,是 SCSS 提供给我们的数据结构。由一个个 key: value 键值对组成。上例中的 key 表示的是设备有效范围的起始点。

不同的设备下,容器有不同的 max-width 值。所以,这里我们再声明一个表示容器宽度的变量 $container-max-widths

$container-max-widths: (
    xs: none,
    sm: 540px,
    md: 720px,
    lg: 960px,
    xl: 1140px
);
复制代码

这里的 $container-max-widths 也是个列表,这里的 key 表示某个设备下容器的最大宽度。比如,在超大屏设备下,容器的最大宽度是 1140px,而在平常手机下,不设置容器的最大宽度,为默认值 none

有了实现的思路,接下来就着手实现。

我们就可以借助媒体查询指令 @media,依据视口宽度的范围,给予 .container 不同的 max-width 值。

@each $device, $breakpoint in $breakpoints {
    @media only screen and (min-width: $breakpoint) {
        .container {
            max-width: map-get($container-max-widths, $device);
        }
    }
}
复制代码

7 行代码搞定!

下面解释下上面的代码。

我们对列表遍历,使用的是 @each...in 语法,每一次遍历取出对应的 key、value,得到当前的 $device$breakpointmap-get 是 SCSS 提供的用来操作列表的方法:根据 key 取出 value。比如,当 $device 值为 xs 的时候,map-get($container-max-widths, $device) 对应值为 none;当 $device 值为 sm 的时候,map-get($container-max-widths, $device) 对应值为 540px,以此类推。

@media only screen and (min-width: $breakpoint) { ... } 中包含的代码,表示从当前设备断点开始处,应用的 CSS 样式。当我们同时按照从小到大的顺序设置两个断点的媒体查询时,后者会覆盖前者的样式,这是实现不同视口下,具有不同宽度容器的核心原理。

接下来,将得到的宽度值赋给容器的 max-width 属性就可以了。

到现在为止,我们就写出了一个响应式容器了,我们总揽下代码:

$breakpoints: (
    // Extra small screen / phone
    xs: 0,
    // Small screen / phone
    sm: 576px,
    // Medium screen / tablet
    md: 768px,
    // Large screen / desktop
    lg: 992px,
    // Extra large screen / wide desktop
    xl: 1200px
);

$container-max-widths: (
    xs: none,
    sm: 540px,
    md: 720px,
    lg: 960px,
    xl: 1140px
);

.container {
    margin-left: auto;
    margin-right: auto;
}

@each $device, $breakpoint in $breakpoints {
    @media only screen and (min-width: $breakpoint) {
        .container {
            max-width: map-get($container-max-widths, $device);
        }
    }
}
复制代码

点击这里,查看效果。

下面再来介绍 12 列栅格布局。

12 列栅格布局

先使用 Flex 布局,写一个最简的等宽布局。

.row {
    display: flex;
    
    .col {
        flex-grow: 1;
        flex-basis: 0;
    }
}
复制代码

没错,这就是使用 Flex 布局实现一个等宽布局的所有代码了。如果不考虑中间的空白行,只需要 7 行代码。

这里的原理是,我们将所有 Flex 项目的 flex-basis 设置为 0 了,就是说这些 Flex 项目在 grow 或 shrink 之前都没有宽度,是一样长的。这样最终计算出来的主轴空间会平均地分配给了每个 Flex 项目,这样它们就等宽了。

到这里,我们所写的这个简易栅格布局有两个局限:

  1. 不能布局非等宽项目。
  2. 不支持换行。

换行的话很好弄,为 Flex 容器加个 flex-wrap: wrap 就可以了。那怎样处理“非等宽项目”排列布局呢。

为了能实现非等宽项目的布局,我们的思路是:禁用 Flex 项目的伸缩特性,使用百分比 width 指定宽度

首先,禁用 Flex 项目的伸缩特性,使用到的属性如下:

flex-shrink: 0;
flex-grow: 0;
flex-basis: 0;
复制代码

这三个属性等价的快捷写法是:

flex: none;
复制代码

然后就是使用百分比 width 指定宽度了。

我们实现的是一行最多 12 列的栅格布局。也就是说把一行划分成 12 列,每一列的宽度大约占总宽度的 8.33%。我们用 .is-列数 指定一个项目占据的列数:

  • .is-1:占据 1 列,也就是 1/12 宽
  • .is-2:占据 2 列,也就是 1/6 宽
  • .is-3:占据 3 列,也就是 1/4 宽
  • .is-4:占据 4 列,也就是 1/3 宽
  • .is-5:占据 5 列,也就是 5/12 宽
  • .is-6:占据 6 列,也就是 1/2 宽
  • .is-7:占据 7 列,也就是 7/12 宽
  • .is-8:占据 8 列,也就是 2/3 宽
  • .is-9:占据 9 列,也就是 3/4 宽
  • .is-10:占据 10 列,也就是 5/6 宽
  • .is-11:占据 11 列,也就是 11/12 宽
  • .is-12:占据 12 列,也就是占满整个宽度

根据这个规律,我们可以很容易地写出栅格布局代码:

$columns: 12;

.row {
    display: flex;
    
    .col {
        flex-grow: 1;
        flex-basis: 0;
        
        @for $i from 1 through 12 {
            &.is-#{$i} {
                flex: none;
                width: percentage($i / 12);
            }
        }
    }
}
复制代码

这里我们使用 @for 指令的 @for $var from <start> through <end> 语法,从 1 递增到 12,定义了 .is-*这一系列类名,原理就是我们说过的禁用了 Flex 项目的伸缩特性,指定给它百分比宽度。怎么样,很简单吧。

接下来再加上折行(.row.is-multiline)和 Flex 项目偏移(.is-offset-*)的支持。

我们总揽下代码:

$columns: 12;

.row {
    display: flex;
    
    &.is-multiline {
        flex-wrap: wrap;   
    }
    
    .col {
        flex-grow: 1;
        flex-basis: 0;
        
        @for $i from 1 through 12 {
            &.is-#{$i} {
                flex: none;
                width: percentage($i / 12);
            }
            &.is-offset-#{$i} {
                margin-left: percentage($i / 12);
            }
        }
    }
}
复制代码

.is-multiline 是跟随 .row 一起使用的,得到的就是 flex-wrap: wrap 的效果;项目偏移则借助 margin-left 属性实现。

到这里,我们的 12 列栅格布局就写完了 ヾ(◍°∇°◍)ノ゙

完整代码

我们把上面两部分的代码整合起来,就能得到一个最小的响应式布局系统了~ O(∩_∩)O

$breakpoints: (
    // Extra small screen / phone
    xs: 0,
    // Small screen / phone
    sm: 576px,
    // Medium screen / tablet
    md: 768px,
    // Large screen / desktop
    lg: 992px,
    // Extra large screen / wide desktop
    xl: 1200px
);

$container-max-widths: (
    xs: none,
    sm: 540px,
    md: 720px,
    lg: 960px,
    xl: 1140px
);

.container {
    margin-left: auto;
    margin-right: auto;
}

@each $device, $breakpoint in $breakpoints {
    @media only screen and (min-width: $breakpoint) {
        .container {
            max-width: map-get($container-max-widths, $device);
        }
    }
}

$columns: 12;

.row {
    display: flex;
    
    &.is-multiline {
        flex-wrap: wrap;   
    }
    
    .col {
        flex-grow: 1;
        flex-basis: 0;
        
        @for $i from 1 through 12 {
            &.is-#{$i} {
                flex: none;
                width: percentage($i / 12);
            }
            &.is-offset-#{$i} {
                margin-left: percentage($i / 12);
            }
        }
    }
}
复制代码

可以在此查看效果。

当然,更多其他丰富的功能任君添加,这里只是提供了一个最简单的代码实现。

参考链接

Grid system, by getbootstrap.com

贡献指北

感谢你花费宝贵的时间⏲️阅读这篇文章。

如果你觉得这篇文章让你的生活美好了一点点,欢迎鼓(diǎn)励(zàn)?。如果能在文章下面留下你宝贵的评论或意见是再合适不过的了,因为研究证明,参与讨论比单纯阅读更能让人对知识印象深刻?。

(完)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现一个最小的 CSS 响应式布局系统 的相关文章

  • 程序员面试必备书单

    点击关注异步图书 xff0c 置顶公众号 每天与你分享 IT好书 技术干货 职场知识 Tips 参与文末话题讨论 xff0c 即有机会获得异步图书一本 世上最快乐的事 xff0c 莫过于为理想奋斗 一个满意的工作 xff0c 便是为理想奋斗
  • vnc linux 终端打不开,vnc连接后只能看到终端

    我在windows安装了VNC Viewer xff0c 远程链接ubunt12 04服务器 xff0c 发现远程桌面只有一个终端 xff0c 没有桌面 从网上查了一些资料 xff0c 问题得以解决 xff0c 记录如下 xff1a 修改
  • ubuntu11.04下CUDA4.0的安装与配置

    ubuntu11 04下CUDA4 0的安装与配置 1 xff1a 下载CUDA 4 0 安装官网最新的显卡驱动 xff1a 安装方法可以参考 xff1a Ubuntu11 04下安装Nvidia显卡驱动的方法 然后从NVIDIA网站 xf
  • MySQL中如何定位DDL被阻塞的问题

    在生产环境中 xff0c 执行了一个DDL xff0c 发现很久都没有执行完 xff0c 是不是被阻塞了 xff1f 要怎么解决 xff1f 实际上 xff0c 如何解决DDL阻塞的问题 xff0c 是MySQL中一个共性且高频的问题 下面
  • oracle中的index函数,Oracle中的索引详解(整理)

    一 ROWID的概念 存储了row在数据文件中的具体位置 xff1a 64位 编码的数据 xff0c A Z a z 0 9 43 和 xff0c row在数据块中的存储方式 SELECT ROWID last name FROM hr e
  • KM算法学习笔记

    二分图定义 图的顶点恰好可以分成两个集合 xff0c 同一个集合内的顶点间不允许有边 xff0c 处在不同集合的顶点允许有边相连 问题分类 最大匹配问题 xff1a 匈牙利算法 Hopcroft Karp算法最优权值匹配问题 xff1a K
  • [转]GStreamer资料(摄像头采集,视频保存,远程监控)DVR

    http blog csdn net wzwxiaozheng archive 2010 12 26 6099397 aspx GStreamer资料整理 包括摄像头采集 视频保存 远程监控 流媒体RTP传输 1 gstreamer开发手册
  • HDFS的基础组成部分及基础操作

    HDFS组件结构图解说 xff1a 1 如图所示中 xff0c NameNode充当master角色 xff0c 职责包括 xff1a 管理文档系统的命名空间 namespace xff1b 调节客户端访问到需要的文件 存储在DateNod
  • 在XP下使用putty连接虚拟机中的linux出现主机拒绝的问题解决办法

    XP下的Linux虚拟机无法与主机ping通但主机可以ping通虚拟机的问题也可以用下面办法解决 xff01 一 首先windows的ip地址段必须和linux的ip地址段相同 xff0c 具体方法百度 xff0c Google下 xff0
  • Lodash学习笔记 - compact函数

    百忙之中 xff08 闲来无事 xff09 想抽点时间好好读一下源码 xff0c 于是就选了Lodash来写一个系列罢 读源码顺序就按照loadsh文档顺序来 文档地址 xff1a 中文文档 英文文档 源码地址 xff1a gayhub c
  • Ubuntu16.04调整屏幕分辨率至1920*1080

    安装好ubuntu 16 04桌面版后 xff0c 发现屏幕分辨率调整选项里没有1920 1080这一选项 xff0c 经过一番查找 xff0c 可通过如下方式进行屏幕分辨率设置 以下操作均在ubuntu 16 04桌面版操作 xff0c
  • 请查资料了解这些术语:/dev/hda, /dev/hdb, /dev/sda, /dev/sdb, 他们之间有什么区别?...

    1 请查资料了解这些术语 xff1a dev hda dev hdb dev sda dev sdb 他们之间有什么区别 xff1f 答 xff1a hda一般是指IDE接口的硬盘 xff0c hda指第一块硬盘 xff0c hdb指第二块
  • ubuntu常用技巧

    安装 xff1a 配置 xff1a AMD xff08 939 xff09 3500 xff0c 升技av8 xff08 k8t800pro xff09 xff0c 创见1GBddr400 xff0c 希捷250GB xff08 IDE x
  • 2016计算机cpu,看完你再评论!2016年CPU市场展望分析

    PConline 杂谈 相比早几年 xff0c 2016年有点特别 xff0c CPU市场终于让人看到折腾的盼头 xff0c 今年Intel和AMD都将有重量级的新产品上市 xff0c Intel将会在旗舰系列上推出14nm的Broadwe
  • MySQL中删除操作Delete、Truncate、Drop用法比较

    1 执行速度比较 Delete Truncate Drop关键字都可以删除数据 drop gt truncate gt delete 2 原理方面 2 1 delete delete 属于数据库 DML 操作语言 xff0c 只会删除数据表
  • floating IP 原理分析 - 每天5分钟玩转 OpenStack(107)

    上一节我们通过 Web UI 创建为 cirros vm3 分配了浮动 IP xff0c 今天将分析其工作原理 首先查看 router 的 interface 配置 xff1a 可以看到 xff0c floating IP 已经配置到 ro
  • linux移动硬盘挂载错误,suse挂载移动硬盘出错

    suse挂载移动硬盘出错 发布时间 2008 04 29 11 46 54来源 红联作者 Dnirta 刚刚挂移动硬盘想装个东西 xff0c 结果盘符出来了 xff0c 却打不开 有提示 root 64 localhost mount t
  • 【webapp的优化整理】要做移动前端优化的朋友进来看看吧

    单页or多页 本文仅代表个人观点 xff0c 不足请见谅 xff0c 欢迎赐教 webapp 小钗从事单页相关的开发一年有余 xff0c 期间无比的推崇webapp的网站模式 xff0c 也整理了很多移动开发的知识点 xff0c 但是现在回
  • Dell的Linux服务器开机按F1解决方法

    最近买了些二手服务器 xff0c dell品牌 xff0c 性价比还不错 xff0c 但是一台dell 服务器开机总是提示按F1才能进系统 到底应该怎么解决呢 xff1f 请问我的电脑开机老是提示 strike the f1 key to
  • ADB 操作命令详解及用法大全

    一 ADB是什么 xff1f ADB xff0c 即 Android Debug Bridge 是一种允许模拟器或已连接的 Android 设备进行通信的命令行工具 xff0c 它可为各种设备操作提供便利 xff0c 如安装和调试应用 xf

随机推荐

  • 在OpenResty中使用淘宝的concat进行css和js合并,同时支持GZIP静态压缩

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • cygwin64安装wget和apt-cyg

    说实话 xff0c 网上的教程要么不适用 xff0c 要么不能用 xff0c 唯有多次试错之后才杀出一条血路 1 安装cygwin 2 勾选wget 这个如果忘记勾选了 xff0c 就再次打开setup exe 选择如下操作 xff0c 即
  • React系列——websocket群聊系统在react的实现

    前奏 这篇文章仅对不熟悉在react中使用socket io的人 以及websocket入门者有帮助 下面这个动态图展示的聊天系统是用react 43 express 43 websocket搭建的 xff0c 很模糊吧 xff0c 要得就
  • JNA 实际开发中若干问题解决方法(二)

    1 JNA 中 byte 类型映射问题 在之前的文章中 xff0c 我们知道 JNA 中 xff0c char 和 char 类型都可以映射为 byte 类型 xff0c 通常来说也就是 byte 具有通用性 在实际开发中 xff0c 我们
  • 独家解读 | 智能驾驶视觉技术领域四类供应商及其商业化路径

    9 月 3 日 xff0c 雷锋网新智驾正式对外发布了 2018 智能驾驶视觉技术行业研究报告 xff0c 对智能驾驶技术感兴趣的读者可加入 新智驾会员计划 免费阅读本报告 xff0c 也可以通过官方渠道单独购买后进行查阅 首份报告发布两天
  • MySQL存储过程与存储函数

    1 创建存储过程 存储过程就是一条或者多条 SQL 语句的集合 xff0c 可以视为批文件 它可以定义批量插入的语句 xff0c 也可以定义一个接收不同条件的 SQL 创建存储过程的语句为 create procedure xff0c 创建
  • Vue+SpringBoot实现增删改查

    Vue 43 Spring boot Vue前端 Vue新建项目 当前我是用的是vue脚手架3 4 1版本 github地址 xff1a github com liangcongco vue create vue demo 新建项目 spa
  • 一例关于无法删除VMware虚拟机文件的案例

    关键字 xff1a VMware ESXi 虚拟机 操作背景 xff1a 由于运维不当导致一台虚拟机挂掉 xff0c 期望删除该VM的文件夹 xff0c 但从vCenter界面或者用指令界面 xff0c 均提示无法删除 xff0c 文件被占
  • PS安装扩展面板提示无法加载,因为它未经正确签署解决方法(适用于Mac/Win)

    最近发现好多小伙伴在使用Photoshop Mac端或者win端安装ps扩展面板时 总会遇到Photoshop错误提示无法加载 因为它未经正确签署 今天小编就和大家分享解决Mac Win端ps扩展面板提示无法加载 因为它未经正确签署解决方法
  • FTP连接不上的解决方法

    1 注意内网IP和外网IP 2 检查ftp服务是否启动 xff08 面板首页即可看到 xff09 3 检查防火墙20端口 ftp 21端口及被动端口39000 40000是否放行 xff08 如是腾讯云 阿里云等还需检查安全组 xff09
  • Arduino和C51开发OLED显示屏

    技术 xff1a 51单片机 Arduino OLED显示屏 U8glib 概述 OLED显示屏常常用作为智能产品的显示设备 xff0c 本文简单介绍OLED显示屏的使用方法 详细 代码下载 xff1a http www demodashi
  • mac 查看 本地网络代理

    networksetup listallnetworkservices 转载于 https www cnblogs com yshuai p 7813258 html
  • 常用的ROS命令

    在这里记一下 xff0c 以免以后忘记了 打开ros master xff1a roscore 查看topic列表 xff1a rostopic list v 打印topic内容 xff1a rostopic echo topic 将bag
  • platform下的js分析_2

    目录 主要包含 url js utils js requiring frame js attribute js CCMacro js CCSys js CCScreen js CCVisibleRect js callbacks invok
  • 重学前端学习笔记(六)--JavaScript类型有哪些你不知道的细节?

    笔记说明 重学前端是程劭非 xff08 winter xff09 前手机淘宝前端负责人 在极客时间开的一个专栏 xff0c 每天10分钟 xff0c 重构你的前端知识体系 xff0c 笔者主要整理学习过程的一些要点笔记以及感悟 xff0c
  • 用nvm安装node后,发现npm下载总是失败的解决办法

    用nvm安装node后 xff0c 发现npm下载总是失败的解决办法 执行安装命令如下出现npm下载失败 xff0c 尝试多次都不成功 xff1a C windows system32 gt nvm install 14 17 3 Down
  • OpenStack —— DevStack一键自动化安装

    一 DevStack介绍 Devstack 目前是支持Ubuntu16 04和CentOS 7 xff0c 而且Devstack官方建议使用Ubuntu16 04 xff0c 所以我们使用Ubuntu 16 04进行安装 默认无论是Devs
  • 树莓派3b+安装

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 贴散热片 xff1a 背面一片 xff0c 正面两篇 二 系统安装 xff1a 1 使用SD Formatter格式化SD卡 2 使用Win32DiskImager写入
  • Amap地图轨迹

    最近在做运动相关的项目 xff0c 需要运动轨迹 xff0c 接了一下Google xff0c 头一天还能获取Location xff0c 之后就没法用了 xff0c 所以换成高德 xff0c 高德的地图包Amap 使用高德地图定位Loca
  • 实现一个最小的 CSS 响应式布局系统

    阳光里她在院子中央晾晒着衣裳 在四季的风中她散着头发安慰着时光 赵雷 南方姑娘 响应式布局系统 xff0c 在现在流行的 CSS 框架中已经非常常见了 它主要由容器类和约定一行列数的栅格系统组成 xff0c 组成了一个框架的骨架 在流行的前