1.移動端基礎
1.1 瀏覽器現狀
PC端瀏覽器
360瀏覽器、谷歌瀏覽器、火狐瀏覽器、QQ瀏覽器、百度瀏覽器(停止服務)、搜狗瀏覽器、IE瀏覽器
移動端瀏覽器
UC、QQ瀏覽器、歐朋瀏覽器、百度手機瀏覽器、360、搜狗、獵豹、谷歌等其他手機自帶的瀏覽器
國內尚無自主研發的瀏覽器內核,就像國內的手機操作系統都是基于android 修改開發一樣
總結:兼容移動端主流瀏覽器,處理webkit 內核瀏覽器即可
1.2 手機屏幕現狀
- 移動端屏幕尺寸非常多、碎片化嚴重
- Android設備有多種分辨率,480X800、480X854、540X960、720x1280、1080x1920,還有2K、4K屏
- 近年來 iphone 的碎片化也加劇了,其設備主要分辨率有 640x960、640x1136、750x1334、1242x2208
- 作為前端開發人員無需關注這些分辨率,因為我們常用尺寸為 px(邏輯像素)
1.3 常見移動端屏幕尺寸
參考
https://www.material.io/resources/devices/
作為前端開發,不要去糾結 dp、dpi、pt、ppi 等單位,因為我們不是做原生開發的
1.4 調試方法
- chrome DevTools 模擬手機
- 搭建本地web服務,手機和服務器在一個局域網內,通過手機訪問服務器
- 使用外網服務器,直接IP或者域名訪問
2. 視口
布局視口
視覺視口
理想視口
2.1 為什么使用視口
移動開發興起后,出現的概念
也就是說,如果我們開發的頁面只需要適應PC端,則不用考慮視口的概念
看下面的代碼,并沒有對視口進行配置
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>.box{width: 300px;}</style>
</head><body>
<img class="box" src="./3.jpg" alt="">
</body></html>
在PC端的表現和在手機端的表現分別如下
原因在于,我們在手機端瀏覽中渲染此頁面時,手機設置了視口為980,而我們手機屏幕的寬度為 375,默認情況下PC上的內容是無法在手機端顯示完整的,會出現橫向滾動條
手機上的瀏覽器一般不會允許出現這個橫向滾動條,所以都會對內容進行縮放,也就是原來需要在980px 上顯示的內容,縮放到375px 上就能夠展示,你們頁面中的所有元素就都要進行等比例的縮放
所以,在我們看來,圖片變小了
2.2 設置視口寬度
解決方法:設置視口
設置固定寬度
作用是覆蓋默認980的設置,而是自己設置
<meta name="viewport" content="width=375">
再看一下手機端的表現
此時圖片大小與PC端就一致了
原因在于設置了視口寬度與設備寬度一致,也就是1:1 的關系,則頁面內容不會縮放,圖片也就按照原來設置的尺寸展示
試實設置視口為750px 看看什么效果,說說為什么?
使用設備寬度
不同設備的寬度不一樣,為了更好的適配不同的設備,可以使用下面的設置
<meta name="viewport" content="width=device-width">
2.3 設置縮放比
刪除上面的代碼,實時下面的代碼
<meta name="viewport" content="initial-scale=1">
效果相當于
<meta name="viewport" content="width=device-width">
initial-scale 的值也可以設置為其他倍數
2.4 用戶縮放
上面的 initial-scale 和 width ,都是開發人員設置的頁面初始化的縮放設置
下面是對用戶對頁面縮放的控制
很多時候,我們不希望用戶縮放頁面,進而導致將我們的布局搞亂,可以使用下面的配置
user-scalable=no
完整配置
<meta name="viewport" content="initial-scale=1,user-scalable=no">
此時,用戶就無法在瀏覽中進行頁面的縮放
當然,也可以使用下面的配置替代 user-scalabel
<meta name="viewport" content="initial-scale=1,minimum-scale=1, maximum-scale=1">
為了兼容性,規范的寫法是都寫上
2.5 完整寫法
結合前面所講的所有只是,viewport 的完整寫法如下
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,minimum-scale=1, maximum-scale=1">
2.6 通過 js 獲取視口尺寸
可以通過下面的幾種方法,獲取視口的寬度,注意這里獲取的是邏輯像素
console.log(window.innerWidth)
console.log(document.documentElement.clientWidth)
console.log(document.documentElement.getBoundingClientRect().width)
為了更好的兼容性,更推薦下面的寫法
var clientWidth=window.innerWidth||document.documentElement.clientWidth||document.documentElement.getBoundingClientRect().width
可以通過下面的代碼獲取物理像素
console.log(screen.width)
可以通過如下方法獲取像素比(dpr)
console.log(window.devicePixelRatio)
可以通過開發者工具顯示出dpr
3. 像素
本節涉及的知識點:
分辨率、物理像素、CSS 像素、設備像素比(dpr)、標清屏和高清屏、縮放、PPI/DPI
3.1 物理像素
手機屏幕橫向有828個點
手機屏幕縱向上有1792個點
同等大小屏幕下,點越多、圖像顯示越精細
上面所說屏幕上一個個點就是物理像素(physical pixel)
物理像素也叫設備像素(dp:device pixel)
可見,每個像素就是一個點,每個點由紅綠藍三原色組成,只需要控制每個點每種顏色的明暗,就可以顯示不同的顏色
實際開發中使用物理像素嗎
看下面的例子
同等屏幕大小的兩個手機
一個橫向有2個物理像素,一個有4個物理像素
如果使用物理像素,則很明顯展示的效果不一樣,在高清屏幕下,可能圖片會顯示的很小,設置都會看看不清楚
也就是說,在實際開發中,我們使用設備的物理像素
3.2 CSS 像素
CSS 像素,也叫邏輯像素(logical pixel)
也成為 設備獨立像素(dip:divice independent pixel)
我們在開發當中使用的就是CSS像素
.box {
width: 1000px;
height: 500px;
}
CSS像素與物理像素的關系
mark
在標清屏下,1個css像素使用1個物理像素展示
在高清屏下,1個css像素使用4個物理像素表示
注意:高清屏下,4個點相當于標清屏下1個點的大小,所以說在高清屏下1個css像素使用4個物理像素表示
點越多,展示的越精細,想想燈帶。。。。
瀏覽器會根據當前設備屏幕,自動換算出1個CSS像素使用多少個物理像素表示
3.3 設備像素比
設備像素比(dpr:device pixel ratio)
dpr=設備像素/CSS 像素(縮放比是1的情況下)
所以上面兩種屏幕下的 dpr 分別為
mark
dpr=2 表示的1個css 像素使用 2X2 個設備像素繪制
注意:計算時指的是1個方向上,橫向或者縱向
所以 dpr>1 的我們都可以認為是高清屏
3.3.1 二倍圖
對于一張50px * 50px(css像素)的圖片,在手機 Retina 屏中打開,按照上面介紹的物理像素比會放大倍數,這樣會造成圖片模糊
在標準的viewport 設置中,使用倍圖來提高圖片質量,解決在高清屏設備中的模糊問題
通常使用二倍圖,因為在 iphone6\7\8 的影響,但是現在還存在3倍圖、4倍圖的情況,這個看實際開發公司需求
背景圖片注意縮放問題
具體解決方案
準備一張100 * 100 的圖片,但是通過css 將其設置成50 * 50,在高清屏上,會將其放大2被,變成 100 * 100,因為圖片背身就是100 * 100,所以不會失真
需要注意的是,一定將其設置成50 * 50,否則會將其放大成200 * 200,仍然會失真



