0x00 简介
前文 📚 Layout拾遗 提到了栅格布局系统中响应式布局的实现方式媒体查询,本文将对其深入分析, 耐心读完,相信会对您有所帮助。
更多组件分析详见 👉 📚 Element UI 源码剖析组件总览 。
本专栏的 gitbook 版本地址已经发布 📚《learning element-ui》 ,内容同步更新中!
0x01 媒体查询
媒体查询(Media queries)是实现响应式设计的最常见方法,它可以让我们根据设备的大致类型(如打印、手机、平板或电脑等)或者特定的特征和设备参数(例如屏幕分辨率和浏览器视口宽度)来调整网站或应用。 例如,缩小小型设备上的字体大小,判断手机朝向(横屏或竖屏)等。
CSS 语法
媒体查询语法通常使用 @media(@规则), 可用于基于一个或多个媒体查询的结果来应用样式表。
通过指定的媒体类型与正在显示文档的设备类型匹配,并且媒体查询中的所有表达式均为 true,将应用样式规则。
// 媒体类型 媒体特性表达式
@media media-type and (media-feature-rule) {
/* CSS rules go here */
}
媒体类型
媒体类型(Media types)描述设备的一般类别。可以指定的媒体类型为:
all适用于所有设备。print适用于在打印预览模式下。screen主要用于屏幕(计算机屏幕、平板电脑、智能手机)。speech主要应用于屏幕阅读器等发声设备。
在不使用
not或only操作符的情况下,媒体类型是可选的,默认为all。
媒体特性
媒体特性(Media features)描述了user agent、输出设备,或是浏览环境的具体特征。媒体特性表达式是完全可选的,它负责测试这些特性或特征是否存在、值为多少。每条媒体特性表达式都必须用括号括起来。
最常用的特性是视口宽度,可以使用min-width(最常用)、max-width和width媒体特性,在视口宽度大于或者小于某个大小——或者是恰好等于某个大小——的时候,应用CSS样式规则。
逻辑运算符
逻辑操作符(logical operators) 使用 not, and, only和, (逗号) 构建复杂的媒体查询。
and运算符用来把多个媒体属性组合起来,合并到同一条媒体查询中。只有当每个属性都为真时,这条查询的结果才为真。not运算符用于否定媒体查询,如果不满足这个条件则返回true,否则返回false。 如果出现在以逗号分隔的查询列表中,它将仅否定应用了该查询的特定查询。not关键字不能用于否定单个媒体功能表达式,而只能用于否定整个媒体查询。only运算符仅在整个查询匹配时才用于应用样式,并且对于防止老式浏览应用所选样式很有用。,逗号将多个媒体查询合并为一个规则。 逗号分隔列表中的每个查询都与其他查询分开处理。 因此,如果列表中的任何查询为true,则整个@media语句均返回true。 换句话说,列表的行为类似于逻辑或or运算符。
使用
not,only运算符,必须指定媒体类型。
在老式浏览器中将
@media only screen and (min-width: 992px) {...}简单地解释为only,因为没有叫only的设备,所以老式浏览器不会应用样式。 当不使用only时,将@media screen and (min-width: 992px) {...}简单地解释为screen,忽略查询的其余部分,应用样式。
0x02 断点
断点(Breakpoints) 是响应式设计的基石。 它是可自定义的宽度,使用它可以控制何时可以在特定视口或设备大小下调整布局。
断点设置
参照了 Bootstrap 的 响应式设计,预设了五个响应尺寸:xs、sm、md、lg 和 xl。
| 断点 | 类中缀 | 分辨率 | 设备 |
|---|---|---|---|
| X-Small | xs | <767px | 超小屏幕 手机 |
| Small | sm | ≥768px | 小屏幕 平板 |
| Medium | md | ≥992px | 中等屏幕 桌面显示器 |
| Large | lg | ≥1200px | 大屏幕 大桌面显示器 |
| Extra large | xl | ≥1920px | 超大屏幕 大桌面显示器 |
在文件 theme-chalk\src\common\var.scss 定义了这些断点。
/* Break-point
--------------------------*/
$--sm: 768px !default;
$--md: 992px !default;
$--lg: 1200px !default;
$--xl: 1920px !default;
// 断点Map
$--breakpoints: (
"xs": (
max-width: $--sm - 1,
),
"sm": (
min-width: $--sm,
),
"md": (
min-width: $--md,
),
"lg": (
min-width: $--lg,
),
"xl": (
min-width: $--xl,
),
);
0x03 组件响应式实现
@mixin res()
在文件 theme-chalk\src\mixins\mixins.scss 定义了指令 res构建css,使用媒体查询来创建关键的分界点阈值。
/* Break-points
-------------------------- */
// 断点Map
$--breakpoints: (
"xs": ( max-width: 767px ),
"sm": ( min-width: 768px ),
"md": ( min-width: 992px ),
"lg": ( min-width: 1200px ),
"xl": ( min-width: 1920px ),
);
@mixin res($key, $map: $--breakpoints) {
// 循环断点Map,如果存在则返回
@if map-has-key($map, $key) {
@media only screen and #{inspect(map-get($map, $key))} {
@content;
}
} @else {
@warn "Undefeined points: `#{$map}`";
}
}
指令功能逻辑如下:
- 指令
res接受两个参数$key(响应尺寸) 和$map(断点Map)。 - 指令内部使用函数
map-has-key($map,$key)作用是根据$key参数,返回$key在$map中对应的 value 值。如果$key不存在$map中,将返回 null 值(此时生成警告断点未定义Undefeined points)。 - 若返回 true,使用函数
map-get($map,$key)返回$key在$map中对应的 value 值。 - 使用函数
inspect($value)将其转成字符串,使用插值#{}、@content生成 媒体查询。
// 参数 $key 值为 xs
// 获取Map
map-get($map, $key) => ( max-width: 767px )
// 返回string
inspect(map-get($map, $key)) => '( max-width: 767px )'
@media only screen and #{inspect(map-get($map, $key))} { @content; }
// 编译结果
@media only screen and (max-width: 767px) { ... }
在栅格系统中,媒体查询通过断点构建CSS。响应式布局五个响应尺寸样式如下:
/* 超小屏幕(手机,小于 768px) */
@media only screen and (max-width: 767px) { ... }
/* 小屏幕(平板,大于等于 768px) */
@media only screen and (min-width: 768px) { ... }
/* 中等屏幕(桌面显示器,大于等于 992px) */
@media only screen and (min-width: 992px) { ... }
/* 大屏幕(大桌面显示器,大于等于 1200px) */
@media only screen and (min-width: 1200px) { ... }
/* 超大屏幕(大桌面显示器,大于等于 1920px) */
@media only screen and (min-width: 1920px) { ... }
0x04 基于断点的隐藏实现
Element 额外提供了一系列类名,用于在某些条件下隐藏元素。
使用方式
首先,项目引入样式文件:
import 'element-ui/lib/theme-chalk/display.css';
然后将这些类名可以添加在任何 DOM 元素或自定义组件上。
hidden-xs-only- 当视口在xs尺寸时隐藏hidden-sm-only- 当视口在sm尺寸时隐藏hidden-sm-and-down- 当视口在sm及以下尺寸时隐藏hidden-sm-and-up- 当视口在sm及以上尺寸时隐藏hidden-md-only- 当视口在md尺寸时隐藏hidden-md-and-down- 当视口在md及以下尺寸时隐藏hidden-md-and-up- 当视口在md及以上尺寸时隐藏hidden-lg-only- 当视口在lg尺寸时隐藏hidden-lg-and-down- 当视口在lg及以下尺寸时隐藏hidden-lg-and-up- 当视口在lg及以上尺寸时隐藏hidden-xl-only- 当视口在xl尺寸时隐藏
实现原理
文件 theme-chalk\src\common\var.scss 定义了隐藏类断点Map$--breakpoints-spec ,使用逻辑运算符 and,让媒体查询能跨越多个断点宽度。
$--breakpoints-spec: (
"xs-only": (
max-width: $--sm - 1,
),
"sm-and-up": (
min-width: $--sm,
),
"sm-only": "(min-width: #{$--sm}) and (max-width: #{$--md - 1})",
"sm-and-down": (
max-width: $--md - 1,
),
"md-and-up": (
min-width: $--md,
),
"md-only": "(min-width: #{$--md}) and (max-width: #{$--lg - 1})",
"md-and-down": (
max-width: $--lg - 1,
),
"lg-and-up": (
min-width: $--lg,
),
"lg-only": "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})",
"lg-and-down": (
max-width: $--xl - 1,
),
"xl-only": (
min-width: $--xl,
),
);
转译后内容如下,定了关于视口宽度的各种媒体查询规则。
$--breakpoints-spec: (
"xs-only":( max-width: 767px ),
"sm-and-up": ( min-width: 768px ),
"sm-only": "(min-width: 768px) and (max-width: 991px)",
"sm-and-down": (max-width: 991px),
"md-and-up": ( min-width: 992px ),
"md-only": "(min-width: 992px) and (max-width: 1199px)",
"md-and-down": (max-width: 1199px),
"lg-and-up": (min-width: 1200px),
"lg-only": "(min-width: 1200px) and (max-width: 1919px)",
"lg-and-down": (max-width: 1919px),
"xl-only": (min-width: 1920px),
);
使用指令 res 生成带前缀 hidden的隐藏类。隐藏类CSS规则 display: none !important; 用于隐藏元素。
// 类前缀
.hidden {
// 遍历 Map $--breakpoints-spec
@each $break-point-name, $value in $--breakpoints-spec {
// 生成.hidden-#{$break-point-name} 如 hidden-xs-only hidden-sm-only
&-#{$break-point-name} {
// 生成媒体查询
@include res($break-point-name, $--breakpoints-spec) {
display: none !important;
}
}
}
}
最终生成 display.css,内容如下:
// 当视口在 `xs` 尺寸时
@media only screen and (max-width: 767px) { /* .hidden-xs-only */ }
// 当视口在 `sm` 及以上尺寸时
@media only screen and (min-width: 768px) { /* .hidden-sm-and-up */ }
// 当视口在 `sm` 尺寸时
@media only screen and (min-width: 768px) and (max-width: 991px) { /* .hidden-sm-only */ }
// 当视口在 `sm` 及以下尺寸时
@media only screen and (max-width: 991px) { /* .hidden-sm-and-down */ }
// 当视口在 `md` 及以上尺寸时
@media only screen and (min-width: 992px) { /* .hidden-md-and-up */ }
// 当视口在 `md` 尺寸时
@media only screen and (min-width: 992px) and (max-width: 1199px) { /* .hidden-md-only */ }
// 当视口在 `md` 及以下尺寸时
@media only screen and (max-width: 1199px) { /* .hidden-md-and-down */ }
// 当视口在 `lg` 及以上尺寸时
@media only screen and (min-width: 1200px) { /* .hidden-lg-and-up */ }
// 当视口在 `lg` 尺寸时
@media only screen and (min-width: 1200px) and (max-width: 1919px) { /* .hidden-lg-only */ }
// 当视口在 `lg` 及以下尺寸时
@media only screen and (max-width: 1919px) { /* .hidden-lg-and-down */ }
// 当视口在 `xl` 尺寸时
@media only screen and (min-width: 1920px) { /* .hidden-xl-only */ }
📚参考&关联阅读
“使用媒体查询”,MDN
“Media_queries”,MDN
"@规则",MDN
screen sizes
“sass 在线编辑器”,sassmeister.com
关注专栏
如果本文对您有所帮助请关注➕、 点赞👍、 收藏⭐!您的认可就是对我的最大支持!
此文章已收录到专栏中 👇,可以直接关注。