探索前端响应式设计:实现跨设备无缝体验
Responsive Design,响应式设计是一种让网站或应用能够根据访问设备的不同特性(如视窗大小、屏幕分辨率等),智能地调整布局、图片大小、交互方式以及功能的设计方法。其目标是在任何设备上都能为用户提供最佳的视觉效果和操作体验。响应式设计可以通过有条件的应用 css 规则、媒体查询、容器查询和 flexbox 布局(flex 和 grid)来完成。
一、媒体查询(Media Queries)
媒体查询(Media Queries)是 CSS3 中的一项核心特性,它允许开发人员编写针对不同设备环境和视口条件的样式规则。媒体查询通过对设备的媒体类型、特性或某些特定条件进行检测,使得 CSS 可以根据这些条件的变化动态地应用相应的样式,从而实现网页内容在不同设备上的适配和响应式布局。
1.1 移动优先设计
移动优先设计是设计和构建响应式 Web 应用程序时可以采用的原则。
1.2 设置 viewport
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<!-- 智能手表 -->
<!-- <meta name="disable-adaptations" content="watch" /> -->
- width=device-width,网页的宽度等于设备的物理宽度
- initial-scale=1,初始缩放级别,即页面加载时的缩放比例应为 1
- viewport-fit=cover,此属性适用于具有刘海屏或圆角屏幕的现代智能手机。设置为 cover 意味着网页内容将延伸至整个可视区域,包括可能被设备“刘海”或“下巴”遮挡的部分。这就要求网页设计时考虑到安全区域(safe area)的概念,避免重要内容被遮挡。
1.3 禁止用户人为缩放文字大小
最好限制字体最小为 16px
html {
-moz-text-size-adjust: none;
-webkit-text-size-adjust: none;
text-size-adjust: none;
}
1.4 @media
(1)媒体类型(Media Types)
all
: 包括所有设备,此类型下的样式在任何设备上都会被应用。screen
: 专用于计算机显示器、平板电脑和智能手机等具有显示屏的设备。print
: 在打印预览或者实际打印页面时生效,应用于打印样式。speech
: 针对屏幕阅读器和其他基于语音的用户代理。
(2)媒体特性(Media Features) 体特性是媒体查询中用于检测设备具体特性的关键词和值对:
width
和height
:检测视口或设备的宽度和高度。device-width
和device-height
:检测物理设备屏幕本身的宽度和高度,而非浏览器视口大小。orientation
:检测设备的方向,取值为 portrait(竖屏)或 landscape(横屏)。aspect-ratio
、device-aspect-ratio
:检测设备宽高比。color
、color-index
、monochrome
:关于颜色深度和灰度级的特性。resolution
:检测设备的分辨率或 dpi(每英寸点数)。
(3)常设宽度
320px
:智能手机视口的最小宽度480px
:智能手机和平板电脑的大致边界768px
:原始 ipad 的分辨率为 768x10241024px
:同上1280px
:16:9 720p(HD)显示屏的标准宽度
@media screen and (max-width: 479px) {
body {
background-color: #ccc;
}
}
@media screen and (min-width: 480px) {
body {
background-color: #fff;
}
}
@media screen and (width < 480px) {
body {
background-color: #fff;
}
}
@media screen and (width >= 480px) {
body {
background-color: #f0f0f0;
}
}
二、Flexbox
伸缩布局,一维布局
2.1 基本概念
- main axis:水平主轴
- cross axis:垂直的交叉轴
- flex item:容器中的单元,项目
- main size:每个项目占据的主轴空间
- cross size:每个项目占据的交叉轴的空间
2.2 Flex 容器(父)
(1) 指定某个容器为 flex 布局
.container {
display: flex | inline-flex;
}
- flex:块状的
- inline-flex:行内的
- 设置 flex 布局,子元素的 float、clear、vertical-align 的属性将会失效。
(2) 设置在 flex 容器上的属性
flex-direction
:决定主轴的方向(即项目的排列方向)
.container {
/* row,主轴为水平方向,起点在左端。 */
/* row-reverse:主轴为水平方向,起点在右端 */
/* column:主轴为垂直方向,起点在上沿 */
/* column-reverse:主轴为垂直方向,起点在下沿 */
flex-direction: row | row-reverse | column | column-reverse;
}
flex-wrap
:决定容器内项目是否可换行
.container {
/* nowrap 不换行 */
/* wrap:项目主轴总尺寸超出容器时换行,第一行在上方 */
/* wrap-reverse:换行,第一行在下方 */
flex-wrap: nowrap | wrap | wrap-reverse;
}
flex-flow
: flex-direction 和 flex-wrap 的简写形式
.container {
/* 默认值为: row nowrap */
flex-flow: <flex-direction> || <flex-wrap>;
}
justify-content
:定义项目在主轴的对齐方式
.container {
/* flex-start 左对齐 */
/* flex-end:右对齐 */
/* center:居中 */
/* space-between:两端对齐,项目之间的间隔相等,即剩余空间等分成间隙。 */
/* space-around:每个项目两侧的间隔相等,所以项目之间的间隔比项目与边缘的间隔大一倍。 */
justify-content: flex-start | flex-end | center | space-between | space-around;
}
align-items
: 定义项目在交叉轴上的对齐方式
.container {
/* 默认值为 stretch 即如果项目未设置高度或者设为 auto,将占满整个容器的高度。 */
/* flex-start:交叉轴的起点对齐(上对齐) */
/* flex-end:交叉轴的终点对齐 */
/* center:交叉轴的中点对齐 */
/* baseline: 项目的第一行文字的基线对齐 */
align-items: flex-start | flex-end | center | baseline | stretch;
}
align-content
:定义多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用。- 当 flex-wrap 设置为 nowrap 时,项目不换行,容器只存在一根轴线。
- 当 flex-wrap 设置为 wrap 时,容器可能会出现多条轴线,这时可使用
align-content
属性。
/* 默认值为 stretch,多条轴线平分容器的垂直方向上的空间 */
/* flex-start:轴线全部在交叉轴上的起点对齐 */
/* flex-end:轴线全部在交叉轴上的终点对齐 */
/* center:轴线全部在交叉轴上的中间对齐 */
/* space-between:轴线两端对齐,之间的间隔相等,即剩余空间等分成间隙。 */
/* space-around:每个轴线两侧的间隔相等,所以轴线之间的间隔比轴线与边缘的间隔大一倍。 */
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
2.3 Flex 项目(子)
设置中 item 上的属性。
order
: 定义项目在容器中的排列顺序,数值越小,排列越靠前,默认值为 0
.item {
order: <integer>;
}
flex-basis
:定义在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间
.item {
/* 默认值:auto,即项目本来的大小 */
/* 当主轴为水平方向的时候,当设置了 flex-basis,项目的宽度设置值会失效,flex-basis 需要跟 flex-grow 和 flex-shrink 配合使用才能发挥效果。 */
flex-basis: <length> | auto;
}
flex-grow
: 定义项目的放大比例 当所有的项目都以 flex-basis 的值进行排列后,仍有剩余空间,这时候 flex-grow 就会发挥作用。
.item {
/* 默认值为 0,即如果存在剩余空间,也不放大 */
flex-grow: <number>;
}
flex-shrink
: 定义项目的缩小比例
.item {
/* 默认值: 1,即如果空间不足,该项目将缩小,负值对该属性无效。 */
flex-shrink: <number>;
}
flex
: flex-grow, flex-shrink 和 flex-basis 的简写
.item {
/* 假设三个属性同样取默认值,则 flex 的默认值是 0 1 auto。 */
flex: none | [ < "flex-grow" > < "flex-shrink" >? || < "flex-basis" >];
}
align-self
:允许单个项目有与其他项目不一样的对齐方式 单个项目覆盖 align-items 定义的属性
.item {
/* 默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch */
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
三、CSS Grid
网格布局,CSS 二维布局
3.1 基本概念
- 容器:采用网格布局的区域,container。
- 项目:容器内部采用网格定位的子元素,item。
- 行:容器里面的水平区域,row。
- 列:容器里面的垂直区域,column。
- 单元格:行和列的交叉区域,cell。
- 网格线:划分网格的线,grid line。水平网格线划分出行,垂直网格线划分出列。
3.2 容器
(1)指定容器采用网格布局
/* 设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。 */
div {
display: grid | inline-grid;
}
(2)容器上的属性
1)grid-template-columns
和 grid-template-rows
grid-template-columns 属性定义每一列的列宽 grid-template-rows 属性定义每一行的行高
.container {
display: grid;
/* 绝对值 */
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
/* 百分比 */
grid-template-columns: 33.33% 33.33% 33.33%;
grid-template-rows: 33.33% 33.33% 33.33%;
/* repeat() */
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
/* 六列 */
grid-template-columns: repeat(2, 100px 20px 80px);
/* auto-fill 关键字,自动填充 */
grid-template-columns: repeat(auto-fill, 100px);
/* 与auto-fill的行为基本是相同的。只有当容器足够宽,可以在一行容纳所有单元格,并且单元格宽度不固定的时候,才会有行为差异:auto-fill会用空格子填满剩余宽度,auto-fit则会尽量扩大单元格的宽度。 */
grid-template-columns: repeat(auto-fit, 100px);
/* fr 关键字(fraction 的缩写,意为"片段"),片段之间的比例关系 */
grid-template-columns: 1fr 1fr;
/* fr可以与绝对长度的单位结合使用 */
grid-template-columns: 150px 1fr 2fr;
/* minmax() */
/* 函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。 */
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
/* auto 关键字 */
/* auto关键字表示由浏览器自己决定长度 */
grid-template-columns: 100px auto 100px;
/* 网格线的名称 */
/* c1 c2 c3 c4 */
grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
}
2)grid-row-gap、grid-column-gap、grid-gap 设置间隔
.container {
grid-row-gap: 20px;
grid-column-gap: 20px;
grid-gap: <grid-row-gap> <grid-column-gap>;
}
3)grid-template-areas 设置区域
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas:
"a b c"
"d e f"
"g h i";
}
4)grid-auto-flow :放置顺序,"先行后列","先列后行"
/* row-先行后列 */
/* column-先列后行 */
.container {
grid-auto-flow: column | row;
/* dense 尽可能填满空格 */
grid-auto-flow: row dense;
grid-auto-flow: column dense;
}
5)justify-items、align-items、place-items
justify-items
:设置单元格内容的水平位置(左中右)align-items
:设置单元格内容的垂直位置(上中下)place-items
:前面两个结合
.container {
/* start:对齐单元格的起始边缘 */
/* end:对齐单元格的结束边缘 */
/* center:单元格内部居中 */
/* stretch:拉伸,占满单元格的整个宽度(默认值) */
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
place-items: <align-items> <justify-items>;
}
6)justify-content、align-content、place-content
justify-content
属性是整个内容区域在容器里面的水平位置(左中右)align-content
属性是整个内容区域的垂直位置(上中下)place-content
属性是 align-content 属性和 justify-content 属性的合并简写形式
.container {
/* start - 对齐容器的起始边框 */
/* end - 对齐容器的结束边框 */
/* center - 容器内部居中 */
/* stretch - 项目大小没有指定时,拉伸占据整个网格容器 */
/* space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍 */
/* space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔 */
/* space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔 */
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
place-content: <align-content> <justify-content>;
}
7)grid-auto-columns、grid-auto-rows
grid-auto-columns
属性和grid-auto-rows
属性用来设置,浏览器自动创建的多余网格的列宽和行高。- 写法与
grid-template-columns
和grid-template-rows
完全相同。 - 如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
8)grid-template、grid
grid-template
:是 grid-template-columns、grid-template-rows 和 grid-template-areas 这三个属性的合并简写形式grid
:是 grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow 这六个属性的合并简写形式
3.3 项目
(1)项目属性
1)grid-column-start、grid-column-end、grid-row-start、grid-row-end
grid-column-start
:左边框所在的垂直网格线grid-column-end
:右边框所在的垂直网格线grid-row-start
:上边框所在的水平网格线grid-row-end
:下边框所在的水平网格线
.item-1 {
/* 跨两列 */
grid-column-start: 2;
grid-column-end: 4;
/* span 跨多少个网格 */
grid-column-start: span 2;
}
2)grid-column、grid-row
grid-column
属性是 grid-column-start 和 grid-column-end 的合并简写形式grid-row
属性是 grid-row-start 属性和 grid-row-end 的合并简写形式
.item {
grid-column: <start-line> / <end-line>;
grid-row: <start-line> / <end-line>;
}
.item-1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
/* 等同于 */
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}
3)grid-area
- 指定项目放在哪一个区域
- 还可用作 grid-row-start、grid-column-start、grid-row-end、grid-column-end 的合并简写形式
.item-1 {
grid-area: e;
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
grid-area: 1 / 1 / 3 / 3;
}
4)justify-self、align-self、place-self
justify-self
:设置单元格内容的水平位置(左中右),跟 justify-items 属性的用法完全一致,但只作用于单个项目。align-self
:设置单元格内容的垂直位置(上中下),跟 align-items 属性的用法完全一致,也是只作用于单个项目 -place-self
:是 align-self 属性和 justify-self 属性的合并简写形式。
.item {
/* start:对齐单元格的起始边缘 */
/* end:对齐单元格的结束边缘 */
/* center:单元格内部居中 */
/* stretch:拉伸,占满单元格的整个宽度(默认值) */
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
place-self: center center;
}
PS:网格布局、GRID GARDEN
四、可伸缩矢量图形(SVG)和响应式图片
4.1 SVG
使用 SVG 替代传统位图以保持图像在各种分辨率下的清晰度。
4.2 响应式图片
结合 HTML5 的 srcset 属性和 sizes 属性,可以按需加载适合当前设备分辨率的图片资源。
<img
srcset="
/path/to/img-44w.png 1x,
/path/to/img-66w.png 1.5x,
/path/to/img-88w.png 2x,
/path/to/img-132w.png 3x
"
/>
.selector {
height: 44px;
width: 44px;
/* 2x fallback for browsers which do not support image-set() */
background-image: url(/path/to/img-88w.png);
/* Safari only supports -webkit-image-set() */
background-image: -webkit-image-set(
url(/path/to/img-44w.png) 1x,
url(/path/to/img-66w.png) 1.5x,
url(/path/to/img-88w.png) 2x,
url(/path/to/img-132w.png) 3x
);
/* Standard syntax */
background-image: image-set(
url(/path/to/img-44w.png) 1x,
url(/path/to/img-66w.png) 1.5x,
url(/path/to/img-88w.png) 2x,
url(/path/to/img-132w.png) 3x
);
}
<img
srcset="
/path/to/img-320w.jpg 320w,
/path/to/img-480w.jpg 480w,
/path/to/img-640w.jpg 640w,
/path/to/img-960w.jpg 960w,
/path/to/img-1280w.jpg 1280w
"
sizes="(min-width: 768px) 480px, 100vw"
/>
五、响应式框架与工具
Tailwind CSS、Bootstrap 等框架是基于响应式设计开发的,它们会根据屏幕宽度自动调整布局。