摘要:前言本來(lái)是打算寫寫怎么使用進(jìn)行移動(dòng)端的布局的然后前面還加些像素基本知識(shí)鋪墊后面又加了些屬性概念最后還來(lái)些常見(jiàn)布局問(wèn)題和系統(tǒng)樣式果然排版也是門高深學(xué)問(wèn)這里有些自己寫的有些看完之后總結(jié)出來(lái)的還有些別人那里搬來(lái)的順帶會(huì)送上飛機(jī)票告訴你們來(lái)源在哪
前言
本來(lái)是打算寫寫怎么使用 lib-flexible 進(jìn)行移動(dòng)端的布局的, 然后前面還加些像素基本知識(shí)鋪墊, 后面又加了些 CSS 屬性概念, 最后還來(lái)些常見(jiàn)布局問(wèn)題和系統(tǒng)樣式 bug, 果然排版也是門高深學(xué)問(wèn), 這里有些自己寫的, 有些看完之后總結(jié)出來(lái)的, 還有些別人那里搬來(lái)的, 順帶會(huì)送上飛機(jī)票告訴你們來(lái)源在哪里, 他們會(huì)更加仔細(xì), 畢竟我只是簡(jiǎn)明扼要的寫結(jié)論.
因?yàn)橹R(shí)點(diǎn)太多, 我沒(méi)有全都碰到過(guò), 所以最后的一些樣式解決辦法是覺(jué)得有用寫出來(lái)的, 沒(méi)試過(guò), 以后如果還有遇到其他問(wèn)題或者看到別人有意思的方案也會(huì)補(bǔ)充進(jìn)來(lái).
最后, 這文章我已經(jīng)轉(zhuǎn)成簡(jiǎn)體字了, 應(yīng)該不會(huì)再有人說(shuō)看的吃力了吧.
疑問(wèn)相比 PC 端, 移動(dòng)端怎么適配不同尺寸的屏幕?
為什么同一套代碼, 有些看起來(lái)很清晰, 有些看起來(lái)很模糊?
除了響應(yīng)式之外有一步到位的布局方法么?
為什么樣式?jīng)]寫錯(cuò), 有些手機(jī)用起來(lái)就是不正常?
怎么解決遇到的一些亂七八糟沒(méi)有邏輯的 bug?
像素基本知識(shí) 視窗 viewport:設(shè)備的屏幕上能用來(lái)顯示我們的網(wǎng)頁(yè)的那一塊區(qū)域, 而移動(dòng)端還提供了兩個(gè) viewport:
visual viewport(虛擬視口):
可以改變大小或形狀, 當(dāng)前屏幕上顯示的頁(yè)面的一部分
通過(guò) window.innerWidth/Height 獲取, 會(huì)隨著頁(yè)面縮放而變化
layout viewport(布局視口):
不會(huì)改變大小或形狀, 可以比可視化的 viewport 寬得多, 并且包含出現(xiàn)在屏幕上的元素
通過(guò) document.documentElement.clientWidth/Height 獲取. 在 Android 2, Oprea mini 和 UC 8 中無(wú)法正確獲取
ideal viewport(理想視口):不需要用戶縮放和滾動(dòng)就能正常的查看網(wǎng)站的所有內(nèi)容, 顯示的文字大小合適, 保證同樣的網(wǎng)站在不同分辨率的設(shè)備上看起來(lái)都是一樣或差不多的.
渲染過(guò)程:1) 渲染: 將整個(gè)頁(yè)面渲染在一個(gè) layout viewport 中, 以保證頁(yè)面排版正確;
2) 縮放: 將整個(gè) layout viewport 縮放到 visual viewport 大小, 以保證頁(yè)面在手機(jī)屏幕上被完整顯示出來(lái);
公式表示就是: visual viewpor = layout viewport * scale;
例如你在手機(jī)上訪問(wèn)一個(gè) PC 頁(yè)面, 手機(jī)當(dāng)前展示區(qū)域就是 visual viewport, 但是整個(gè) PC 頁(yè)面是很大的, 往往屏幕是顯示不完, 所以會(huì)出現(xiàn)滾動(dòng)條給你滑動(dòng)(固定值排版的話), 整個(gè) PC 頁(yè)面的尺寸就是 layout viewport 了, 上面說(shuō) visual viewport 可以改變大小或形狀, 意思是你可以通過(guò)旋轉(zhuǎn)屏幕或放大縮小改變顯示的頁(yè)面.
物理像素(physical pixel) || 設(shè)備像素:顯示設(shè)備中一個(gè)最微小的物理部件. 每個(gè)像素可以根據(jù)操作系統(tǒng)設(shè)置自己的顏色和亮度. 正是這些設(shè)備像素的微小距離欺騙了我們?nèi)庋劭吹降膱D像效果.
設(shè)備獨(dú)立像素(density-independent pixel) || 邏輯像素 || 密度無(wú)關(guān)像素:可以認(rèn)為是計(jì)算機(jī)坐標(biāo)系統(tǒng)中的一個(gè)點(diǎn), 這個(gè)點(diǎn)代表一個(gè)可以由程序使用并控制的虛擬像素(比如 CSS 像素), 然后由相關(guān)系統(tǒng)轉(zhuǎn)換為物理像素.
公式表示就是: CSS 像素 = 設(shè)備獨(dú)立像素 = 邏輯像素.
與設(shè)備無(wú)關(guān)的像素(device-independent pixel) || CSS 像素用于頁(yè)面布局的抽象單位, 用來(lái)精確度量網(wǎng)頁(yè)上的內(nèi)容, 在不同的設(shè)備或不同的環(huán)境中, css 中的 1px 所代表的設(shè)備物理像素的長(zhǎng)度可能是不同的
屏幕密度(pixels per inch) || 像素密度:即每英寸屏幕所擁有的像素?cái)?shù), 像素密度越大, 顯示畫面細(xì)節(jié)就越豐富,
公式表示就是: 像素密度 = 對(duì)角線分辨率 / 屏幕尺寸.
設(shè)備像素比(device pixel ratio):物理像素與邏輯像素之間的比例.
公式表示就是: 設(shè)備像素比(dpr) = 物理像素(pp) / 設(shè)備獨(dú)立像素(dip).
在 JavaScript 中, 可以通過(guò) window.devicePixelRatio 獲取到當(dāng)前設(shè)備的 dpr. 而在 CSS 中, 可以通過(guò) - webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio 和 -webkit-max-device-pixel-ratio 進(jìn)行媒體查詢, 對(duì)不同 dpr 的設(shè)備, 做一些樣式適配
為什么需要了解這些?一切的起源來(lái)自于 iphone4 的誕生, 當(dāng)時(shí)它使用一種新的屏幕的顯示技術(shù) Retina(視網(wǎng)膜), 它將 640x960 的分辨率壓縮到一個(gè) 3.5 英寸的顯示屏, 像素密度達(dá)到 326 像素 / 英寸(ppi). 聲稱當(dāng)一個(gè)顯示屏像素密度超過(guò) 300ppi 時(shí), 人眼就無(wú)法區(qū)分出多帶帶的像素, 顯示設(shè)備清晰度已達(dá)到人視網(wǎng)膜可分辨像素的極限.
示例機(jī)型 | iPhone6S | 某某手機(jī) |
---|---|---|
設(shè)備寬高(pp) | 375 * 667 | 375 * 667 |
屏幕密度(ppi) | 326 | --- |
CSS 像素(px) | 375 * 667 | 375 * 667 |
設(shè)備獨(dú)立像素(dip) | 750dip * 1334dip | 375dip 667dip |
設(shè)備像素比(dpr) | 2 | 1 |
盡管兩者 CSS 像素所呈現(xiàn)的物理尺寸是一致的, 但在普通屏幕下 1 個(gè) CSS 像素對(duì)應(yīng) 1 個(gè)物理像素, 而在 Retina 屏幕下, 1 個(gè) CSS 像素對(duì)應(yīng)的卻是 4 個(gè)物理像素. 靠提升單位面積屏幕的像素?cái)?shù)量, 即像素密度來(lái)提升分辨率.
iphone 常見(jiàn)如下:
(更詳細(xì)內(nèi)容請(qǐng)看 The Ultimate Guide To iPhone Resolutions)
lib-flexible重點(diǎn)來(lái)了, 在舊的布局方式困難重重, 新的屬性方法短時(shí)間不被主流瀏覽器大范圍兼容的情況下, 手淘團(tuán)隊(duì)出了 lib-flexible.
基本原理先在 < html > 元素上增加一個(gè) data-dpr 屬性, 以及一個(gè) font-size 樣式. JS 會(huì)根據(jù)不同的設(shè)備添加不同的 data-dpr 值和對(duì)應(yīng)的 font-size 的值. 開(kāi)發(fā)時(shí)候通過(guò)把設(shè)計(jì)稿做些計(jì)算轉(zhuǎn)換成 rem 單位來(lái)設(shè)置. 他們會(huì)根據(jù) html 元素的 font-size 值做相應(yīng)的計(jì)算, 從而實(shí)現(xiàn)屏幕的適配效果.
使用建議在頁(yè)面所有資源加載前執(zhí)行, 避免在渲染過(guò)程或之后再次重新計(jì)算樣式;
像字體, 某些固定尺寸的樣式可以直接使用 px;
(更詳細(xì)內(nèi)容請(qǐng)看使用 Flexible 實(shí)現(xiàn)手淘 H5 頁(yè)面的終端適配 https://www.w3cplus.com/mobil... )(還有一些常用的居中布局, 經(jīng)典布局方法和優(yōu)缺點(diǎn)可以參考我之前寫的文章頁(yè)面基礎(chǔ)布局相關(guān)知識(shí) --- 居中 & 經(jīng)典布局)
meta 標(biāo)簽這里只會(huì)列出一些常用的標(biāo)簽, 多帶帶某些瀏覽器或低版本系統(tǒng)不會(huì)列出來(lái).
限制移動(dòng)端頁(yè)面視口寬度縮放等
移動(dòng)端必備標(biāo)簽!
屬性 | 描述 |
---|---|
width | device-width: viewport 寬度 |
initial-scale | 初始縮放比例 |
maximum-scale | 最大縮放比例 |
minimum-scale | 最小縮放比例 |
user-scalable | 是否允許用戶縮放(yes/no) |
很多時(shí)候真的只是文本文字, 也會(huì)被當(dāng)作電話號(hào)碼處理
忽略識(shí)別郵箱 刪除默認(rèn)的蘋果工具欄和菜單欄 設(shè)置蘋果狀態(tài)欄的背景顏色默認(rèn)值為default(白色),可以定為black(黑色)和black-translucent(黑色半透明.)
black-translucent 狀態(tài)欄背景是黑色半透明. 如果設(shè)置為 default 或 black , 網(wǎng)頁(yè)內(nèi)容從狀態(tài)欄底部開(kāi)始. 如果設(shè)置為 black-translucent , 網(wǎng)頁(yè)內(nèi)容充滿整個(gè)屏幕, 頂部會(huì)被狀態(tài)欄遮擋.
蘋果添加到主屏后的標(biāo)題(iOS 6 新增) 蘋果是否啟用 WebApp 全屏模式 理論知識(shí) CSS 優(yōu)先級(jí)算法如何計(jì)算?元素選擇符: 1
class 選擇符: 10
id 選擇符: 100
內(nèi)聯(lián)樣式: 1000
!important 優(yōu)先級(jí)最高
如果優(yōu)先級(jí)相同, 則選擇最后出現(xiàn)的樣式;
繼承得到的樣式的優(yōu)先級(jí)最低;
嵌套選擇器優(yōu)先級(jí)是相加, 例如: #A .B = 100 + 10 = 110;
margin 有什么需要注意的特性?合并
margin 在垂直方向會(huì)合并, 其值為兩者最大值, 水平方向不合并;
如果元素內(nèi)容為空, 自身 margin 垂直方向也會(huì)合并, 其值為兩者最大值;
父元素如果沒(méi)有 padding, border 等屬性時(shí), 其子元素的 margin 上下方向會(huì)和父元素的 margin 進(jìn)行重疊;
與其他元素相交定位
位于普通文檔流中元素, 只會(huì)覆蓋顏色, 不會(huì)覆蓋文字;
relative 下, 會(huì)完全覆蓋前一個(gè)元素并影響后面元素一起移動(dòng);
absolute 下, 元素脫離了普通文檔流并對(duì)其他元素沒(méi)有影響;
對(duì)于 float 元素, 可以通過(guò)負(fù)值進(jìn)行覆蓋;
(原本想寫些例子, 但是太麻煩, 可能還得截圖標(biāo)注, 就干脆不寫了.)
為什么會(huì)出現(xiàn)浮動(dòng)和什么時(shí)候需要清除浮動(dòng)? 清除浮動(dòng)的方式?先說(shuō)說(shuō) float 的特性:
浮動(dòng)元素會(huì)脫離正常文檔流, 一直平移到碰到容器邊框或者另一個(gè)浮動(dòng)元素;
浮動(dòng)元素會(huì)根據(jù)上一個(gè)元素的類型判斷位置:
如果是浮動(dòng)元素, 則跟隨他浮動(dòng), 放置不下就擠到下一行展示;
如果是標(biāo)準(zhǔn)流元素, 則浮動(dòng)元素的相對(duì)垂直高度不變, 頂部和上一個(gè)底部對(duì)齊;
浮動(dòng)帶來(lái)的問(wèn)題:
父元素的高度無(wú)法被撐開(kāi), 影響與父元素同級(jí)的元素
與浮動(dòng)元素同級(jí)的非浮動(dòng)元素 (內(nèi)聯(lián)元素) 會(huì)跟隨其后
若非第一個(gè)元素浮動(dòng), 則該元素之前的元素也需要浮動(dòng), 否則會(huì)影響頁(yè)面顯示的結(jié)構(gòu).
綜合寫法:
.clearfix:after { content: ""; // 設(shè)置內(nèi)容為空 height: 0; // 高度為 0 line-height: 0; // 行高為 0 display: block; // 將文本轉(zhuǎn)為塊級(jí)元素 visibility: hidden; // 將元素隱藏 clear: both; // 清除浮動(dòng) } .clearfix { zoom: 1; // 為了兼容 IE; }position 跟 display,overflow,float 這些特性相互疊加后會(huì)怎么樣?
display 屬性規(guī)定元素應(yīng)該生成的框的類型;
overflow 屬性規(guī)定當(dāng)內(nèi)容溢出元素框時(shí)發(fā)生的事情.
position 屬性規(guī)定元素的定位類型;
float 屬性是一種布局方式, 定義元素在哪個(gè)方向浮動(dòng).
首先 overflow 怎么處理溢出顯示, 跟其他三者無(wú)沖突影響的;
如果 display: none 此元素不會(huì)被顯示. 否則就是規(guī)定元素應(yīng)該生成的框的類型;
如果脫離文檔流的話 position:absolute/fixed 優(yōu)先級(jí)高于浮動(dòng) float, 并且 display 只能影響子元素繼承屬性;
float 或者 absolute 定位的元素, display 只能是塊元素或表格;
元素豎向的百分比設(shè)定是相對(duì)于容器的高度嗎?當(dāng)按百分比設(shè)定一個(gè)元素的寬度時(shí), 它是相對(duì)于父容器的寬度計(jì)算的, 但是, 對(duì)于一些表示豎向距離的屬性, 例如 padding-top , padding-bottom , margin-top , margin-bottom 等, 當(dāng)按百分比設(shè)定它們時(shí), 依據(jù)的也是父容器的寬度, 而不是高度.
偽類和偽元素有哪些, 又有什么區(qū)別和作用?偽類 (Pseudo-classes) :active, :focus, :hover, :link, :visited, :first-child, :lang 等, 用于向某些選擇器添加特殊的效果.
偽元素 (Pseudo-elements) :first-letter, :first-line, :before, :after 等, 用于向某些選擇器設(shè)置特殊效果.
偽類能獲取不能被常規(guī) CSS 選擇器獲取的信息, 可以算是選擇器的一種補(bǔ)充吧, 每個(gè)選擇器可以同時(shí)使用多種偽類.
偽元素能在 DOM 樹中創(chuàng)建一些存在于文檔語(yǔ)言里的抽象元素.
對(duì) BFC 規(guī)范的理解?定義: BFC(Block formatting context)直譯為 "塊級(jí)格式化上下文". 它是一個(gè)獨(dú)立的渲染區(qū)域, 只有 Block-level box 參與, 它規(guī)定了內(nèi)部的 Block-level Box 如何布局, 并且與這個(gè)區(qū)域外部毫不相干.
w3c 規(guī)范中的 BFC 定義:
浮動(dòng)元素和絕對(duì)定位元素, 非塊級(jí)盒子的塊級(jí)容器(例如 inline-blocks, table-cells, 和 table-captions), 以及 overflow 值不為 "visiable" 的塊級(jí)盒子, 都會(huì)為他們的內(nèi)容創(chuàng)建新的 BFC(塊級(jí)格式上下文).
在 BFC 中, 盒子從頂端開(kāi)始垂直地一個(gè)接一個(gè)地排列, 兩個(gè)盒子之間的垂直的間隙是由他們的 margin 值所決定的. 在一個(gè) BFC 中, 兩個(gè)相鄰的塊級(jí)盒子的垂直外邊距會(huì)產(chǎn)生折疊.
在 BFC 中, 每一個(gè)盒子的左外邊緣 (margin-left) 會(huì)觸碰到容器的左邊緣(border-left)(對(duì)于從右到左的格式來(lái)說(shuō), 則觸碰到右邊緣).
BFC 布局規(guī)則:
內(nèi)部的 Box 會(huì)在垂直方向, 一個(gè)接一個(gè)地放置;
Box 垂直方向的距離由 margin 決定. 屬于同一個(gè) BFC 的兩個(gè)相鄰 Box 的 margin 會(huì)發(fā)生重疊;
每個(gè)元素的 margin box 的左邊, 與包含塊 border box 的左邊相接觸(對(duì)于從左往右的格式化, 否則相反). 即使存在浮動(dòng)也是如此;
BFC 的區(qū)域不會(huì)與 float box 重疊;
BFC 就是頁(yè)面上的一個(gè)隔離的獨(dú)立容器, 容器里面的子元素不會(huì)影響到外面的元素. 反之也如此;
計(jì)算 BFC 的高度時(shí), 浮動(dòng)元素也參與計(jì)算;
觸發(fā)條件:
根元素, 即 html;
float 的值不為 none(默認(rèn));
overflow 的值不為 visible(默認(rèn));
display 的值為 inline-block,table-cell,table-caption;
position 的值為 absolute 或 fixed;
(更詳細(xì)內(nèi)容請(qǐng)看前端精選文摘: BFC 神奇背后的原理 )
層疊(實(shí)在復(fù)雜, 更詳細(xì)內(nèi)容請(qǐng)看 CSS 大神張?chǎng)涡竦纳钊肜斫?CSS 中的層疊上下文和層疊順序 , 下面都是我根據(jù)他的文章簡(jiǎn)要記錄下來(lái)的)
層疊上下文(stacking context): 是 HTML 中的一個(gè)三維的概念. 如果一個(gè)元素含有層疊上下文, 我們可以理解為這個(gè)元素在 z 軸上就 "高人一等".
層疊水平(stacking level): 決定了同一個(gè)層疊上下文中元素在 z 軸上的顯示順序.
層疊順序(stacking order): 表示元素發(fā)生層疊時(shí)候有著特定的垂直顯示順序.
注意: 上面的層疊上下文和層疊水平是概念, 而這里的層疊順序是規(guī)則.
(原諒我盜圖)
普通元素的層疊水平優(yōu)先由層疊上下文決定, 某些情況下 z-index 可以影響層疊水平, 但是, 只限于定位元素以及 flex 盒子的子元素;
當(dāng)在同一個(gè)層疊上下文領(lǐng)域具有明顯的層疊水平標(biāo)示的時(shí)候, 如 z-indx, 層疊水平值大的那一個(gè)覆蓋小的那一個(gè);
當(dāng)元素的層疊水平一致, 層疊順序相同的時(shí)候, 在 DOM 流中處于后面的元素會(huì)覆蓋前面的元素;
層疊上下文的層疊水平要比普通元素高;
層疊上下文可以阻斷元素的混合模式(普通元素的層疊水平優(yōu)先由層疊上下文決定);
層疊上下文可以嵌套, 內(nèi)部層疊上下文及其所有子元素均受制于外部的層疊上下文(父元素的層級(jí)決定了子元素之間的層級(jí)比較);
每個(gè)層疊上下文和兄弟元素獨(dú)立, 也就是當(dāng)進(jìn)行層疊變化或渲染的時(shí)候, 只需要考慮后代元素;
每個(gè)層疊上下文是自成體系的, 當(dāng)元素發(fā)生層疊的時(shí)候, 整個(gè)元素被認(rèn)為是在父層疊上下文的層疊順序中;
根層疊上下文:
頁(yè)面根元素 html;
定位元素與傳統(tǒng)層疊上下文:
對(duì)于包含有 position:relative/position:absolute 的定位元素, 以及 FireFox/IE 瀏覽器 (不包括 Chrome 等 webkit 內(nèi)核瀏覽器) 下含有 position:fixed 聲明的定位元素, 當(dāng)其 z-index 值不是 auto 的時(shí)候, 會(huì)創(chuàng)建層疊上下文;
CSS3 與新時(shí)代的層疊上下文:
z-index 值不為 auto 的 flex 項(xiàng)(父元素 display:flex|inline-flex).
元素的 opacity 值不是 1.
元素的 transform 值不是 none.
元素 mix-blend-mode 值不是 normal.
元素的 filter 值不是 none.
元素的 isolation 值是 isolate.
will-change 指定的屬性值為上面任意一個(gè).
元素的 - webkit-overflow-scrolling 設(shè)為 touch.
層疊上下文之間的順序:
如果不依賴 z-index, 則 z-index:auto 可看成 z:index:0 級(jí)別;
元素一旦成為定位元素, 其 z-index 就會(huì)自動(dòng)生效就是默認(rèn)的 auto, 也就是 0 級(jí)別, 根據(jù)上面的層疊順序表, 就會(huì)覆蓋 inline 或 block 或 float 元素;
不支持 z-index 的層疊上下文元素天然 z-index:auto 級(jí)別, 也就意味著, 層疊上下文元素和定位元素是一個(gè)層疊順序的, 遵循的是 "后來(lái)居上" 準(zhǔn)則
如果依賴 z-index, 則其層疊順序由 z-index 值決定.
z-index 勝者為王;
瀏覽器是怎樣解析 CSS 選擇器的?.title {} .title h1 {} .title h1 span {}
要找到. title .h1 span 選擇器:
找到父節(jié)點(diǎn) title;
在父節(jié)點(diǎn)之下找 h1;
再找到 h1 下面的 span;
看起來(lái)順利解析完畢, 然后來(lái)看看再看看稍微復(fù)雜點(diǎn)的
.title {} .title h1 {} .title h2 {} .title h1 em {} .title h1 span {}
要找到. title .h1 span 選擇器:
找到父節(jié)點(diǎn) title;
在父節(jié)點(diǎn)之下找 h1(第三行不符合);
再找到 h1 下面的 span(第四行不符合);
在這里也能大概看得出, 如果是從左往右解析 CSS 選擇器的話, 每次發(fā)現(xiàn)不符合規(guī)則的都要進(jìn)行回溯, 不僅浪費(fèi)時(shí)間而且浪費(fèi)性能, 所以上面的說(shuō)法是我誤導(dǎo)不懂的人的, 實(shí)際上瀏覽器 CSS 選擇器的解析規(guī)則是從右往左的. 然后我們?cè)倏纯瓷厦娴慕馕鲆?guī)則.
找到子節(jié)點(diǎn) span;
在 span 的父節(jié)點(diǎn)上找 h1;
在 h1 的父節(jié)點(diǎn)上找 title;
整個(gè)解析下來(lái), 每一步都能過(guò)濾掉些不符合規(guī)則的分支情況, 直到找到根元素或滿足條件的匹配規(guī)則的選擇器就結(jié)束這個(gè)分支的遍歷.
最后建議:, 不管瀏覽器怎么解析, 我剛開(kāi)始學(xué)前端的時(shí)候就經(jīng)常看到那么一句話: 盡量避免深層嵌套 CSS, 因?yàn)閷ふ疫x擇器和計(jì)算最終樣式都會(huì)受影響的.
如果需要手動(dòng)寫動(dòng)畫, 你認(rèn)為最小時(shí)間間隔是多久, 為什么?多數(shù)顯示器默認(rèn)頻率是 60Hz, 即 1 秒刷新 60 次, 所以理論上最小間隔為 1/60*1000ms = 16.7ms.
移動(dòng)端點(diǎn)擊 300ms 延遲原因: 因?yàn)槭謾C(jī)會(huì)通過(guò) 300ms 的延遲判斷用戶是單擊還是雙擊屏幕決定執(zhí)行哪種手勢(shì)行為.
解決方案:
網(wǎng)頁(yè)頭部 meta 標(biāo)簽禁用縮放, 為了解決短暫的延遲問(wèn)題卻要完全禁止用戶手勢(shì)縮放行為, 這就過(guò)分了;
網(wǎng)頁(yè)頭部 meta 標(biāo)簽設(shè)置視口寬度為設(shè)備寬度, 優(yōu)點(diǎn)是只禁用雙擊手勢(shì)縮放功能;
指針事件, 是一個(gè)新的 web 事件系列, 相應(yīng)的規(guī)范旨在使用一個(gè)多帶帶的事件模型, 對(duì)所有輸入類型, 包括鼠標(biāo) (mouse), 觸摸 (touch), 觸控 (stylus) 等, 進(jìn)行統(tǒng)一的處理. 其中 touch-action
屬性決定 "是否觸摸操作會(huì)觸發(fā)用戶代理的默認(rèn)行為. 這包括但不限于雙指縮放等行為". 但瀏覽器兼容是個(gè)問(wèn)題;
解決庫(kù):
指針事件庫(kù), 就是上面第三個(gè)方案的 js 兼容庫(kù);
FastClick.js , 實(shí)現(xiàn)原理是在檢測(cè)到 touchend 事件的時(shí)候, 會(huì)通過(guò) DOM 自定義事件立即觸發(fā)模擬一個(gè) click 事件, 并把瀏覽器在 300ms 之后的 click 事件阻止掉. 需要注意的是至 2015 年之后的瀏覽器大多數(shù)都已經(jīng)取消了 300ms 的延遲, 再引入的話不僅沒(méi)用還可能引起應(yīng)用 bug;
tap 事件代替 click, 如果你引用的庫(kù)或框架有提供的話;
(我發(fā)現(xiàn)有個(gè)文章深入源碼分析的挺好的, 雖然我沒(méi)細(xì)看, 有興趣可以看一下[[讀 fastclick 源碼有感] 徹底解決 tap"點(diǎn)透", 提升移動(dòng)端點(diǎn)擊響應(yīng)速度](https://github.com/ftlabs/fas... )
點(diǎn)擊穿透問(wèn)題原因: 移動(dòng)端一次點(diǎn)擊會(huì)順序觸發(fā) touchstart -> touchmove -> touchend -> tap(如果有) -> click, 并且 click 有 300ms 的滯后性.
舉例: 有一對(duì)父子元素, 分別綁定讓自身消失的事件在父元素的 click 和子元素的 touchstart 上, 當(dāng)點(diǎn)擊子元素會(huì)讓子元素自身消失, 過(guò)了 300ms 之后才會(huì)觸發(fā)到 click 事件, 但是子元素已經(jīng)消失了, click 事件會(huì)被順遞派發(fā)到下層的父元素讓其也消失.
解決方案:
盡量都使用 touch 事件來(lái)替換 click 事件. 例如用 touchend 事件(推薦);
fastclick;
preventDefault 阻止;
延遲一定的時(shí)間 (300ms+) 來(lái)處理事件 (不推薦);
以上一般都能解決, 實(shí)在不行就換成 click 事件;
滾動(dòng)穿透問(wèn)題舉例: 當(dāng)頁(yè)面彈出遮罩的時(shí)候依然可以讓頁(yè)面滾動(dòng).
解決方案:
touchmove 事件監(jiān)聽(tīng)加 e.preventDefault()
如果遮罩本身也有滾動(dòng)條也會(huì)被禁止;
body/html 添加 overflow:hidden,height: 100%;
部分機(jī)器 / 瀏覽器不行;
頁(yè)面的背景還是能夠有滾的動(dòng)的效果;
滾動(dòng)位置消失, 需要 js 計(jì)算修復(fù);
body.modal-open {position: fixed; width: 100%;} ------------------------------------------------------------ var ModalHelper = (function(bodyCls) { var scrollTop; // 在閉包中定義一個(gè)用來(lái)保存滾動(dòng)位置的變量 return { afterOpen: function() { // 彈出之后記錄保存滾動(dòng)位置, 并且給 body 添加. modal-open scrollTop = document.scrollingElement.scrollTop; document.body.classList.add(bodyCls); document.body.style.top = -scrollTop + "px"; }, beforeClose: function() { // 關(guān)閉時(shí)將. modal-open 移除并還原之前保存滾動(dòng)位置 document.body.classList.remove(bodyCls); document.scrollingElement.scrollTop = scrollTop; }, }; })("modal-open");
(從網(wǎng)上看到的方法關(guān)于移動(dòng)端開(kāi)發(fā)中遇到的坑)
通用樣式這里只會(huì)總結(jié)部分特殊問(wèn)題, 太常見(jiàn)的就不提, IE 的不提, 低版本瀏覽器問(wèn)題不提(主要我也不懂).
改變輸入框 placeholder 的顏色值::-webkit-input-placeholder { /* WebKit browsers */ color: #999; } :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #999; } ::-moz-placeholder { /* Mozilla Firefox 19+ */ color: #999; } :-ms-input-placeholder { /* Internet Explorer 10+ */ color: #999; } input:focus::-webkit-input-placeholder { color: #999; }省略文本
單行文本
p{ overflow: hidden;/*超出部分隱藏*/ text-overflow:ellipsis;/* 超出部分顯示省略號(hào) */ white-space: nowrap;/*規(guī)定段落中的文本不進(jìn)行換行 */ width: 250px;/*需要配合寬度來(lái)使用*/ border: 1px solid red; font-size: 30px; }
多行文本
p{ display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; width: 250px; border: 1px solid red; font-size: 30px; }旋轉(zhuǎn)樣式
// 豎屏?xí)r樣式 @media all and (orientation:portrait){} // 橫屏?xí)r樣式 @media all and (orientation:landscape){}transition 閃屏
//設(shè)置內(nèi)嵌的元素在 3D 空間如何呈現(xiàn): 保留 3D -webkit-transform-style: preserve-3d; //設(shè)置進(jìn)行轉(zhuǎn)換的元素的背面在面對(duì)用戶時(shí)是否可見(jiàn): 隱藏 -webkit-backface-visibility:hidden; //定義 3D 元素距視圖的距離,以像素計(jì) -webkit-perspective: 1000;純 CSS 創(chuàng)建三角形?
div { width: 0; height: 0; border-top: 40px solid transparent; border-left: 40px solid transparent; border-right: 40px solid transparent; border-bottom: 40px solid #ff0000; }input[type=number]的問(wèn)題
1, maxlength 屬性不會(huì)提供任何反饋.
用 js 解決
2, form 提交會(huì)默認(rèn)取整數(shù).
step 屬性規(guī)定 < input > 元素的合法數(shù)字間隔, 也是通過(guò)自帶箭頭增減的數(shù)字, 默認(rèn)為 1
通過(guò) transform 進(jìn)行 skew 變形, rotate 旋轉(zhuǎn)會(huì)造成出現(xiàn)鋸齒現(xiàn)象Element { -webkit-transform: rotate(-4deg) skew(10deg) translateZ(0); transform: rotate(-4deg) skew(10deg) translateZ(0); outline: 1px solid rgba(255,255,255,0); }打電話
打電話給: 10086發(fā)短信, winphone 系統(tǒng)無(wú)效
發(fā)短信給: 10086寫郵件
第一個(gè)功能以 "?" 開(kāi)頭, 后面的以 "&" 開(kāi)頭
mailto: 普通郵件
cc: 收件地址后添加抄送地址(Android 存在兼容問(wèn)題)
bcc: 抄送地址后添加密件抄送地址(Android 存在兼容問(wèn)題)
subject: 包含主題
body: 包含內(nèi)容,
如包含文本, 使用 給文本換行
如包含 http(s):// 等的文本自動(dòng)轉(zhuǎn)化為鏈接
如內(nèi)容包含圖片(PC 不支持)
包含多個(gè)收件人, 抄送, 密件抄送人, 用分號(hào) (;) 隔開(kāi)多個(gè)郵件人的地址
點(diǎn)擊我發(fā)郵件系統(tǒng)兼容問(wèn)題
安卓蘋果常見(jiàn)的問(wèn)題, 還有些基于系統(tǒng)版本, 瀏覽器版本的不說(shuō).
某些 Android 手機(jī)圓角失效Element { background-clip: padding-box; }android 去掉語(yǔ)音輸入按鈕
input::-webkit-input-speech-button {display: none}ios 和 android 下觸摸元素時(shí)出現(xiàn)半透明灰色遮罩
Element { -webkit-tap-highlight-color: rgba(255,255,255,0); }
有些機(jī)型去除不了, 不使用 a 或者 input 標(biāo)簽, 直接用 div 標(biāo)簽
ios 設(shè)置 input 按鈕樣式會(huì)被默認(rèn)樣式覆蓋input, textarea { border: 0; -webkit-appearance: none; }iphone 及 ipad 下輸入框默認(rèn)內(nèi)陰影
Element { -webkit-appearance: none; }Retina 屏的 1px 邊框
Element { border-width: thin; }關(guān)于 iOS 系統(tǒng)中, 中文輸入法輸入英文時(shí), 字母之間可能會(huì)出現(xiàn)一個(gè)六分之一空格
this.value = this.value.replace(/u2006/g, "");IOS 中 input 鍵盤事件 keyup,keydown,keypress 支持不是很好
html5 的 oninput 事件代替
iOS 某些時(shí)候會(huì)覺(jué)得滾動(dòng)很卡Element { -webkit-overflow-scrolling: touch; }
auto: 使用普通滾動(dòng), 當(dāng)手指從觸摸屏上移開(kāi), 滾動(dòng)會(huì)立即停止.
touch: 使用具有回彈效果的滾動(dòng), 當(dāng)手指從觸摸屏上移開(kāi), 內(nèi)容會(huì)繼續(xù)保持一段時(shí)間的滾動(dòng)效果. 繼續(xù)滾動(dòng)的速度和持續(xù)的時(shí)間和滾動(dòng)手勢(shì)的強(qiáng)烈程度成正比. 同時(shí)也會(huì)創(chuàng)建一個(gè)新的堆棧上下文.
啟動(dòng)了硬件加速的特性, 所以滑動(dòng)起來(lái)會(huì)非常流暢; 不過(guò)會(huì)影響性能
解決 IOS 鍵盤字母輸入默認(rèn)首字母大寫 禁止長(zhǎng)按鏈接與圖片彈出菜單a, img { -webkit-touch-callout: none; }手機(jī)拍照和上傳圖片
IOS 有拍照, 錄像, 選取本地圖片功能, 部分 Android 只有選擇本地圖片功能. Winphone 不支持
輸入框被鍵盤擋住問(wèn)題
if (/Android/.test(navigator.appVersion)) { window.addEventListener("resize", function() { if (document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "TEXTAREA") { document.activeElement.scrollIntoView(); } }); }
可以解決絕大數(shù)安卓機(jī)上面的問(wèn)題
播放視頻不全屏ios7 + 支持自動(dòng)播放
支持 Airplay 的設(shè)備 (如: 音箱, Apple TV) 播放: x-webkit-airplay="true"
播放視頻不全屏: webkit-playsinline="true"
移動(dòng)端 HTML5 audio autoplay 失效問(wèn)題蘋果系統(tǒng)和安卓系統(tǒng)通常都會(huì)禁止自動(dòng)播放和使用 JS 的觸發(fā)播放, 必須由用戶來(lái)觸發(fā)才可以播放.
audio 元素的 autoplay 屬性在 IOS 及 Android 上無(wú)法使用, 在 PC 端正常
audio 元素沒(méi)有設(shè)置 controls 時(shí), 在 IOS 及 Android 會(huì)占據(jù)空間大小, 而在 PC 端 Chrome 是不會(huì)占據(jù)任何空間
解決方法思路: 先通過(guò)用戶 touchstart 觸碰, 觸發(fā)播放并暫停(音頻開(kāi)始加載, 后面用 JS 再操作就沒(méi)問(wèn)題了).
document.addEventListener("touchstart", function() { document.getElementsByTagName("audio")[0].play(); document.getElementsByTagName("audio")[0].pause(); });
微信下兼容處理
document.addEventListener( "WeixinJSBridgeReady", function() { music.play(); }, false );
ios10 + 以上, 盡管開(kāi)發(fā)者設(shè)置了 user-scalable=no,Safari 還是允許用戶通過(guò)手勢(shì)來(lái)縮放
檢測(cè) touch 相關(guān)事件來(lái)阻止事件的觸發(fā)
window.onload = function () { // 同時(shí)按下兩個(gè)手指 document.addEventListener("touchstart", function (event) { if (event.touches.length > 1) { event.preventDefault(); } }); var lastTouchEnd = 0; // 特別注意 300ms 時(shí)差的設(shè)置 document.addEventListener("touchend", function (event) { var now = new Date().getTime(); if (now - lastTouchEnd <= 300) { event.preventDefault(); } lastTouchEnd = now; }); };定位的坑
fixed 定位
ios 下 fixed 元素容易定位出錯(cuò), 軟鍵盤彈出時(shí), 影響 fixed 元素定位
android 下 fixed 表現(xiàn)要比 iOS 更好, 軟鍵盤彈出時(shí), 不會(huì)影響 fixed 元素定位
ios4 下不支持 position:fixed
解決方案: 使用 Iscroll , 如:
position 定位
Android 下彈出軟鍵盤彈出時(shí), 影響 absolute 元素定位
var ua = navigator.userAgent.indexOf("Android"); if (ua > -1) { $(".ipt") .on("focus", function() { $(".css").css({ visibility: "hidden" }); }) .on("blur", function() { $(".css").css({ visibility: "visible" }); }); }各種黑科技
使用的都是些特殊屬性, 兼容性是個(gè)比較大的問(wèn)題.
Chrome 設(shè)置小于 12px 的字體大小?新版本谷歌好像取消支持了
-webkit-text-size-adjust: none;
縮小尺寸
-webkit-transform: scale(0.5);
解決縮放后 margin-left 的位移問(wèn)題
-webkit-transform-origin-x: 0;
解決縮放后 margin-left 的位移問(wèn)題
-webkit-transform-origin-x: 0;
注意: 放在 body 上會(huì)導(dǎo)致頁(yè)面縮放失效
長(zhǎng)時(shí)間按住頁(yè)面出現(xiàn)閃退element { -webkit-touch-callout: none; }旋轉(zhuǎn)屏幕時(shí), 字體大小調(diào)整的問(wèn)題
body, div, fieldset, form, h1, h2, h3, h4, h5, h6, html, p { webkit-text-size-adjust: 100%; }去除 input 默認(rèn)樣式
input[type=number] { -moz-appearance: textfield; } input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }禁用 radio 和 checkbox 默認(rèn)樣式,::-ms-check 修改表單復(fù)選框或單選框默認(rèn)圖標(biāo), 設(shè)置隱藏并使用背景圖片來(lái)修飾
input[type=checkbox]::-ms-check, input[type=radio]::-ms-check { display: none; }禁用 pc 端表單輸入框默認(rèn)清除按鈕,::-ms-clear 修改清除按鈕, 設(shè)置隱藏并使用背景圖片來(lái)修飾
input[type=number]::-ms-clear, input[type=tel]::-ms-clear, input[type=text]::-ms-clear { display: none; }select 下拉選擇設(shè)置右對(duì)齊
select option { direction: rtl; }出現(xiàn)滾動(dòng)條時(shí)頁(yè)面跳動(dòng)?
原因是滾動(dòng)條占據(jù)一定的寬度擠壓了頁(yè)面布局導(dǎo)致的.
Element { margin-left: calc(100vw - 100%); }禁止復(fù)制, 選中文本
Element { -webkit-user-select: none; -moz-user-select: none; -khtml-user-select: none; user-select: none; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/106343.html
摘要:前言本來(lái)是打算寫寫怎么使用進(jìn)行移動(dòng)端的布局的然后前面還加些像素基本知識(shí)鋪墊后面又加了些屬性概念最后還來(lái)些常見(jiàn)布局問(wèn)題和系統(tǒng)樣式果然排版也是門高深學(xué)問(wèn)這里有些自己寫的有些看完之后總結(jié)出來(lái)的還有些別人那里搬來(lái)的順帶會(huì)送上飛機(jī)票告訴你們來(lái)源在哪 前言 本來(lái)是打算寫寫怎么使用 lib-flexible 進(jìn)行移動(dòng)端的布局的, 然后前面還加些像素基本知識(shí)鋪墊, 后面又加了些 CSS 屬性概念, 最...
摘要:為此決定自研一個(gè)富文本編輯器。例如當(dāng)要轉(zhuǎn)化的對(duì)象有環(huán)存在時(shí)子節(jié)點(diǎn)屬性賦值了父節(jié)點(diǎn)的引用,為了關(guān)于函數(shù)式編程的思考作者李英杰,美團(tuán)金融前端團(tuán)隊(duì)成員。只有正確使用作用域,才能使用優(yōu)秀的設(shè)計(jì)模式,幫助你規(guī)避副作用。 JavaScript 專題之惰性函數(shù) JavaScript 專題系列第十五篇,講解惰性函數(shù) 需求 我們現(xiàn)在需要寫一個(gè) foo 函數(shù),這個(gè)函數(shù)返回首次調(diào)用時(shí)的 Date 對(duì)象,注意...
摘要:實(shí)戰(zhàn)之微信錢包騰訊服務(wù)界面網(wǎng)格布局是讓開(kāi)發(fā)人員設(shè)計(jì)一個(gè)網(wǎng)格并將內(nèi)容放在這些網(wǎng)格內(nèi)。對(duì)于移動(dòng)端適配,不同的公司不同的團(tuán)隊(duì)有不同的解決方案。柵格系統(tǒng)用于處理頁(yè)面多終端適配的問(wèn)題。 grid實(shí)戰(zhàn)之微信錢包 騰訊服務(wù)界面 CSS3網(wǎng)格布局是讓開(kāi)發(fā)人員設(shè)計(jì)一個(gè)網(wǎng)格并將內(nèi)容放在這些網(wǎng)格內(nèi)。而不是使用浮動(dòng)制作一個(gè)網(wǎng)格,實(shí)際上是你將一個(gè)元素聲明為一個(gè)網(wǎng)格容器,并把元素內(nèi)容置于網(wǎng)格中。 移動(dòng)端頁(yè)面適配—...
閱讀 1624·2021-11-22 13:53
閱讀 2856·2021-11-15 18:10
閱讀 2762·2021-09-23 11:21
閱讀 2506·2019-08-30 15:55
閱讀 482·2019-08-30 13:02
閱讀 757·2019-08-29 17:22
閱讀 1667·2019-08-29 13:56
閱讀 3458·2019-08-29 11:31