CSS 主流布局进阶
- 前言
- 一、CSS 还原 UI 设计
- 二、布局的尺寸与位置
- 三、flex 弹性布局
- 四、grid 网格布局
- 1、grid 布局的基本概念
- 2、grid 容器
- (1)定义网格(显式)的行和列 —— grid-template-rows & grid-template-columns
- (2)网格命名及合并网格 —— grid-template-areas
- (3)网格定义、命名、合并的缩写 —— grid-template
- (4)网格间隙及简写 —— grid-row-gap、grid-column-gap & grid-gap
- (5)容器对齐方式及简写 —— justify-content、align-content & place-content
- (6)网格对齐方式及简写 —— justify-items、align-items & place-items
- (7)隐式网格的定义 —— grid-auto-rows、grid-auto-columns
- (8)repeat() 和 minmax()
- (9)指定项目排列方式 —— grid-auto-flow
- 3、grid 项目
- 五、移动端端适配布局
- 六、响应式布局
- 总结
前言
- CSS 主要分为三个方向:特效、工程化、布局
- 特效:动画、3D、渐变等
- 工程化:sass、less、postcss 等
- 布局:Flex、Grid、响应式布局等
一、CSS 还原 UI 设计
1、Photoshop 还原 UI 设计
(1)PhotoShop 下载安装
- PhotoShop2020 Mac 下载链接: https://pan.baidu.com/s/1S1rO1MgmZmTorWxX0qUOcQ 提取码: heu9
- PhotoShop2020 Win 下载链接: https://pan.baidu.com/s/19ktONg_UFyXitX8XI6boyw 提取码: 1cl5
(2)添加辅助线
- 点击“视图”菜单,勾选“标尺”,然后在图片编辑界面上面和左侧就会出现标尺
- 通过从上或从左的标尺位置向下或向右拖拉,就能拉出标尺线
(3)尺寸、文字、颜色等信息的获取
尺寸大小的测量:
- 点击“窗口”,勾选“信息”
- 然后在出现的信息面板点击“面板选项”,将“标尺单位”改为“像素”
- 配合选框工具或者其它工具就可以在信息面板查看尺寸大小
颜色的测量:
- 通过吸管工具去拾取颜色,就可以在拾取器上得到颜色值
文字信息的获取:
- 点击文字会选中对应的图层,点击字符面板,就可以看到文字相关信息
(4)切图操作
- 点击编辑菜单找到“首选项”,或者点击 PhotoShop 图标选择“首选项”,然后点击“增效工具”,勾选“启用生成器”
- 点击文件菜单点击“生成”,选择“图像资源”
- 就可以对需要的图标图层进行重命名+图片后缀,然后在与当前文件相同的目录下就会出现图层对应的图片图标了
- 也可以在命名的前面加上百分比和空格,就可以得到原图对应缩放比例的图片,例如:200% icon1.png
2、蓝湖 App 快速标注信息
- 蓝湖在线切图:https://lanhuapp.com/
二、布局的尺寸与位置
1、尺寸
(1)CSS 盒模型
- 在 CSS 中,所有元素都被一个个的“盒子(box)”装着,即大盒装小盒
- 盒子的组成:content 内容(上图188.742x51.875部分)、padding 内边距(上图 padding 部分)、border 边框(上图 border 部分)、margin 外边距(上图 margin 部分)
⚠️CSS 盒模型的注意点:
- padding 不能为负值,而 margin 可以为负值
- 背景色的设置会包含 content、padding、border 三个非 margin 的区域,即 padding 和 border 的背景色和 content 背景色一样
- margin-top 会出现传递的现象,即当子盒子设置 margin-top 时,会导致父盒子产生效果而不是子盒子产生效果。
解决方案:父盒子设置 border 属性;子盒子改为使用 padding-top 属性;使用 BFC 格式化上下文 - margin 上下重叠问题,即两个上下排列的盒子,如果上面的盒子设置 margin-bottom 属性,下面的盒子设置 margin-top 属性,会导致实际上两个盒子之间的外边距值为 margin-bottom 和 margin-top 两者相比的较大值,而不是想象中的相加
解决方案:只针对上面的盒子或者下面的盒子两者之一加想产生的实际距离值;BFC 也能解决
(2)块级盒子与内联盒子
- 在 CSS 中主要分为两种盒子——块级盒子(block box)和行级盒子(inline box)
- 块级盒子:块级盒子会独占一行,例如:div、p、h系列 …
- 内联盒子:行内盒子会在一行排列,直到当前行不能容纳导致换行,例如:span、a、strong …
块级盒子的特性:
- 独占一行
- 支持所有样式
- 不写宽度时,默认与父容器的宽度相同
- 所占区域是一个矩形
内联盒子的特性:
- 盒子不会产生换行
- 有些样式不支持,例如:width、height 等
- 不写宽度时,宽度由内容决定
- 内联盒子之间会产生间隙
解决方案:标签之间不换行;将父容器的 font-size 设置为 0;设置浮动;将其变为块级盒子 display:block;
(3)标准盒模型与怪异盒模型
- 标准盒模型是:当容器设置宽高时,所设的宽高就是实际 content 部分的宽高
- 怪异盒模型:当容器使用 box-sizing: border-box; 时,容器设置的宽高变为 content + padding + border
2、位置
(1)浮动与清除浮动
- 当元素被浮动时,浮动的元素会脱离文档流,根据设置 float 的值为向左或向右,浮动的元素会向左或向右移动,直到碰到父元素的内边界或者兄弟浮动元素的边界为止
- 文档流:文档流是元素在 Web 页面上的一种呈现方式,按照出现的顺序进行排列
清除浮动: 清除浮动的作用是使浮动元素的兄弟元素不受浮动的影响
- BFC
- 使用 clear 属性
// html
<div class="box1"></div>
<div class="box2"></div>
// css
.box1 {
width: 100px;
height:100px;
background: red;
float: left;
}
.box2 {
width: 200px;
height:200px;
background: skyblue;
// 清除浮动:
// 如果是左浮动可以使用 clear: left;
// 如果是右浮动可以使用 clear: right;
// 如果是想将左右浮动都清楚可以使用 clear: both;
clear: both;
}
- 通过对空标签使用 clear 属性
- 使用 .clearfix::after {}
// 原理是使用空标签 + clear: both; 只不过是通过 ::after 伪类的形式添加
// html
<div class="box1 clearfix">
<div class="box2"></div>
</div>
// css
.box1 {
width: 200px;
border: 1px solid #333;
}
.box2 {
width: 100px;
height: 100px;
background: skyblue;
float: left;
}
/* 清除浮动 */
.clearfix::after {
content: "",
display: block; // 将 ::after 添加的盒子变成块级盒子
clear: both; // clear 属性清除浮动只能针对块级盒子,对行内盒子不起作用
}
⚠️浮动特性注意点:
- 浮动的元素只会影响到后面元素的布局
- 文本不会被浮动元素覆盖
- 浮动元素具备行级盒子的特性:宽度由内容决定
- 浮动元素也具备块级盒子的特性:支持所有样式
- 浮动元素在一行排列不下时会自动换行
(2)定位样式简介
- CSS 中的 position 属性用于指定一个元素在文档中的定位方式,其中 top、right、bottom、left 则决定了该元素的位置
- position 属性的属性值:static、relative、absolute、fixed、sticky
static 属性值:默认情况
relative 属性值:相对定位是相对于原位置的偏移;不会脱离文档流;不会影响其它元素布局
absolute 属性值:绝对定位的元素会脱离文档流;具备行级盒子的特性——宽度由内容决定;具备块级盒子的特性——支持所有样式;绝对定位元素相对于 最近的非 static 外层元素进行定位,若这样的元素不存在,则相对于可视区定位(而不是 body)
fixed 属性值:固定定位与绝对定位相似,会脱离文档流;具备行级盒子的特性——宽度由内容决定;具备块级盒子的特性——支持所有样式;但是会固定在可视区中,不受外层元素的影响
sticky 属性值:粘性定位被认为是相对定位与固定定位的混合,元素在跨域特定阈值前为相对定位,之后为固定定位
⚠️定位特性注意点:
- 绝对定位的 z-index 值默认为 0
3、其它
(1)详解 display 属性
- 在 CSS 中 display 属性表示“显示框类型”,即不同的盒模型,就是把块级盒子转位内联盒子,或者把内联盒子转位块级盒子
display-outside(外部值):
- 外部值就是定义自身元素的外部表现,而不影响其内的子元素
- block 值:表示块级盒子,如:div、p …
- inline 值:表示内联盒子,如:span、a、i …
- run-in 值:还处在实验性质的属性,浏览器支持性不好
display-inside(内部值):
- 和外部值相反,内部值就是定义子元素布局的
- flow-root 值:一个 BFC 的块级盒子
- table 值:带有内部表格的块级盒子
- flex 值:带有内部弹性布局的块级盒子
- grid 值:带有内部网格布局的块级盒子
- flow 值:
- ruby 值:
- subgrid 值:
display-listitem(列表值):
- list-item 值:该属性值是生成一个容纳内容和单独的列表行内元素盒的块级盒子
display-internal(属性值):
- 一些盒 table 布局、ruby 搭配一起控制页面布局的属性值
- table-row-group 值:
- table-header-group 值:
- table-footer-group 值:
- table-row 值:
- table-cell 值:
- table-column-group 值:
- table-column 值:
- table-caption 值:
- ruby-base 值:
- ruby-text 值:
- ruby-base-container 值:
- ruby-text-container 值:
display-box(显示值):
- contents 值:只影响其内容的样式生效,比如:字体大小、文字颜色等,但像背景色、边框是不会生效的
- none 值:从盒子树中移除,包括其所有后代元素
display-legacy(混合值):
- inline-block 值:对外表现成内联盒子,对外表现成块级盒子
- inline-table 值:对外表现成内联盒子,对子元素表现成表格盒子
- inline-flex 值:对外表现成内联盒子,对子元素表现成弹性盒子
- inline-grid 值:对外表现成内联盒子,对子元素表现成网格盒子
display-global(全局值):
- inherit 值:继承父元素的 display 属性
- initial 值:不管父元素如何设定,恢复到浏览器最初时的 display 属性
- unset 值:unset 混合了 inherit 和 initial 。如果父元素设定,就用父元素的,如果父元素没设定,就用浏览器的缺省设定
(2)BFC 块级格式上下文
- BFC 即块级格式化上下文(Block Formatting Contexts),它是 W3C CSS2.1 规范中的一个概念
- 具有 BFC 特性的元素可以看作是一个独立的容器,容器里面的布局不会影响到外面(小千世界、中千世界、大千世界)
BFC 的生成条件:
- float 的值不是 none
- position 的值不是 static 或者 relative
- overflow 的值不是 visible
- display 的值是 inline-block、table-cell、flex、table-caption 或 inline-flex
BFC 的应用:
- 解决 margin 传递和 margin 上下塌陷的问题
- 解决浮动时父元素高度塌陷的问题。让父元素 BFC,例:overflow: hidden;
(3)标签默认样式以及清除
- 一些 HTML 标签在浏览器中会有默认样式,例如:body 标签有 margin: 8px; ul 标签有 margin: 16px 0; 等等
清除标签默认样式:
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
- Normalize CSS:http://necolas.github.io/normalize.css/
- Normalize CSS 比 Reset CSS 更优
保护有用的浏览器默认样式而不是完全去掉
修复浏览器自身的 bug,并保证各浏览器的一致性 - 使用 npm 下载
npm install normalize.css
- 复制如下代码到项目
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
(4)书写模式与逻辑属性
书写模式:
- 大部分国家的阅读方式都是从左到右进行的,但是也有一些国家的阅读方式是从右到左,所以在做国际网站网页排版时,就需要考虑阅读方式的问题
- 书写模式 writing-mode 属性: 定义了文本水平或垂直排布,以及文本在块级元素的行进方向
horizontal-tb 值:水平方向自上而下的书写方式
vertical-rl 值:垂直方向自右向左的书写方式
vertical-lr 值:垂直方向且自左向右的书写方式
sideways-rl 值:内容垂直方向从上到下排列
sideways-lr 值:内容垂直方向从下到上排列
逻辑属性:
- 逻辑属性是从逻辑角度控制布局,而不是从物理、方向或维度来控制
- 物理属性和值常见的为:width、height、left、top、right、bottom 等等
- 逻辑属性和值是指:start、end、inline-start、inline-end、block-start、block-end 等值。其中 inline 表示水平方向,block 表示垂直方向。在不同的书写模式下,inline 和 block 所代表的方向是会发生改变的
三、flex 弹性布局
- 弹性盒子是一种用于按行或按列布局元素的一维布局方式。元素可以扩大填充额外空间,或者缩小以适应更小的空间
- 若想将盒子设置为弹性盒子,需要将 display 属性设置为 flex(可以参考上面“详解 display 属性”小节)
- flex 容器的属性只会对容器产生作用;属性有:flex-direction、flex-wrap、flex-flow、justify-content、align-items、align-content
- flex 项目的属性也只会对项目产生作用;属性有:order、flex-grow、flex-shrink、flex-basis、flex、align-self
1、flex 容器
(1)主轴与交叉轴
- flex 布局的默认情况或者当设置 flex-direction 为 row 时,项目以水平方向排列,主轴方向就是水平方向,交叉轴是垂直方向
- 同理,当设置 flex-direction 为 column 时,项目以垂直方向排列,主轴方向就是垂直方向,交叉轴是水平方向
- 主轴与交叉轴互相垂直
(2)改变轴方向 —— flex-direction
- row 值:默认值,主轴是水平,方向从左到右
- row-reverse 值:主轴水平,方向从右到左
- column 值:主轴垂直,方向从上到下
- column-reverse 值:主轴垂直,方向从下到上
(3)换行 —— flex-wrap
- nowrap 值:默认,不换行
若项目设置宽度,当总项目宽度超出容器宽度,项目也不会换行,而是缩小项目宽度以适应容器宽度;当项目宽度缩小到最小且不能再继续缩小,而总项目宽度依旧超过容器宽度,则会导致溢出 - wrap 值:换行
若容器高度超出换行后项目的总高度,则换行成多少行就将容器高度均分为多少份,每行项目排列在该份高度的顶部 - wrap-reverse 值:反向换行
当主轴方向是水平时,默认是从上向下换行,当使用该属性值,换行是从下往上换行;
当主轴方向是垂直时,默认是从左向右换行,当使用该属性值,换行是从右往左
(4)改变主轴与换行的缩写 —— flex-flow
- flex-flow 是 flex-direction 与 flex-wrap 的缩写形式
- flex-flow: [flex-direction] [flex-wrap]
(5)主轴对齐 —— justify-content
- flex-start 值:默认,起始方向对齐
- flex-end 值:终点方向对齐
- center 值:居中对齐
- space-around 值:每个项目的外边距都相等,相邻项目之间的距离为两倍边距
- space-between 值:靠近容器边界的项目贴合容器,相邻项目的间隔相等
- space-evenly 值:项目与容器边界或者与相邻项目之间的间距相等
(6)交叉轴对齐 —— align-content
- align-content 是针对交叉轴整体的对齐方式
- 当不换行的情况下,align-content 是不生效的
- stretch 值:默认,拉伸
当不设置宽高时,默认会自动拉伸 - flex-start 值:起始方向对齐
- flex-end 值:终点方向对齐
- center 值:居中对齐
- space-around 值:
- space-between 值:
- space-evenly 值:
(7)交叉轴对齐 —— align-items
- align-items 是针对交叉轴每行的对齐方式
- stretch 值:默认,拉伸
当不设置宽高时,默认会自动拉伸 - flex-start 值:起始方向对齐
- flex-end 值:终点方向对齐
- center 值:居中对齐
- baseline 值:基线对齐
2、flex 项目
(1)扩展比例 —— flex-grow
- 默认值是 0,表示不占用剩余的空白间隙扩展自己的宽度
- 最小值就是 0,不能为负数
- 如果只有一个项目且比例值大于等于 1,就占满剩余的所有空间
- 如果只有一个项目且比例值为小数,所占空间 = 项目空间 + (容器空间 - 项目空间) * 比例值
- 如果有多个项目,且项目总比例大于等于1,则单个项目所占空间 = 当前项目空间 + (当前项目比例 / 总比例) * (容器空间 - 项目总空间)
- 如果有多个项目,且项目总比例小于1,则单个项目所占空间 = 当前项目空间 + (容器空间 - 项目总空间) * 当前项目比例
// html
<div class="box">
<div>1</div>
<div>2</div>
</div>
// css
/**
* 示例1:
* 当项目1扩展比例为1,项目2扩展比例为1时,总比例值大于等于1
* 项目1所占空间 = 200 * 1/(1 + 1) + 200 = 300
* 项目2所占空间 = 200 * 1/(1 + 1) + 100 = 200
**/
/**
* 示例2:
* 当项目1扩展比例为 3,项目2扩展比例为 2 时,总比例值大于等于1
* 项目1所占空间 = 200 + (500 - 200 - 100) * 3/(2 + 3) = 320
* 项目2所占空间 = 100 + (500 - 200 - 100) * 2/(2 + 3) = 180
**/
/**
* 示例3:
* 当项目1扩展比例为 0.3,项目2扩展比例为 0.8 时,总比例值大于等于1
* 项目1所占空间 = 200 + (500 - 200 - 100) * 0.3/(0.3 + 0.8) = 254.55
* 项目2所占空间 = 100 + (500 - 200 - 100) * 0.8/(0.3 + 0.8) = 245.45
**/
/**
* 示例4:
* 当项目1扩展比例为 0.3,项目2扩展比例为 0.7 时,总比例值大于等于1
* 项目1所占空间 = 200 + (500 - 200 - 100) * 0.3/(0.3 + 0.7) = 260
* 项目2所占空间 = 100 + (500 - 200 - 100) * 0.7/(0.3 + 0.7) = 240
**/
/**
* 示例5:
* 当项目1扩展比例为 0.3,项目2扩展比例为 0.4 时,总比例值小于1
* 项目1所占空间 = 200 + (500 - 200 - 100) * 0.3 = 260
* 项目2所占空间 = 100 + (500 - 200 - 100) * 0.4 = 180
**/
.box {
width: 500px;
height: 300px;
border: 1px solid red;
}
.box div:nth-of-type(1) {
width: 200px;
height: 100px;
border: 1px solid green;
flex-grow: 1;
}
.box div:nth-of-type(2) {
width: 100px;
height: 100px;
border: 1px solid green;
flex-grow: 1;
}
(2)收缩比例 —— flex-shrink
- 默认值是 1,表示 flex 容器空间不足时,项目自动收缩以适应容器
- 如果只有一个项目,当收缩比例大于等于 1时,项目所占空间 = 项目初始空间 - 容器空间
- 如果只有一个项目,当收缩比例值小于 1 时,超出容器部分按比例收缩,即:所占空间 = 项目初始空间 - (项目初始空间 - 容器空间) * 收缩比例
- 如果有多个项目,且项目总比例大于等于1,则单个项目所占空间 = 当前项目所占空间 - ((当前项目所占空间 * 当前项目所占比例) / (每个项目所占空间 * 每个项目所占比例) 之和) * 超出容器空间
- 如果有多个项目,且项目总比例小于1,则单个项目所占空间 = 当前项目所占空间 - ((当前项目所占空间 * 当前项目所占比例) / (每个项目所占空间 * 每个项目所占比例) 之和) * (项目所占总比例 * 超出容器空间)
// html
<div class="main">
<div>1</div>
<div>2</div>
</div>
// css
/**
* 多个项目示例1:
* 当项目1收缩比例为2,项目2扩展比例为3时,即总比例大于1
* 项目1所占空间 = 400 - ((400 * 2)/(400*2 + 300*3)) * (400 + 300 -500) = 305.88
* 项目2所占空间 = 300 - ((300 * 3)/(400*2 + 300*3)) * (400 + 300 -500) = 194.12
**/
/**
* 多个项目示例2:
* 当项目1收缩比例为2,项目2扩展比例为 0.3时,即总比例大于1
* 项目1所占空间 = 400 - ((400 * 2)/(400*2 + 300*0.3)) * (400 + 300 -500) = 220.23
* 项目2所占空间 = 300 - ((300 * 0.3)/(400*2 + 300*0.3)) * (400 + 300 -500) = 279.77
**/
/**
* 多个项目示例3:
* 当项目1收缩比例为0.3,项目2扩展比例为 0.7时,即总比例等于1
* 项目1所占空间 = 400 - ((400 * 0.3)/(400*0.3 + 300*0.7)) * (400 + 300 -500) = 327.27
* 项目2所占空间 = 300 - ((300 * 0.7)/(400*0.3 + 300*0.7)) * (400 + 300 -500) = 172.73
**/
/**
* 多个项目示例4:
* 当项目1收缩比例为0.3,项目2扩展比例为 0.1时,即总比例小于1
* 项目1所占空间 = 400 - ((400 * 0.3)/(400*0.3 + 300*0.1)) * ((0.3 + 0.1) * (400 + 300 -500)) = 336
* 项目2所占空间 = 300 - ((300 * 0.1)/(400*0.3 + 300*0.1)) * ((0.3 + 0.1) * (400 + 300 -500)) = 284
**/
.main {
width: 500px;
height: 300px;
background-color: skyblue;
display: flex;
}
.main div:nth-of-type(1) {
width: 400px;
height: 100px;
background-color: red;
flex-shrink: 0.3;
}
.main div:nth-of-type(2) {
width: 300px;
height: 100px;
background-color: green;
flex-shrink: 0.1;
}
(3)初始化主轴值 —— flex-basis
- flex-basis 默认值是 auto,指定了 flex 元素在主轴方向的初始大小
- flex-basis 优先级大于主轴方向的宽(主轴水平)或者高(主轴垂直)
- auto 值:默认
- 固定值:例如:200px
- 百分比值:例如:100%
(4)扩展、缩小、初始值的简写 —— flex
- flex 属性是 flex-grow、flex-shrink、flex-basis 的缩写
- flex: 1 的展开:flex-grow: 1; flex-shrink: 1; flex-basis: 0%;
- flex: 0 的展开:flex-grow: 0; flex-shrink: 1; flex-basis: 0%;
- flex: auto 的展开:flex-grow: 1; flex-shrink: 1; flex-basis: auto;
(5)项目排序 —— order
- order 的默认值是 0,用于改变某个项目的排序位置
- order 的值越小,排序越靠前
- order 的值也可以为负数
(6)单独项目垂直对齐 —— align-self
- align-self 的默认值是 auto,用于控制单独某一个 flex 项目的交叉轴对齐方式
- align-self 的值默认是和容器的 align-items 的值保持一致
- stretch 值:默认,拉伸
当不设置宽高时,默认会自动拉伸 - flex-start 值:起始方向对齐
- flex-end 值:终点方向对齐
- center 值:居中对齐
- baseline 值:基线对齐
四、grid 网格布局
- CSS 网格是一个用于 Web 的二维布局系统。网格布局可以把内容按照行和列的格式进行排版,实现一些复杂的布局
1、grid 布局的基本概念
(1)基本概念
容器和项目:
- 容器(container):和 flex 布局的容器一样,采用网格布局的区域称为容器
- 项目(item):容器中的每一个子项称为项目(子项的子项不属于容器的项目)
行和列:
- 行(row):容器内水平方向的区域称为行(类比于普通表格的行)
- 列(column):容器的垂直方向的区域称为列(类比于普通表格的列)
单元格:
- 单元格(cell):行和列交叉的区域称为单元格(类比于普通表格的单元格)
间隙:
- 间隙(gap):单元格之间的距离称为间隙(可以类比于表格的border边框)
网格线:
- 网格线(grid line):用于划分单元格的线称为网格线
- 水平网格线划分出行,每两根水平网格线划分出一行
- 垂直网格线划分出列,每两根垂直网格线划分出一列
- 网格线可以使用数字命名方式,也可以自定义名称命名
- 数字命名:默认从左到右和从上到下分别为:1、2、3、4 …,例如一个 3x3 的网格线水平方向从左到右依次为:1、2、3、4,垂直方向从上到下依次为:1、2、3、4
区域:
- 区域(area):相邻单元格之间可以合并,合并后的单元格称为区域
(2)fr 单位
- fr(fraction的缩写)是一种用来表示比例关系的单位,例如:有两个容器的宽度分别为 1fr 和 2fr,表示第二个容器的宽度是第一个容器宽度的两倍
2、grid 容器
(1)定义网格(显式)的行和列 —— grid-template-rows & grid-template-columns
- display: grid;:在容器中将容器定义为网格布局
- grid-template-rows 属性:用于定义网格的行
- grid-template-columns 属性:用于定义网格的列
- 定义行、列属性的属性值可以为:fr、px、%、auto、rem 等等
- 定义多少列就写多少列的属性值,属性值之间用空格分隔
- 同理,定义多少行就写多少行的属性值,属性值之间用空格分隔
// html
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
// css
.container {
width: 500px;
height: 300px;
background: skyblue;
display: grid;
// 定义行 3行,第一行宽度 100px,第二行宽度 100px,第三行宽度 100px
grid-template-rows: 100px 100px 100px;
// 定义列 3列,第一列宽度 100px,第二列宽度 200px,第二列宽度 200px
grid-tempalte-columns: 100px 200px 200px;
}
.container div {
background: red;
}
(2)网格命名及合并网格 —— grid-template-areas
- 使用命名方式定义网格区域,使用时需要配合 grid-area 属性进行使用
- grid-template-areas 属性:用于命名网格,网格名称可以自定义
- 合并网格:只要将相邻的网格的名称命名相同,就会合并对应位置的网格
- ⚠️注意:合并后的网格要形成一个矩形
// html
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
// css
.container {
width: 300px;
height: 300px;
background: skyblue;
display: grid;
// 定义列 3列,三列均分容器宽度,每列占三分之一宽度
grid-tempalte-rows: 1fr 1fr 1fr;
// 定义行 3行,三行均分容器宽度,每行占三分之一高度
grid-template-columns: 1fr 1fr 1fr;
// 例如:将第一行的第一列及第二列合并,将第三行的第一列、第二列及第三列合并,
grid-template-areas:
"a1 a1 a2"
"a3 a4 a5"
"a6 a6 a6";
}
.container div {
background: green;
border: 1px solid #000;
box-sizing: border-box;
}
.container div:nth-of-type(1) {
// 表示第一个值1所在div容器占 a1 区域
grid-area: a1;
}
.container div:nth-of-type(2) {
// 表示第一个值2所在div容器占 a2 区域
grid-area: a2;
}
.container div:nth-of-type(3) {
// 表示第一个值3所在div容器占 a3 区域
grid-area: a3;
}
.container div:nth-of-type(4) {
// 表示第一个值4所在div容器占 a4 区域
grid-area: a4;
}
.container div:nth-of-type(5) {
// 表示第一个值5所在div容器占 a5 区域
grid-area: a5;
}
.container div:nth-of-type(6) {
// 表示第一个值6所在div容器占 a6 区域
grid-area: a6;
}
(3)网格定义、命名、合并的缩写 —— grid-template
- grid-template 属性是 grid-temolate-rows、grid-template-columns、grid-template-areas 属性的缩写
- 即:grid-template: grid-temolate-rows grid-template-columns grid-template-areas;
grid-template:
"命名11 命名12 ... 命名1n" 第一行的高度
"命名21 命名22 ... 命名2n" 第二行的高度
"......"
"命名m1 命名m2 ... 命名mn" 第m行的高度
/ 第一列的宽度 第二列的宽度 ... 第n列的宽度 ;
- 示例
grid-tempalte-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas:
"a1 a1 a2"
"a3 a4 a5"
"a6 a6 a6";
// 缩写为
grid-template:
"a1 a1 a2" 1fr
"a3 a4 a5" 1fr
"a6 a6 a6" 1fr
/ 1fr 1fr 1fr;
(4)网格间隙及简写 —— grid-row-gap、grid-column-gap & grid-gap
- 用来设置元素行列之间的间隙大小,推荐使用:row-gap、column-gap、gap,原因是加 grid 前缀的属性已经过时了,而没有加 grid 前缀的在其它例如flex布局中也可以使用
- grid-row-gap 属性:添加网格之间行间距
- grid-column-gap 属性:添加网格之间列间距
- grid-gap 属性是 grid-row-gap 属性和 grid-column-gap 属性的缩写
- grid-gap: row-gap column-gap; 或者 gap: row-gap column-gap;
// css
.container {
width: 300px;
height: 300px;
background: skyblue;
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-tempalte-columns: 1fr 1fr 1fr;
/* grid-row-gap: 20px;
grid-column-gap: 10px; */
/* row-gap: 20px;
column-gap: 10px; */
/* grid-gap: 20px 10px; */
gap: 20px 10px;
}
(5)容器对齐方式及简写 —— justify-content、align-content & place-content
- 这些属性的对齐指的是所有网格在容器中的对齐方式
- stretch 值:默认,拉伸
- start 值:起始位置对齐
- center 值:居中对齐
- end 值:终点对齐
- space-around 值:每个项目两侧的边距相等,且相邻项目之间的间隔为边距的两倍
- space-between 值:项目之间的间隔相等,靠近容器的项目贴合容器边界
- space-evenly 值:项目之间的间隔相等,且项目与容器边界的间隔等于项目之间的间隔
- place-content: align-content justify-content;
(6)网格对齐方式及简写 —— justify-items、align-items & place-items
- 这些属性指定了项目在网格中的对齐方式
- 这些属性的对齐指的是所有项目在单元格中的对齐方式
- stretch 值:默认,拉伸
- start 值:起始位置对齐
- center 值:居中对齐
- end 值:终点对齐
- space-around 值:每个项目两侧的边距相等,且相邻项目之间的间隔为边距的两倍
- space-between 值:项目之间的间隔相等,靠近容器的项目贴合容器边界
- space-evenly 值:项目之间的间隔相等,且项目与容器边界的间隔等于项目之间的间隔
- place-items: align-items justify-items;
(7)隐式网格的定义 —— grid-auto-rows、grid-auto-columns
- 隐式网格:有时候定义容器的项目数超出容器单元格的数目,就会造成一部分项目溢出形成新的单元格,溢出形成的网格称为隐式网格
- 如果不定义隐式网格的大小,浏览器就会默认以内容的宽高为隐式单元格的宽高
- 隐式网格的定义和显式网格的定义相似
(8)repeat() 和 minmax()
- repeat(次数,值) 方法表示相同数值的重复次数,有一个可选值 auto-fill
- auto-fill 表示自动会根据容器大小进行调整
- minmax(minVal, maxVal) 方法表示设置最小和最大的范围
// 示例1:
grid-template-columns: 100px 100px 100px;
// 等价于
grid-template-columns: repeat(3, 100px);
// 示例2:
grid-template-columns: 150px 100px 100px;
// 等价于
grid-template-columns: 150px repeat(2, 100px);
// 示例3:
grid-template-columns: 100px minmax(100px, 1fr) 100px;
// 示例4:
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
(9)指定项目排列方式 —— grid-auto-flow
- row 值:默认,指定项目按行排列,即:按行从左到右排列
- column 值:指定项目按列排列,即:按列从上到下排列
- row dense 值:某些项目指定位置以后,剩下的项目按“先行后列”尽量紧密排列
- column dense 值:某些项目指定位置以后,剩下的项目按“先列后行”尽量紧密排列
3、grid 项目
(1)指定项目占据的区域 —— grid-column-start、grid-column-end、grid-row-start、grid-row-end
- 表示 grid 项目所占的区域的起始和终止位置,包括水平方向和垂直方向
- 默认值是 auto
- 当某个项目指定占据区域后,其它未指定的项目按默认顺序排列
// html
<div class="container">
<div>1</div>
</div>
// css
.container {
width: 300px;
height: 300px;
background: skyblue;
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-tempalte-columns: 1fr 1fr 1fr;
}
.container div:nth-of-type(1) {
background: red;
grid-row-start: 2; // 垂直方向第2条水平网格线开始
grid-row-end: 4; // 垂直方向第4条水平网格线结束
grid-column-start: 2; // 水平方向第2条垂直网格线开始
grid-column-end: 3; // 水平方向第3条垂直网格线结束
}
- 也可以使用“span”关键字加数字的形式,表示跨越多少个网格
// html
<div class="container">
<div>1</div>
</div>
// css
.container {
width: 300px;
height: 300px;
background: skyblue;
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-tempalte-columns: 1fr 1fr 1fr;
}
.container div:nth-of-type(1) {
background: red;
grid-row-start: 2; // 垂直方向第2条水平网格线开始
grid-row-end: span 2; // 表示占据两行,即从第2条水平网格线开始到第4条水平网格线结束
grid-column-start: 2; // 水平方向第2条垂直网格线开始
grid-column-end: span 1; // 表示占据一列,即从第2条垂直网格线开始到第3条垂直网格线结束
}
- 自定义命名网格线名称:在定义网格时,分别在每行或每列前后定义网格线名称
// html
<div class="container">
<div>1</div>
</div>
// css
.container {
width: 300px;
height: 300px;
background: skyblue;
display: grid;
grid-template-rows: [row1] 1fr [row2] 1fr [row3] 1fr [row4];
grid-tempalte-columns: [col1] 1fr [col2] 1fr [col3] 1fr [col4];
}
.container div:nth-of-type(1) {
background: red;
grid-row-start: row2; // 垂直方向第2条水平网格线开始
grid-row-end: span 2; // 表示占据两行,即从第2条水平网格线开始到第4条水平网格线结束
grid-column-start: col2; // 水平方向第2条垂直网格线开始
grid-column-end: span 1; // 表示占据一列,即从第2条垂直网格线开始到第3条垂直网格线结束
}
(2)指定项目占据区域的简写 —— grid-row、grid-column & grid-area
- 简写方式通过 / 作为分割
- grid-row: grid-row-start / grid-row-end;
- grid-column: grid-column-start / grid-column-end;
- grid-area 是 grid-row-start、grid-column-start、grid-row-end、grid-column-end 属性的缩写,并且支持 grid-template-areas 设置网格名称
- 即:grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
(3)项目的对齐方式 —— justify-self、align-self、place-self
- 这些属性的对齐指的是某个项目在自己区域中的对齐方式
- stretch 值:默认,拉伸
- start 值:起始位置对齐
- center 值:居中对齐
- end 值:终点对齐
- space-around 值:每个项目两侧的边距相等,且相邻项目之间的间隔为边距的两倍
- space-between 值:项目之间的间隔相等,靠近容器的项目贴合容器边界
- space-evenly 值:项目之间的间隔相等,且项目与容器边界的间隔等于项目之间的间隔
- place-self: align-self justify-self;
// html
<div class="container">
<div>1</div>
</div>
// css
.container {
width: 300px;
height: 300px;
background: skyblue;
display: grid;
grid-template-rows: [row1] 1fr [row2] 1fr [row3] 1fr [row4];
grid-tempalte-columns: [col1] 1fr [col2] 1fr [col3] 1fr [col4];
}
.container div:nth-of-type(1) {
width: 50px;
height: 50px;
background: purple;
grid-row-start: row2; // 垂直方向第2条水平网格线开始
grid-row-end: span 2; // 表示占据两行,即从第2条水平网格线开始到第4条水平网格线结束
grid-column-start: col2; // 水平方向第2条垂直网格线开始
grid-column-end: span 1; // 表示占据一列,即从第2条垂直网格线开始到第3条垂直网格线结束
justify-self: center;
align-self: center;
}
五、移动端端适配布局
- 移动端适配:是实现各种设备的等比适配,让所有移动端设备看起来是相同的
1、移动端概念
(1)像素
分辨率:
- 屏幕上的点,每一个点称为物理像素
- 分辨率 = 纵向的点数 x 横向的点数
物理像素(physical pixel):
- 也称为设备像素(dp:device pixel))
CSS 像素:
- 也称为逻辑像素(logical pixel)或 设备独立像素(dip:device independent pixel)
- CSS 像素是实际开发中使用的像素
设备像素比(dpr):
- 设备像素比(dpr:device pixel ratio)
- dpr = 设备像素 / CSS像素(缩放比是 1 的情况下)
- dpi = 2 表示 1 个CSS像素用 2x2个设备像素来绘制
标清屏和高清屏:
- 标清屏:是指设备像素与CSS像素一比一,即 1 个CSS像素 = 1 个物理像素
- 高清屏:是指设备像素与CSS像素比大于 1
缩放:
- 缩放改变的是 CSS 像素的大小
- 放大:1 个CSS像素 = 多 x 多 个物理像素
- 缩小:多 x 多 个CSS像素 = 1 个物理像素
PPI/DPI:
- 屏幕英寸:屏幕对角线的长度
- PPI:每英寸的物理像素点,PPI = (屏幕宽的平方 + 屏幕高的平方)开根号再除以屏幕英寸
- DPI:每英寸的点
(2)视口(viewport)
视口宽度设置:
// 一般这样写
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,maximum-scale=1,minimum-scale=1">
// 下面这些是分开写
<meta name="viewport" content="initial-scale=1">
<meta name="viewport" content="width=device-width">
<meta name="viewport" content="maximum-scale=1,minimum-scale=1">
JS 中获取视口宽度:
console.log(window.innerWidth);
console.log(document.documentElement.clientWidth);
console.log(document.documentElement.getBoundingClientRect().width);
var viewWidth = window.innerWidth || document.documentElement.clientWidth || document.documentElement.getBoundingClientRect().width;
JS 中获取设备像素比 dpr:
console.log(window.devicePixelRatio);
(3)移动端常用单位(px/%/em/rem/vw/vh)
- px / % / em / rem / vw / vh 这些单位中除了 px 是固定单位,其它都是相对单位
- em:元素自身字体大小,1 em = 1 font-size,即表示 1 个 em 等于它自身 font-size 的大小;当自身没有设置 font-size 属性或 font-size 属性单位也为 em 时,则会向父元素找
font-size: 12px;
width: 5em; // 相当于宽为 5 x 12 = 60px
height: 6em; // 相当于高为 6 x 12 = 72px
- rem:rem 是相对根元素设置的 font-size,即设置的是 html 的字体大小,然后可以整个当前页面全局使用
html {
font-size: 12px;
}
.box {
width: 1rem; // 相当于宽为 1 x 12 = 12px
}
- vw:视口宽度,1 vw = 1%viewWidth
- vh:视口高度,1 vw = 1%viewHeight
2、移动端 rem 布局
(1)rem 布局原理
- rem:rem 是相对根元素设置的 font-size,即设置的是 html 的字体大小,然后可以整个当前页面全局使用
html {
font-size: 16px;
}
.box {
width: 2rem; // 相当于宽为 2 x 16 = 32px
}
(2)VSCode 中 px 转 rem 插件的安装与使用
px to rem 插件的安装:
- 在 VSCode 扩展里搜索“px to rem”
- 点击“1”的设置图标,然后选择“扩展设置”
- 第“1”部分是设置将 px 单位转为 rem 单位后保留几位小数
- 第“2”部分是设置 1rem 等于多少 px(在这里设置为与项目中的相同)
- ⚠️注意:如果不同项目中设置的 1rem 等于的 px 值不相同,则需要每次都改第“2”部分
px to rem 插件的使用:
- 将需要转换的 CSS 代码选中
- 然后 Mac 电脑按“option + z”对选中 px 单位进行 rem 转换
- Win 电脑按“Alt + z”对选中 px 单位进行 rem 转换
⚠️注意:PS 中量取的数值,是物理像素,CSS 中设置的是逻辑像素,所以需要对量取的值进行除以 2
(3)postcss-px2rem 插件的使用
- postcss-px2rem 是一款在编译时自动将 px 单位转为 rem 单位的插件。在开发时,可以直接使用 px 单位进行开发,该插件会在底层将 px 单位转为 rem 单位
- postcss-px2rem 插件的安装
npm install -D postcss-px2rem
- Vue 项目中,在 vue.config.js 文件进行配置使用
- remUnit 必须与设置的 1rem 等于多少 px 保持一致,例如:开发中 1rem = 100px,则设置 remUnit: 100
// vue.config.js
const px2rem = require('postcss-px2rem')
const postcss = px2rem({
remUnit: 100
})
module.exports = {
publicPath: "./",
css: {
loaderOptions: {
postcss: {
plugins: [
postcss
]
}
}
}
}
- 动态设置根元素 html 中的 font-size
- Vue 项目中,在 index.html 文件动态设置根元素的字体大小
<script>
// 这里的 100 表示 1rem = 100px
// baseSize 设置与 vue.config.js 中的 remUnit 值保持一致
const baseSize = 100
function setRem() {
// 相对于 1920px 像素,获得一个缩放比例
const scale = document.documentElement.clientWidth / 1920
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
window.onresize = function () {
setRem()
}
</script>
3、移动端 vw 布局
(1)vw 布局
- vw:视口宽度,1 vw = 1%viewWidth
(2)px-to-vw 插件的安装与使用
- 安装插件
- 配置
- “3”表示保留3位小数,可以自己根据需要改
- “375”表示 1vw = 3.75px,可以自己根据需要改
- 使用
- 将需要转换的 CSS 代码选中
- 然后 Mac 电脑按“option + z”对选中 px 单位进行 rem 转换
- Win 电脑按“Alt + z”对选中 px 单位进行 rem 转换
⚠️注意:px to rem 和 px-to-vw 两个插件不能同时使用,在使用某一个之前需要将另一个禁用
六、响应式布局
- 响应式布局概念:是指网页能自动识别屏幕宽度、并作出相应调整的网页设计
- 响应式布局可以为不同终端的用户提供更加舒适的界面和更好的用户体验
1、媒体查询语法
(1)媒体类型
- 媒体类型(Media Types)描述设备的一般类型
- all:适用于所有设备
- print:适用于打印预览模式
- screen:主要用于屏幕
- speech:主要用于语音合成器
@media 媒体类型 {}
(2)媒体特性
- 媒体特性(Media features)描述了 user agent、输出设备、或是浏览器环境的具体特征
- width:viewport 的宽度
- height:view height 的高度
- aspect-ratio:viewport 的宽高比
- orientation:viewport 的旋转方向
// 大于等于 200px
@media (min-width: 200px) {}
// 垂直
@media (orientation: portrait) {}
// 水平
@media (orientation: portrait) {}
(3)逻辑操作符
- 逻辑操作符(logical operators):not、and、or、only
- and:用于将多个媒体查询规则组合成单条媒体查询
- not:用于否定媒体查询,如果不满足条件则返回 true,否则返回 false
- or:用逗号表示,用于将多个媒体查询合并为一个规则
- only:用于旧版浏览器识别媒体类型使用
// and
@media (min-width: 200px) and (max-width: 300px) {}
// not
@media not screen and (min-width: 200px) {}
// or
@media (max-width: 200px), (min-width:500px) {}
(4)link 标签方式
- 通过 media 属性设置媒体查询类型和媒体特性
// a.css
// b.css
<link rel="stylesheet" href="./css/a.css" media="(max-width: 200px)">
<link rel="stylesheet" href="./css/b.css" media="(min-width: 500px)">
2、媒体查询的编写位置及顺序
- 一般会将媒体查询添加到样式表的底部,对 CSS 进行优先级的覆盖
- 移动端 => PC端 的适配原则,即从小到大:min-width 从小到大
- PC端 => 移动端 的适配原则,即从大到小:max-width 从大到小
/**
* 移动端 => PC端
**/
@media (min-width: 576px) {}
@media (min-width: 768px) {}
@media (min-width: 992px) {}
@media (min-width: 1200px) {}
/**
* PC端 => 移动端
**/
@media (max-width: 1200px) {}
@media (max-width: 992px) {}
@media (max-width: 768px) {}
@media (max-width: 576px) {}
3、响应断点(阈值)的设定
- 超小屏(Extra small) < 576px
- 小屏(Small) >= 576px,-sm
- 中屏(Medium) >= 768px,-md
- 大屏(Large) >= 992px,-lg
- 较大屏(X-Large) >= 1200px,-xl
- 超大屏(XX-Large) >= 1400px,-xxl
.font-size {
font-size: 12px;
}
@media (min-width: 576px) {
.font-sm-size {
font-size: 13px;
}
}
@media (min-width: 768px) {
.font-md-size {
font-size: 14px;
}
}
@media (min-width: 992px) {
.font-lg-size {
font-size: 16px;
}
}
@media (min-width: 1200px) {
.font-xl-size {
font-size: 18px;
}
}
@media (min-width: 1400px) {
.font-xxl-size {
font-size: 20px;
}
}
4、响应式栅格系统
- 响应式栅格系统:栅格布局 + 断点设定
// html
<div class="row">
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col</div>
</div>
// css
.row {
background: #ddd;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 30px;
grid-auto-rows: 30px;
}
.row div {
background: #aaa;
border: 1px solid #000;
grid-area: auto/auto/auto/12;
}
.row .col-1 {
grid-area: auto/auto/auto/1;
}
.row .col-2 {
grid-area: auto/auto/auto/2;
}
.row .col-3 {
grid-area: auto/auto/auto/3;
}
.row .col-4 {
grid-area: auto/auto/auto/4;
}
.row .col-5 {
grid-area: auto/auto/auto/5;
}
.row .col-6 {
grid-area: auto/auto/auto/6;
}
.row .col-7 {
grid-area: auto/auto/auto/7;
}
.row .col-8 {
grid-area: auto/auto/auto/8;
}
.row .col-9 {
grid-area: auto/auto/auto/9;
}
.row .col-10 {
grid-area: auto/auto/auto/10;
}
.row .col-11 {
grid-area: auto/auto/auto/11;
}
.row .col-12 {
grid-area: auto/auto/auto/12;
}
@media (min-width: 576px) {
.row .col-sm-1 {
grid-area: auto/auto/auto/1;
}
.row .col-sm-2 {
grid-area: auto/auto/auto/2;
}
.row .col-sm-3 {
grid-area: auto/auto/auto/3;
}
.row .col-sm-4 {
grid-area: auto/auto/auto/4;
}
.row .col-sm-5 {
grid-area: auto/auto/auto/5;
}
.row .col-sm-6 {
grid-area: auto/auto/auto/6;
}
.row .col-sm-7 {
grid-area: auto/auto/auto/7;
}
.row .col-sm-8 {
grid-area: auto/auto/auto/8;
}
.row .col-sm-9 {
grid-area: auto/auto/auto/9;
}
.row .col-sm-10 {
grid-area: auto/auto/auto/10;
}
.row .col-sm-11 {
grid-area: auto/auto/auto/11;
}
.row .col-sm-12 {
grid-area: auto/auto/auto/12;
}
}
@media (min-width: 768px) {
.row .col-md-1 {
grid-area: auto/auto/auto/1;
}
.row .col-md-2 {
grid-area: auto/auto/auto/2;
}
.row .col-md-3 {
grid-area: auto/auto/auto/3;
}
.row .col-md-4 {
grid-area: auto/auto/auto/4;
}
.row .col-md-5 {
grid-area: auto/auto/auto/5;
}
.row .col-md-6 {
grid-area: auto/auto/auto/6;
}
.row .col-md-7 {
grid-area: auto/auto/auto/7;
}
.row .col-md-8 {
grid-area: auto/auto/auto/8;
}
.row .col-md-9 {
grid-area: auto/auto/auto/9;
}
.row .col-md-10 {
grid-area: auto/auto/auto/10;
}
.row .col-md-11 {
grid-area: auto/auto/auto/11;
}
.row .col-md-12 {
grid-area: auto/auto/auto/12;
}
}
@media (min-width: 992px) {
.row .col-lg-1 {
grid-area: auto/auto/auto/1;
}
.row .col-lg-2 {
grid-area: auto/auto/auto/2;
}
.row .col-lg-3 {
grid-area: auto/auto/auto/3;
}
.row .col-lg-4 {
grid-area: auto/auto/auto/4;
}
.row .col-lg-5 {
grid-area: auto/auto/auto/5;
}
.row .col-lg-6 {
grid-area: auto/auto/auto/6;
}
.row .col-lg-7 {
grid-area: auto/auto/auto/7;
}
.row .col-lg-8 {
grid-area: auto/auto/auto/8;
}
.row .col-lg-9 {
grid-area: auto/auto/auto/9;
}
.row .col-lg-10 {
grid-area: auto/auto/auto/10;
}
.row .col-lg-11 {
grid-area: auto/auto/auto/11;
}
.row .col-lg-12 {
grid-area: auto/auto/auto/12;
}
}
@media (min-width:1200px) {
.row .col-xl-1 {
grid-area: auto/auto/auto/1;
}
.row .col-xl-2 {
grid-area: auto/auto/auto/2;
}
.row .col-xl-3 {
grid-area: auto/auto/auto/3;
}
.row .col-xl-4 {
grid-area: auto/auto/auto/4;
}
.row .col-xl-5 {
grid-area: auto/auto/auto/5;
}
.row .col-xl-6 {
grid-area: auto/auto/auto/6;
}
.row .col-xl-7 {
grid-area: auto/auto/auto/7;
}
.row .col-xl-8 {
grid-area: auto/auto/auto/8;
}
.row .col-xl-9 {
grid-area: auto/auto/auto/9;
}
.row .col-xl-10 {
grid-area: auto/auto/auto/10;
}
.row .col-xl-11 {
grid-area: auto/auto/auto/11;
}
.row .col-xl-12 {
grid-area: auto/auto/auto/12;
}
}
@media (min-width: 1400px) {
.row .col-xxl-1 {
grid-area: auto/auto/auto/1;
}
.row .col-xxl-2 {
grid-area: auto/auto/auto/2;
}
.row .col-xxl-3 {
grid-area: auto/auto/auto/3;
}
.row .col-xxl-4 {
grid-area: auto/auto/auto/4;
}
.row .col-xxl-5 {
grid-area: auto/auto/auto/5;
}
.row .col-xxl-6 {
grid-area: auto/auto/auto/6;
}
.row .col-xxl-7 {
grid-area: auto/auto/auto/7;
}
.row .col-xxl-8 {
grid-area: auto/auto/auto/8;
}
.row .col-xxl-9 {
grid-area: auto/auto/auto/9;
}
.row .col-xxl-10 {
grid-area: auto/auto/auto/10;
}
.row .col-xxl-11 {
grid-area: auto/auto/auto/11;
}
.row .col-xxl-12 {
grid-area: auto/auto/auto/12;
}
}
5、响应式交互实现
- 利用 :checked 伪类 实现
- 利用 JavaScript 脚本 实现