前言:一般来说,一个比较大的网站和平台都有PC端和移动端两个网站点,即要写两套css样式,也有一些公司采用的是响应式布局(本质上也是两套css样式),今天就给大家介绍几种移动端的布局方式。
在介绍布局方式之前,先介绍一下视口:viewport,viewport是移动端特有的一个承载网页的虚拟区域,是浏览器承载视口,视口承载网页。我们在head标签内加入<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0">
这句话就完成了标准的移动端适配方案。
一、流式布局
1.移动端布局简介
- 流式布局就是百分比布局,非固定像素,内容向两侧填充,理解成流动的布局,称为流式布局
- 使用流式布局的时候,一般将大盒子设置为width:100%;
- 所有的盒模型最好设置为box-sizing: border-box;,防止内容溢出出现滚动条
- 不建议在移动端使用jquery,移动端有自己的专门的库,后面会说到
- 点击高亮:tap-highlight-color: red;
- 移动端浏览器的兼容:一般只需要加上前缀-webkit-就行了
- 清除图片下间隙:图片是行内块元素,它有一个默认的对齐方式(文字的基线),这样会导致图片有一个下间隙,给图片加display: block;让它变成块元素就可以清除下间隙了
- 多倍图失真问题:在移动端布局的时候,并不是所有的盒子(元素)都用百分比布局,比如一个小图标就需要设置固定像素,但是当图片原来的尺寸比你预留的盒子的大小要大很多时,就需要缩小背景图片来实现布局,对背景设置background-size属性即可
2.关于流式布局的几种布局技巧
1. 双飞翼布局
所谓双飞翼布局就是两边的盒子固定大小,中间的盒子自适应。
方法一:给两边的盒子设置固定大小,让他们定位到两边,给中间的盒子设置width:100%,并设置padding,padding的值为两边盒子的宽度,注意:一定要给中间的盒子设置box-sizing: border-box;否则无效。
方法二:给两边的盒子设置固定大小,让他们浮动到两边,此时会自动触发BFC,给中间的盒子设置width:100%,不用设置padding也可以做到双飞翼布局,但个人觉得方法一更好。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.left{
width: 100px;
height: 100px;
float: left;
background: red;
}
.right{
width: 100px;
height: 100px;
float: right;
background: green;
}
.mid{
width: 100%;
height: 100px;
background: #000;
}
</style>
</head>
<body>
<div class="left"></div>
<div class="right"></div>
<div class="mid"></div>
<!--这是方法二:
如果两边的盒子是浮动的话,注意看几个div的顺序,如果顺序不对,就达不到双飞翼的效果-->
</body>
</html>
2. 两栏布局
两栏布局就是并排两个盒子,其中一个盒子是固定大小,另一个盒子是自适应。
方法一:同上
方法二:先给第一个盒子设置固定宽高,然后让它向左或者右浮动,给第二个盒子设置overflow:hidden;触发BFC,这样就实现了两栏布局。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.left{
width: 100px;
height: 100px;
float: left;/*或者right*/
background: red;
}
.right{
height: 100px;
background: green;
overflow: hidden;
}
</style>
</head>
<body>
<div class="left"></div>
<div class="right"></div>
</body>
</html>
二、响应式布局
1.媒体查询
- 所谓响应式布局就是使用媒体查询能针对不同屏幕区间设置不同的布局和样式,媒体查询的语法:
@media screen and (max-width: 768px) and (min-width: 320px){属性样式}
- 写一套完整的媒体查询的样式:
@media screen and (max-width: 768px) {
/*1. 在超小屏设备的时候 768px以下 当前容器的宽度100% 背景蓝色*/
.container{
width: 100%;
background: blue;
}
}
@media screen and (min-width: 768px) and (max-width: 992px){
/*2. 在小屏设备的时候 768px-992px 当前容器的宽度750px 背景绿色*/
.container{
width: 750px;
background: green;
}
}
@media screen and (min-width: 992px) and (max-width: 1200px){
/*3. 在中屏设备的时候 992px-1200px 当前容器的宽度970px 背景红色*/
.container{
width: 970px;
background: red;
}
}
@media screen and (min-width: 1200px){
/*4. 在大屏设备的时候 1200px以上 当前容器的宽度1170px 背景黄色*/
.container{
width: 1170px;
background: yellow;
}
}
/*优化写法,screen可以省略*/
@media (max-width: 768px) {
/*1. 在超小屏设备的时候 768px以下 当前容器的宽度100% 背景蓝色*/
.container{
width: 100%;
background: blue;
}
}
@media (min-width: 768px){
/*2. 在小屏设备的时候 768px-992px 当前容器的宽度750px 背景绿色*/
.container{
width: 750px;
background: green;
}
}
@media (min-width: 992px) {
/*3. 在中屏设备的时候 992px-1200px 当前容器的宽度970px 背景红色*/
.container{
width: 970px;
background: red;
}
}
@media (min-width: 1200px){
/*4. 在大屏设备的时候 1200px以上 当前容器的宽度1170px 背景黄色*/
.container{
width: 1170px;
background: yellow;
}
}
更多的响应式布局可以参考bootstrap文档 http://www.bootcss.com/ ,Bootstrap提供了一套完整的响应式框架,推荐去系统地学一学。
三、rem布局
1.less
一般rem布局都会用less或者sass去做适配方案,所以我们先学习一下less:
1.less的变量
@charset "UTF-8";//使用less之前最好加上编码语句
@mainColor:#e92323;//变量的声明
@className:box;
div{
background: @mainColor;
}
a:hover{
color: @mainColor;
}
.@{className}{//字符串拼接时,要用{}把变量括起来
color: @mainColor;
}
用less编译后的css文件是这样的:
div {
background: #e92323;
}
a:hover {
color: #e92323;
}
.box {
color: #e92323;
}
2.混入
在 LESS 中,混入是指在一个 CLASS 中引入另外一个已经定义的 CLASS
- 类混入
.w50{
width: 50%;
}
.f_left{
float: left;
}
.f_right{
float: right;
}
.w50-f_left{
.w50();//就像一个函数一样,用已有的类调用
.f_left();
}
less编译之后是这样的:
.w50 {
width: 50%;
}
.f_left {
float: left;
}
.f_right {
float: right;
}
.w50-f_left {
width: 50%;
float: left;
}
- 函数混入
.w50(){
width: 50%;
}
.f_left(){
float: left;
}
.w50-f_left{
.w50();//相当于函数调用
.f_left();
}
less编译后的文件是:(函数混入比类混入的好处是函数混入编译后的css文件代码量更少)
.w50-f_left {
width: 50%;
float: left;
}
- 关于函数的传参问题:
1.如果没有定义参数,调用的时候不传参
2.如果函数定义了参数(没有默认值),调用的时候必须传参
3.定义了参数(有默认值),调用的时候可传可不传
.f(@direction:left){//设置参数的方法,和定义变量是一样的
float: @direction;
}
.borderRadius(@width:100px){
border-radius: @width;
-webkit-border-radius:@width;
-moz-border-radius:@width;
-o-border-radius:@width;
-ms-border-radius:@width;
}
.w50-f_left{
.f(right);//使用传参的方法更加方便
.borderRadius(20px);
}
less编译后的css文件是:
.w50-f_left {
float: right;
border-radius: 20px;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
-o-border-radius: 20px;
-ms-border-radius: 20px;
}
3.嵌套
- 嵌套就是在A选择器里面嵌套一个B选择器,用于B是A的后代时:
注:需要连接的地方(使用伪类选择的时候)用&连接
.wjs_app{
display: block;
img{
display: none;
}
/*需要连接的情况:&*/
&:hover{
img{
display: block;
}
}
> div{
display: block;
}
}
编译后的css文件是:
.wjs_app {
display: block;
}
.wjs_app img {
display: none;
}
.wjs_app:hover img {
display: block;
}
.wjs_app > div {
display: block;
}
4.导入
就像c语言引用头文件一样,less可以导入其他的less文件:用@import "文件名"
来进行导入
比如有一个文件名叫topBar.less的文件,我要在另一个less文件中导入它:
@import "topBar";
5.运算和内置函数
- less可以用进行一些基本运算:
@num:5;
ul{
width: 100%*@num;
li{
width: 100%/@num;
color: red+yellow+blue;
background: gray*0.3;
/*内置函数*/
border-color: darken(red,20%);
}
}
上面的darken(red,20%);是less的一个内置函数,更多的内置函数参考文档 https://www.html.cn/doc/less/
6.在浏览器中使用less
- 像引入css文件一样引入less文件:
<link rel="stylesheet" type="text/less" href="test.less">
- 然后引入js文件:
<script src="https://cdn.bootcss.com/less.js/3.9.0/less.min.js"></script>
2.rem布局
1.rem介绍
-
rem是相对单位
-
em大小是基于父元素的字体大小
-
rem的大小是基于html元素的字体大小
-
r 意思 root 根元素,html标签
-
rem布局的优势:不管是流式布局、flex布局还是响应式布局,他们都是只能做到宽度的自适应,而rem可以做到宽度和高度一起自适应
-
rem布局:通过控制html上的字体大小去控制页面上所有以rem为单位的基准值控制尺寸,这样当设备发生变化的时候,只需要改变html上的字体大小就可以做到自适应了。
-
将此段代码加到html文件中,就可实现html的font-size属性根据设备大小变化,实现rem布局
<script>
(function (doc, win) {
var docEl = doc.documentElement;
resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize';
recalc = function () {
var clientWidth = docEl.clientWidth > 1024 ? 1024 : docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = clientWidth / 3.75 + 'px';
};
win.addEventListener(resizeEvt, recalc, false);
recalc();
})(document, window);
</script>
2.rem布局实现
- 一般来说,要做rem适配比较麻烦且不好维护,因为市面上的设备更新快,要做rem适配的流程大概是这样的:
1.拿到页面设计稿,测量设计稿的宽度并记录
2.预设一个html字体基准值,比如是100px,(意思就是假如设备是设计稿的宽度,就把设置html上的字体大小为100px)然后测量设计稿的元素(盒子)的大小并把单位px转成rem。(比如在设计稿上某个盒子的高是90px,就把它的高设置为0.9rem)
3.当设备大小改变时,只需要改变html上的字体大小就可做到适配。
4.换算公式:当前html的字体大小=预设基准值/设计稿宽度*当前设备的宽度 - 我们可以通过js和媒体查询完成以上步骤,但为了更好地维护,我们可以用less来做适配
- 步骤如下:
1.设置变量:
@charset "UTF-8";
//变量
//rem适配方案不好维护 设备会更新 设计稿尺寸 预设基准值
//适配主流设备十几种
@adapterDeviceList:750px,720px,640px,540px,480px,424px,414px,400px,384px,375px,360px,320px;
//设计稿尺寸
@psdWidth:750px;
//预设基准值
@baseFontSize:1000px;
//设备的种类
@len:length(@adapterDeviceList);
//主体颜色
@snColor:#fabc09;
2.遍历设备
.adapterMixin(@index) when ( @index > 0){
@media (min-width: extract(@adapterDeviceList,@index)){
html{
font-size: @baseFontSize / @psdWidth * extract(@adapterDeviceList,@index);
}
}
.adapterMixin( @index - 1);
}
.adapterMixin(@len);
//less里面没有for循环,可以采用函数的迭代来遍历循环,要注意迭代结束的条件
3.生成适配方案
- 把上面两段代码放在一个less文件里,就可以生成如下css文件,你可以添加更新设备大小,维护性高
@media (min-width: 320px) {
html {
font-size: 426.66666667px;
}
}
@media (min-width: 360px) {
html {
font-size: 480px;
}
}
@media (min-width: 375px) {
html {
font-size: 500px;
}
}
@media (min-width: 384px) {
html {
font-size: 512px;
}
}
@media (min-width: 400px) {
html {
font-size: 533.33333333px;
}
}
@media (min-width: 414px) {
html {
font-size: 552px;
}
}
@media (min-width: 424px) {
html {
font-size: 565.33333333px;
}
}
@media (min-width: 480px) {
html {
font-size: 640px;
}
}
@media (min-width: 540px) {
html {
font-size: 720px;
}
}
@media (min-width: 640px) {
html {
font-size: 853.33333333px;
}
}
@media (min-width: 720px) {
html {
font-size: 960px;
}
}
@media (min-width: 750px) {
html {
font-size: 1000px;
}
}