笔记来源:拉勾教育 - 大前端就业集训营
文章内容:学习过程中的笔记、感悟、和经验
rem布局(苏宁移动端页面为例)
rem(root em)单位
rem是相对单位,类似于em,em参考的是父元素字体大小,rem参考的是html根元素字体大小
**优点:**一个页面只有一个html根元素,参考元素是唯一的,可以实现整体控制
媒体查询(@media)
判断屏幕宽度,CSS3新增语法,类似于触发条件,如果满足会应用其中的样式,否则不执行
- 可以针对不同媒体类型定义不同的样式
- 可以针对不同屏幕大小设置不同样式
- 重置浏览器大小过程中,页面会根据浏览器的宽度和高度重新渲染页面
- 目前移动端设备都可以使用媒体查询
语法规范
- 必须使用@mesia开头
- mediatype - 媒体类型
- and、not、only - 关键字
- nedia featyre - 媒体特性
@media mediatype and|not|only (media featyre){ css样式 }
mediatype - 媒体类型
将不同设备终端划分为不同的类型,称为媒体类型
| 值 | 解释说明 |
|---|---|
| all | 用于所有设备 |
| 用于打印机和打印预览 | |
| screen | 用于电脑屏幕,平板电脑,智能手机等(最常用) |
关键字
关键字将媒体类型或多个媒体特性连接到一起做为媒体查询的条件。
- and:可以将多个媒体特性连接到一起,相当于“且”的意思。
- not:排除某个媒体类型,相当于“非”的意思,可以省略。
- or:可以测试多个媒体查询的条件,只要有一个条件成立,就执行, “或”的意思。
- only:指定某个特定的媒体类型,可以省略。
媒体特性
每种不同的媒体类型具有不同的特性,根据不同的媒体类型的媒体特性设置不同的样式风格
最常用的三个媒体特性:
| 值 | 解释说明 |
|---|---|
| width | 定义输出设备中页面可见区域的宽度 |
| min-width | 定义输出设备中页面最小可见区域宽度 |
| max-width | 定义输出设备中页面最大可见区域宽度 |
案例
- 按照从大到小的或者从小到大的思路
- 注意我们有最大值max-width和最小值min- width都是包含等于的
- 当屏幕小于540像素,背景颜色变为蓝色(x<= 539)
- 当屏幕大于等于540像素并且小于等于969像素的时候背景颜色为绿色( 540=< x <= 969)
- 当屏幕大于等于970像素的时候,背景颜色为红色( x>= 970)
- 注意:
为了防止混乱,媒体查询我们要按照从小到大或者从大到小的顺序来写,但是我们]最喜欢的还是从小到大来写, 这样代码更简洁
需求:
- 当屏幕小于540像素,背景颜色变为蓝色(x<= 539)
- 当屏幕大于等于540像素并且小于等于969像素的时候背景颜色为绿色( 540=< x <= 969)
- 当屏幕大于等于970像素的时候,背景颜色为红色( x>= 970)
/* 宽度小于等于539时 */
@media screen and (max-width: 539px) {
body {
background: #0000ff;
}
}
/* 宽度大于等于540、小于等于969时 */
/* 下面这个是上面一行的简易写法,原理是当宽度大于970时会层叠掉绿色的属性 */
/* @media screen and (min-width: 540px) and (max-width: 969px) { */
@media screen and (min-width: 540px) {
body {
background: #00ff00;
}
}
/* 宽度大于等于970时 */
@media screen and (min-width: 970px) {
body {
background: #ff0000;
}
}
媒体查询+rem实现元素大小动态变化
使用媒体查询修改html根元素得字号,其他元素使用rem单位就可以随着html变化而变化
案例
需求:让文字字号、背景和高度随着宽度变化而变化
<style>
/* 默认html字号 */
html {
font-size: 20px;
}
/* 宽度大于等于640时,修改html字号 */
@media screen and (min-width: 640px) {
html {
font-size: 30px;
}
}
* {
margin: 0;
padding: 0;
}
div {
width: 100%;
height: 3rem;
background: #0f0;
text-align: center;
line-height: 3rem;
}
</style>
<div>购物车</div>
引入资源
当样式比较繁多的时候,我们可以针对不同的媒体使用不同stylesheets (样式表)
原理就是直接在<link>中判断设备的尺寸,然后引用不同的css文件。
语法规范
<link rel= "stylesheet" media=" mediatype andnotlonly (media feature)" href=" mystylesheet.css">
示例
/* 在屏幕宽度大于等于400px时引入styleA.css文件 */
<link rel="stylesheet" href="styleA.css" media="screen and (min-width: 400px)">
建议:从小尺寸到大尺寸引入
less基础
css弊端
CSS是一门非程序式语言,没有变量、函数、SCOPE (作用域)等概念
- CSS需要书写大量看似没有逻辑的代码,CSS 冗余度是比较高的。
- 不方便维护及扩展,不利于复用。
- CSS没有很好的计算能力
- 非前端开发工程师来讲,往往会因为缺少CSS编写经验而很难写出组织良好且易于维护的CSS代码项目。
less简介和安装
- Less (Leaner Style Sheets的缩写)是一门CSS扩展语言,也成为CSS预处理器。
- 做为CSS的一种形式的扩展,它并没有减少CSS的功能,而是在现有的CSS语法上,为CSS加入程序式语言的特性。
- 它在CSS的语法基础之上,引入了变量,Mixin (混入),运算以及函数等功能,大大简化CSS的编写
- 降低了CSS的维护成本,就像它的名称所说的那样,Less 可以让我们用更少的代码做更多的事情。
Less中文网址: lesscss.cn/
常见的CSS预处理器: Sass、 Less、 Stylus
Less是一JCSS预处理语言,它扩展了CSS的动态特性。
安装
- 安装nodejs,可选择最新的版本,网址: https://nodejs org/en/download/
- 检查是否安装成功,使用cmd命令(win10 是window +r打开运行输入cmd)输入 ” node -v "查看版本即可
- 基于node.js在线安装Less,使用cmd命令”npm install -g less”即可
- 检查是否安装成功,使用cmd命令『 lessc -V』 查看版本即可
less使用
首先创建一个.less文件,在里面书写less语句
less变量
变量是指没有固定的值,可以动态改变的。因为我们CSS中的- -些颜色和数值等经常使用。
书写方法:@变量名:值;
变量命名规范
- 必须有@为前缀
- 不能包含特殊字符
- 不能以数字开头
- 大小写敏感
例如:@color: pink;
使用规范
直接在样式里面引入
/* 创建变量 */
@color: pink;
body {
/* 直接使用 */
background: @color;
}
less编译
本质上,Less 包含一套自定义的语法及一个解析器,用户根据这些语法定义自己的样式规则,这些规则最终会通过解析器,编译生成对应的CSS文件。所以,我们需要把我们的.less文件,编译生成为.css 文件,这样我们的html页面才能使用。
推荐方法(nodejs) :在当前文件夹,使用cmd命令“lessc style.less > style.css”
更推荐方法:VScode安装easy less插件,重启后每当保存less文件会自动生成一个同名的css文件,然后在html文件中引入css即可
less嵌套
类似于html结构嵌套,可以直接书写选择器嵌套,使逻辑更加清晰
后代选择器:
#header .logo {
wudth: 100px
}
在less中的写法
#header {
/* 选中#header后代.logo */
.logo {
width: 100px;
}
}
交集|伪类|伪元素选择器
使用&符号代表前一层选择器
/* 伪类选择器 */
a {
&:hover {
color: red;
}
}
/* 伪元素选择器 */
a {
&::after {
content: "";
}
}
/* 交集选择器 */
a {
&.div {
color: red;
}
}
less运算
任何数字、颜色、或者变量都可以参与运算。less提供加减乘除四则运算
200rem / 50px 结果输出4rem
#999 - #333 结果输出#666
注意事项:
- 参与运算的两个数字如果只有一个单位,则继承单位
- 如果都有单位,取第一个数字的单位
- less运算符左右必须有空格
rem适配方案
让页面不能进行等比例适配的元素可以根据宽度等比例适配
使用媒体查询判断宽度,根据宽度设置rem基础字号,元素使用rem单位设置宽高等属性
rem实际开发适配方案
- 按照设计稿与设备宽度的比例,动态计算并设置html根标签的font- size大小; (媒体查询)
- CSS中,设计稿元素的宽、高、相对位置等取值,按照同等比例换算为rem为单位的值
rem适配方案的使用(市场主流)
- 方案1:less + 媒体查询 + rem
- 方案2:淘宝flexible.js + rem (推荐)
方案1
常见设计稿尺寸
| 设备 | 常见宽度 |
|---|---|
| iphone 4/5 | 640px |
| iphone 6/7/8 | 750px |
| Android | 常见320px. 480px、 540px、 600px、 720px、 768px、 800px、 1080px 目前市场主流设备尺寸按照1080px设计 |
一般情况下,我们以一套或两套效果图适应大部分的屏幕,放弃极端屏或对其优雅降级,牺牲一些效果,现在基本以750为准。
具体实施
- 假设设计稿为750px
- 人为假设把屏幕分为15等分(也可以是其他数字)
- 每一份html字体大小就是50px
- 那么适配比如320px的设备时,字体大小就是320px/15 = 21.33px
- 用我们的页面大小除以不同的html字号大小,就可以得到想要的rem数值
比如我们以750px为标准设计稿:
- 一个100* 100像素的页面元素在750屏幕下,就是100 / 50转换为rem是2rem *2 rem比例是1比1
- 320屏幕下,html 字体大小为21.33则2rem = 42.66px此时宽和高都是42.66但是宽和高的比例还是1比1 但是已经能实现不同屏幕下页面元素盒子等比例缩放的效果
元素大小取值方法
- 最后的公式:页面元素的rem值=页面元素值(px)/(屏幕宽度/划分的份数)
- 屏幕宽度/划分的份数就是 html font-size的大
- 或者:页面元素的rem值=页面元素值(p)/ html font-ize字体大小
苏宁首页案例(m.suning.com)
技术选型
- 方案:我们采取单独制作移动页面方案
- 技术:布局采取rem适配布局(less+rem+媒体查询)
- 设计图:本设计图采用750p×设计尺寸
准备工作
- 搭建文件结构(html + css文件夹 + images文件夹)
- html文件设置视口、引入初始化css
- 设置公共样式的common.less文件并引入common.css文件
- 新建common.less设置好最常见的屏幕尺寸,利用媒体查询设置不同的html字体大小,因为 除了首页其他页面也需要。
- 苏宁网站首页的开发尺寸有320px、360px、 375px、 384px、 400px、 414px、 424px、480px、540px、 720px、 750px等。
- 划分的份数我们定为15等份。
- 因为我们pc端也可以打开我们苏宁移动端首页,我们默认html字体大小为50px,注意这句话写到最上面。
- 新建index.less文件,并在里面引入common.less文件(@import "common")在index.html中引入index.css文件
body样式
//body样式
body {
min-width: 320px;
width: 15rem;
margin: 0 auto;
line-height: 1.5;
font-family: Arial, Helvetica, STHeiTi, sans-serif;
background: #f2f2f2;
}
top-banner区域
结构分析:
整体大盒子里面包裹两个a标签,第一个a标签包裹整个图片区域,另一个放置左边的关闭按钮
<!-- top-botter部分 -->
<div class="top-banner">
<a href="javastricp:;">
<img src="./images/top_banner.jpg" alt="">
</a>
<a href="javastricp:;"></a>
</div>
<!-- top-botter部分结束 -->
// top-banner区域
.top-banner {
position: relative;
width: 15rem;
height: 2rem;
//背景图
& a:nth-child(1) {
display: block;
width: 100%;
height: 100%;
& img {
display: block;
height: 100%;
width: 100%;
}
}
//关闭按钮
& a:nth-child(2) {
position: absolute;
top: 0.5rem;
left: 0.1rem;
width: 1rem;
height: 1rem;
background: url(../images/close.png) no-repeat center center;
background-size: 0.6rem auto;
}
}
header区域
结构分析
总体分我上下两层,上面从左到右为三个元素,可以使用flex布局,下面盒子实际上也有三个元素,最上面覆盖了一个a标签点击跳转到其他页面,下面有一个小图标和一个form标签,form标签内部有一个input
<!-- header部分 -->
<div class="header">
<!-- 上部 -->
<div class="header-top">
<a href="javastricp:;"><img src="./images/classify.png" alt=""></a>
<a href="javastricp:;"><img src="./images/ad.gif" alt=""></a>
<a href="javastricp:;"><img src="./images/login.png" alt=""></a>
</div>
<!-- 下部 -->
<div class="header-bottom">
<i></i>
<form action="header-bottom-from">
<input type="seach" placeholder="400元北京消费补贴">
</form>
<a href="javastricp:;"></a>
</div>
</div>
<!-- header部分结束 -->
// header区域
.header {
width: 15rem;
height: 3.6rem;
background: #ffdb47;
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
width: 15rem;
height: 1.76rem;
padding: 0 0.68rem;
box-sizing: border-box;
& a:nth-child(1) {
width: 0.72rem;
height: 1.2rem;
img {
width: 100%;
}
}
& a:nth-child(2) {
width: 9rem;
height: 1.1rem;
img {
width: 100%;
}
}
& a:nth-child(3) {
width: 0.72rem;
height: 1.2rem;
img {
width: 100%;
}
}
}
.header-bottom {
position: relative;
width: 15rem;
height: 1.84rem;
padding: 0 0.48rem;
box-sizing: border-box;
a {
position: absolute;
left: 0.48rem;
top: 0;
display: block;
width: 14.04rem;
height: 1.76rem;
}
i {
position: absolute;
left: 0.84rem;
top: 0.52rem;
width: 0.72rem;
height: 0.72rem;
background: url(../images/search_btn.png) no-repeat 0 0;
background-size: 0.72rem auto;
}
form {
display: flex;
align-items: center;
width: 14.04rem;
height: 1.76rem;
input {
width: 14.4rem;
height: 1.28rem;
border: 0;
padding: 0.06rem 0.4rem 0 1.3rem;
box-sizing: border-box;
border-radius: 0.62rem;
background: #fff;
font-size: 0.56rem;
line-height: 1.28rem;
}
}
}
}
banner区域
结构分析:整体结构一个大个子包裹一套轮播图,需要设置背景,注意轮播图使用三位置法
<!-- banner区域 -->
<div class="banner">
<!-- 图片列表 -->
<ul>
<li class="now"><img src="./images/banner.jpg" alt=""></li>
<li><img src="./images/banner.jpg" alt=""></li>
<li><img src="./images/banner.jpg" alt=""></li>
<li><img src="./images/banner.jpg" alt=""></li>
<li><img src="./images/banner.jpg" alt=""></li>
<li><img src="./images/banner.jpg" alt=""></li>
</ul>
小指示灯
<ol>
<li class="now"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ol>
</div>
<!-- banner区域结束 -->
// banner区域
.banner {
position: relative;
width: 15rem;
height: 5.2rem;
background: url(../images/banner_bg.png) no-repeat 0 0;
background-size: 15rem auto;
ul {
position: relative;
width: 14.04rem;
height: 5.2rem;
margin: 0 auto;
border-radius: 0.48rem;
background: #cccccc;
overflow: hidden;
li {
position: absolute;
top: 0;
left: 100%;
width: 100%;
height: 100%;
&.now {
left: 0;
}
img {
display: block;
width: 100%;
height: 100%;
}
}
}
ol {
display: flex;
justify-content: space-between;
position: absolute;
left: 50%;
bottom: 0.2rem;
width: 2rem;
height: 0.2rem;
margin-left: -1rem;
li {
width: 0.2rem;
height: 0.2rem;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
&.now {
background: rgba(255, 255, 255, 1);
}
}
}
}
nav区域
结构分析:
大盒子包裹10个小盒子,每个盒子里面可以使用flex布局或者其他昂时都可以
<!-- nav部分 -->
<div class="nav">
<ul>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
<li>
<img src="./images/nav_01.png" alt="">
<p>苏宁秒杀</p>
</li>
</ul>
</div>
<!-- nav部分结束 -->
//nav区域
.nav {
width: 15rem;
ul {
width: 100%;
overflow: hidden;
li {
float: left;
width: 3rem;
height: 2.84rem;
text-align: center;
img {
display: block;
width: 1.68rem;
height: 1.68rem;
margin: 0.48rem 0.66rem 0;
}
p {
margin: 0.1rem 0 0.44rem;
font-size: 0.44rem;
line-height: 0.56rem;
color: #666;
}
}
}
}
方案2 (flexible.js + rem)
- 手机淘宝团队出的简洁高效移动端适配库
- 我们再也不需要在写不同屏幕的媒体查询,因为里面js做了处理
- 它的原理是把当前设备划分为10等份,但是不同设备下,比例还是一致的。
- 我们要做的,就是确定好我们当前设备的html文字大小就可以了
- 比如当前设计稿是750px,那么我们只需要把 html文字大小设置为75px(750px / 10)就可以 里面页面元素rem值:页面元素的px 值/ 75剩余的,让flexible.js来去算
github地址: github.com/amfe/lib-fl…
引入js文件
<!-- 引入flexible.js文件 -->
<scricp src="js/flexible.js"></script>
更改flexible.js最大像素值
引入flexible.js文件
新建css文件,利用媒体查询将超过750px的屏幕字号设置为75px
@media screen and (min-width: 750px) {
html {
/* 使用!important关键字强制设置文字字号 */
font-size: 75px !important;
}
}
vscode插件cssrem
使用flexible.js制作苏宁首页案例的时候方法是相同的,可以不实用less(当然也可以使用),可以使vscode插件cssrem,这个插件会在你输入px值的时候提供选项自动转换成rem数值
注意:vscode有一个默认的rem字号,可能不是我们想要的,这时可以更改默认的rem字号(在设置里面直接搜索rem即可),然后重启vscode就可以使用flexible.js制作了