0x00 简介
前文 📚 Layout 拾遗 提到了栅格布局系统中响应式布局的实现方式媒体查询
,本文将对其深入分析, 耐心读完,相信会对您有所帮助。
0x01 媒体查询
媒体查询 (Media queries )是实现响应式设计的最常见方法,它可以让我们根据设备的大致类型(如打印、手机、平板或电脑等)或者特定的特征和设备参数(例如屏幕分辨率和浏览器视口宽度)来调整网站或应用。 例如,缩小小型设备上的字体大小,判断手机朝向(横屏或竖屏)等。
CSS 语法
媒体查询语法通常使用 @media
(@规则
), 可用于基于一个或多个媒体查询的结果来应用样式表。
通过指定的媒体类型与正在显示文档的设备类型匹配,并且媒体查询中的所有表达式均为 true
,将应用样式规则。
复制 // 媒体类型 媒体特性表达式
@media media-type and (media-feature-rule) {
/* CSS rules go here */
}
媒体类型
媒体类型 (Media types )描述设备的一般类别。可以指定的媒体类型为:
screen
主要用于屏幕(计算机屏幕、平板电脑、智能手机)。
在不使用 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
。
在文件 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 */
}
0x05 📚 参考
“使用媒体查询”,MDN
“Media_queries”,MDN
"@规则",MDN
screen sizes
“sass 在线编辑器”,sassmeister.com