如何快速起初2倍圖、3倍圖,別忘了我們PS中的切圖神器
3.4 縮放
縮放改變的是CSS像素,畢竟我們沒有法力
放大:
mark
縮小:
3.5 PPI
每英寸的物理像素點,見圖1
ppi:pixels per inch,可以根據勾股定律進行英寸
注意,因為手機不是正方形的,所以 6.1英寸只是大約值,實際計算時,可以使用 6.06
dpi:dots per inch
- 移動端開發選擇
4.1 主流方案
單獨制作移動端頁面(主流):一般在域名前面加上 m,可以打開移動端,如果是移動設備,能夠自動判斷,也就是說同各國檢測時PC設備還是移動設備,響應不同的頁面
響應式頁面兼容移動端(其次):根據屏幕的寬度來改變樣式。缺點:制作麻煩、需要花很大精力去調兼容性問題 - 移動端技術解決方案
5.1 移動端瀏覽器
移動端瀏覽器基本以 webkit 內核為主,因此只需要考慮 webkit 兼容性即可
可以放心使用 H5 和 CSS3 的新特性
同時瀏覽器的私有前綴只需要添加 webkit 即可
mark
5.2 CSS 初始化
normalize.css
保護了有價值的默認樣式
修復了瀏覽器的bug
模塊化的
擁有詳細的文檔
http://necolas.github.io/normalize.css/
5.3 CSS3 盒子模型 box-sizing
設置盒子的尺寸以內容為準還是邊框為準
傳統模式寬度計算:盒子寬度= CSS 中設置的 border+width+padding
CSS3 盒子模型:盒子寬度=CSS 中設置的width 里面包含了 border 和 padding
也即是說 CSS3 盒子模型中,padding 和 border 的設置不會撐大盒子了
注意:移動端可以全部使用CSS3盒子模型,PC端如果需要兼容,使用傳統模式,不考慮兼容,使用CSS3 盒子模型


