媒体查询
0x00 简介
前文 📚 Layout 拾遗 提到了栅格布局系统中响应式布局的实现方式媒体查询
,本文将对其深入分析, 耐心读完,相信会对您有所帮助。
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 */
}
0x05 📚 参考
“使用媒体查询”,MDN “Media_queries”,MDN "@规则",MDN screen sizes “sass 在线编辑器”,sassmeister.com
最后更新于