點擊超鏈接時,會有背景高亮效果,建議去除
按鈕會有默認樣式,建議去除
圖片、超鏈接等長按會彈出菜單,建議去除(兼容性很不好)
a {
/* 去除超鏈接點擊時的背景高亮效果 /
-webkit-tap-highlight-color: transparent;
}
/ 禁用長按顯示菜單 */
img,
a {
-webkit-touch-callout: none;
}
/去除按鈕的默認樣式,然后才可以為按鈕自定義樣式/
button,
input {
-webkit-appearance: none;
}
6. 移動端常見布局
6.1 移動端技術選型
首先從下面兩種方案中選擇一種
單獨制作移動端頁面(主流)
流式布局(百分比布局)
flex彈性布局(強烈推薦)
less+rem+媒體查詢布局
混合布局
響應式頁面兼容移動端
媒體查詢
bootstrap
6.2 流式布局
流式布局,就是百分比布局,也稱作非固定像素布局
通過盒子的寬度設置城百分比來根據屏幕的寬度進行伸縮,不受固定像素的限制,內容向兩側填充
流式布局時移動web開發使用的比較常見的布局方式
6.3.2 初始化主頁
引入 normalize.css
引入 index.css
編寫視口
參考京東移動端代碼
mark
6.3.4 頭部布局
mark
京東頭部可以分為4個部分
通過查看京東官網發現,百分比分別為 8%、10%、57%、25%
第4部分的顏色與其他部分的背景顏色不一致
html中添加頭部
- 8
- 10
- 57
- 25
在 index.css 中編寫樣式
/* 頭部樣式 */
.app{
width: 100%;
height: 45px;
}
.app ul{
margin: 0;
padding: 0;
list-style-type: none;
}
.app li{
float: left;
height: 45px;
background-color: #333333;
}
.app li:nth-child(1){
width: 8%;
}
.app li:nth-child(2){
width: 10%;
}
.app li:nth-child(3){
width: 57%;
}
.app li:nth-child(4){
width: 25%;
background-color: #f63515;
}
填充內容
第一部分是一個關閉圖標,尺寸為1010
第二部分為網站Logo,尺寸為3030
第三部分和第四部分文字為白色
頭部所有文字和圖片都是水平居中且垂直居中對齊
注意圖片無法通過設置行高等于高度的方式居中對齊
修改 index.html 中的 header 中的代碼
mark
修改 index.css 中的代碼
mark
mark
6.3.5 搜索制作
通過觀察京東,發現如下幾點
搜索分為三部分
左側展開折疊按鈕尺寸固定,不要使用百分比
右側登錄按鈕尺寸固定,不要使用百分比
中間搜索框會隨著屏幕大小的調節而進行縮放
技術實現
搜索區域高度為44px
左右兩側按鈕寬高都為40*44,且分別做固定在左邊和固定在右邊,需要使用絕對定位
中間搜索區域白色背景,圓角,高度為30px,margin-left 和 margin-right 分別為50px
布局
在 index.html 中加入如下代碼
mark
制作左側和右側
左側和右側相對簡單,所以先制作這兩部分
html 代碼
mark
css 代碼
mark
制作放大鏡
京東上使用的是二倍精靈圖,所以使用起來要遵循下面步驟
將精靈圖等比例縮小一半
之后根據大小測量坐標
注意代碼里面background-size也要寫成精靈圖原來的一半
html 代碼
mark
css 代碼
mark
制作輸入框
html 代碼
mark
css 代碼
mark
6.3.6 焦點圖
html 代碼
mark
css 代碼
mark
不要忘了,將 search-box 盒子的定位修改為 固定定位,且 寬度設置為 100%
mark
6.3.7 活動區域
html 代碼
mark
css 代碼
mark
6.6.8 類別區域
html 代碼










mark
- flex 布局
7.1 傳統布局與flex布局
傳統布局:
兼容性好
布局繁瑣
局限性,對移動端的支持不好
flex 唐興布局
操作方便,布局極為簡單,移動端應用廣泛
PC段瀏覽器支持情況較差
IE11或更低版本,不支持或僅部分支持
建議:
PC端頁面,使用傳統布局
移動端頁面或者不考慮兼容性問題的PC段頁面布局,使用flex 彈性布局
7.2 愛的初體驗
html 代碼
mark
加入flex
為 div 加入如下 css 樣式
mark
運行結果
mark
總結
在為div設置 display:flex 之前,span元素的 display=inline
在為div設置 display:flex 之后,span 元素的display=block,所以高度生效,但是因為寬度沒有設置,故為內容寬度
可見,通過為父元素設置 display:flex 子元素無論原來是什么元素,都會變成 block,但是寬度并不會占據父元素的100%,而且也不會獨占1行
設置固定寬度
可以為span元素設置寬度
span{
width: 100px;
height: 100px;
background-color: #fff;
}
設置后,寬度會生效,但是,當調整瀏覽器寬度,默認情況下,span的寬度仍然會壓縮
設置對齊方式
在 div 中加入如下代碼
mark
運行結果
mark
設置平分
也可以不設置固定寬度,而是使用如下代碼
span {
/* width: 100px; */
flex: 1;
height: 100px;
background-color: #fff;
}
此種設置三個span元素將會評分父元素的寬度
mark
7.3 布局原理
flex:flex box 的縮寫
意為 彈性布局,用來為盒狀模型提供最大的靈活性,任何一個容器都可以指定為 flex,但是我們不會變態到將 i 標簽指定為 flex
當我們將父盒子設置為flex后,子元素的float、clear、vertical-align 屬性失效
采用Flex布局的元素,成為Flex容器(flex container),簡稱“容器”,它的所有子元素自動成為容器成員,成為Flex項目(flex item),簡稱“項目”
子元素可以橫向排列,也可以縱向排列
mark
布局原理總結
通過給父盒子添加flex屬性,來控制子盒子的位置和排列方式
7.4 容器常用屬性
一下屬性用于設置容器,也就是父盒子
felx-direction:設置主軸的方向,也就是項目橫向排列還是縱向排列
justify-content:設置主軸上的子元素的排列方式
flex-wrap:設置子元素是否換行
align-content:設置側軸上子元素的排列方式(多行)
align-items:設置側軸上的子元素排列方式(單行)
flex-flow:復合屬性,相當于同時設置了flex-directon 和 flex-wrap
7.4.1 flex-direction
在flex布局中,分為主軸和側軸
默認情況下,水平方向為主軸,水平向右,垂直方向為側軸,垂直向下
mark
flex-direction 屬性可以改變默認的主軸設置
設置行為主軸
設置水平方向為主軸,項目從左向右排列
body {
background-color: #ccc;
}
div {
display:flex;
/設置容器的主軸為X軸,也就是行為主軸,此值為默認值/
flex-direction: row;
width: 800px;
height: 400px;
background-color: #000;
}
span {
width: 100px;
height: 100px;
background-color: #fff;
border: 1px solid black;
}
設置主軸反轉
反轉主軸
設置水平方向為主軸,項目從右向左排列
只需要將如下代碼
flex-direction: row;
修改為
flex-direction: row-reverse;
設置列為主軸
設置主軸為垂直方向,項目從上到下排列
設置 flex-direction 的值 column
flex-direction: column;
將上面的代碼改為
flex-direction: column-reverse;
項目從下到上排列
總結
主軸不是固定的
項目永遠沿主軸排列,所以設置主軸為水平方向,項目1行排列;設置主軸為垂直方向,項目1列排
7.4.2 justify-content
設置主軸上項目的排列方式
使用此屬性之前,要確定主軸是哪一個,主軸不一樣,設置的值也不一樣
flex-start 默認值,從頭部開始,如果主軸是x軸,則從左到右
flex-end 從尾部開始排列,如果主軸是y軸,則從又到左
center 在主軸居中對齊,如果主軸是x軸,則水平居中
spance-around 評分剩余空間
spance-between 先兩邊貼邊,再評分剩余空間
7.4.2.1 X軸為主軸時
flex-start
body {
background-color: #ccc;
}
div {
display:flex;
/設置容器的主軸為X軸,也就是行為主軸,此值為默認值/
flex-direction: row;
/* 設置項目從左到右排列 */
justify-content: flex-start;
width: 800px;
height: 400px;
background-color: #000;
}
span {
width: 100px;
height: 100px;
background-color: #fff;
border: 1px solid black;
}
mark
這與沒設置 justify-content:flex-start 沒有區別
修改 justiry-content 的值為 flex-end
flex-end
/* 設置項目從左到右排列 */
justify-content: flex-end;
mark
注意,這里僅僅是改變了項目的起始方向,并沒有改變項目的排列順序,而我們上面說的 flex-direction 的翻轉會改變項目的排列順序
將 justify-content 的值設置為 center,所有元素居中顯示,兩邊編劇一致
center
justify-content:center;
mark
spance-around
justify-content:space-around;
問題:為什么明明是評分剩余空間,項目的中間距離,看起來是左側兩側邊距的2倍?
mark
注意:
容器-所有項目寬度之和,就是主軸上剩余的空間,這里的平分是指項目之間的距離平分這些空間
如果設置項目的flex:1,而不是設置項目的固定寬度,那么無論 justify-content 的值設置為什么,都沒有效果,因為項目會自動占滿整個容器寬度
space-between
justify-content:space-between;
mark
7.4.2.2 Y 軸為主軸
省略
7.4.3 flex-wrap
傳統布局中,設置子盒子浮動后,如果1行占不下,會自動另起一行
但是在 flex 布局中,則不然
html 代碼
body {
background-color: #ccc;
}
div {
display:flex;
/設置容器的主軸為X軸,也就是行為主軸,此值為默認值/
flex-direction: row;
/* 設置項目從左到右排列 */
justify-content:flex-start;
width: 500px;
height: 400px;
background-color: #000;
}
span {
width: 150px;
height: 100px;
background-color: #fff;
border: 1px solid black;
}
我們發現,當1行站不下所有項目時,會自動縮小項目的寬度
如果不希望改變寬度,而是另起一行,只需要在容器中據加入如下設置即可
flex-wrap: wrap;
mark
問題:為什么兩行之間的垂直間距這么大?
擴展
如果主軸為Y軸,則效果如下
mark
7.4.4 align-items
設置項目在側軸上的排列方式
但是此屬性適合項目為單行時
側軸默認是Y軸,當然可以改變
flex-start 默認值,從上到下
flex-end 從下到上
center 擠在一起居中
stretch 拉伸
7.4.4.1 解決的問題
當前只能通過 justify-content 設置項目在主軸上的位置
div {
display:flex;
/設置容器的主軸為X軸,也就是行為主軸,此值為默認值/
flex-direction: row;
/* 設置項目從左到右排列 */
justify-content:center;
width: 500px;
height: 400px;
background-color: #000;
}
mark
無法設置項目在側軸上居中,對于當前來說,側軸是y軸,那么也就是設置垂直居中
有人可能想到做如下修改
flex-direction: column;
但這樣只是修改了主軸為y軸
mark
當前屬性就是用來解決這個問題的
7.4.4.2 設置側軸居中
只需要在容器中加入
mark
效果
mark
問題:如果主軸為y軸呢?
mark
效果
mark
當然此屬性的只也可以設置為其他幾個
其他幾個值都比較簡單,稍微需要注意的是 stretch ,意思是拉伸,如果主軸是x軸,那么就會拉伸項目的高度與父元素一樣高,但是項目不能設置固定高度,否則無效
7.4.5 align-content
設置側軸上的子元素的排列方式
這與 align-items 相似,區別在于,此屬性用來設置多行項目(也就是項目換行)時的排列方式,在單行項目下時沒有效果的
flex-start 默認值,在側軸的頭部開始排列
flex-end 在側軸的尾部開始排列
center 在側軸的中間顯示
space-around 子項在側軸評分剩余空間
space=between 子項在側軸先分布在兩頭,再平分剩余空間
stretch 設置子項元素高度平分父元素
flex-start
mark
思考,主軸為y軸時如何排列
flex-end
mark
center
mark
space-around
mark
space-between
mark
**align-items 和 align-content 對比
align-items 適用于單行情況下,只有上對齊,下對齊,居中和拉伸
align-content 適用于多行,單行下無效,可以設置對上對齊、下對齊、居中、拉伸一級平分剩余空間等
7.4.6 flex-flow
flex-direction 和 flex-wrap 的復合屬性
flex-flow: column nowrap;
7.5 項目常見屬性
flex 項目占的份數
align-self 控制子項自己在側軸的排列方式,前面的align-items 和 align-content 是對所有子項應用相同的排列方式,而這個屬性是對單個子項應用個性化的排列方式
order 定義項目的排列順序(前后順序)
7.5.1 flex
定義子項目分配剩余空間,用 flex 屬性表示占多少分
分配的容器的剩余空間會增加到元素的寬度上
項目一旦設置固定寬度,就不會參與分配剩余空間
flex 的默認值為0,0就表示不參與分配剩余空間
項目一旦設置了flex,就不能再設置固定寬度
如果flex 的值為其他數字,則表示在分配剩余空間時所占的分數
圣杯效果
7.6.2 初始化主頁
mark
7.6.3 編寫body樣式
body {
max-width: 540px;
min-width: 320px;
margin: 0 auto;
background: #fafafc;
/* 去除橫向滾動條 /
overflow-x: hidden;
/ 去除移動端中超鏈接點擊時的背景高亮效果 */
-webkit-tap-highlight-color: transparent;
}
7.6.4 布局分析
很多元素的高度都是固定的,不會隨著窗口的變化而變化
7.6.5 搜索區域
固定定位
寬度設置為100%,因為設置為固定定位后,盒子成為inline-block
設置最大寬度、最小寬度,因為固定定位的元素的父元素是窗口,不是body,所以在body中設置的最大寬度、最小寬度、以及寬度,搜索盒子都不會繼承,必須單獨設置
水平居中的兩種方式
CSS3屬性的兼容性寫法
html 代碼
mark
index.css 中設置搜索框內部元素樣式
mark