ios
滑動不流暢
ios
- 上下滑動頁面會産生卡頓,手指離開頁面,頁面立即停止運動。整體表現就是滑動不流暢,沒有滑動慣性。
- 原來在
以及之後的版本,滑動有定義有兩個值iOS 5.0
和auto
,預設值為touch
。auto
-webkit-overflow-scrolling: touch; /* 當手指從觸摸屏上移開,會保持一段時間的滾動 */ -webkit-overflow-scrolling: auto; /* 當手指從觸摸屏上移開,滾動會立即停止 */
-
在滾動容器上增加滾動 touch 方法
.wrapper { -webkit-overflow-scrolling: touch; }
-
設定 overflow
設定外部
為overflow
,設定内容元素hidden
overflow
。内部元素超出 body 即産生滾動,超出的部分 body 隐藏。auto
body { overflow-y: hidden; } .wrapper { overflow-y: auto; }
頁面放大或縮小不确定性行為
- 輕按兩下或者雙指張開手指頁面元素,頁面會放大或縮小。
- 移動端正常寫法
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- 是以我們可以設定
、maximum-scale
與minimum-scale
用來避免這個問題user-scalable=no
<meta name=viewport content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no">
click 點選事件延時與穿透
- 監聽元素
事件,點選元素觸發時間延遲約click
300ms
- 點選蒙層,蒙層消失後,下層元素點選觸發。
-
中的 safari,為了實作輕按兩下縮放操作,在單擊iOS
之後,如果未進行第二次點選,則執行300ms
單擊操作。也就是說來判斷使用者行為是否為輕按兩下産生的。但是,在click
中,無論是否需要輕按兩下縮放這種行為,App
單擊都會産生click
延遲。300ms
-
使用
替換 clicktouchstart
el.addEventListener("touchstart", () => { console.log("ok"); }, false);
- 在
中使用`vue
<button @touchstart="handleTouchstart()">點選</button>
-
庫fastclick
import FastClick from 'fastclick'; FastClick.attach(document.body, options);
iPhone X
系列安全區域适配問題
iPhone X
- 頭部劉海兩側區域或者底部區域,出現劉海遮擋文字,或者呈現黑底或白底空白區域。
-
設定
viewport-fit
cover
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
-
變量safe area inset
/* 适配 iPhone X 頂部填充*/ @supports (top: env(safe-area-inset-top)){ body, .header{ padding-top: constant(safe-area-inset-top, 40px); padding-top: env(safe-area-inset-top, 40px); padding-top: var(safe-area-inset-top, 40px); } } /* 判斷iPhoneX 将 footer 的 padding-bottom 填充到最底部 */ @supports (bottom: env(safe-area-inset-bottom)){ body, .footer{ padding-bottom: constant(safe-area-inset-bottom, 20px); padding-bottom: env(safe-area-inset-bottom, 20px); padding-top: var(safe-area-inset-bottom, 20px); } }
-
:安全區域距離左邊邊界距離safe-area-inset-left
-
:安全區域距離右邊邊界距離safe-area-inset-right
-
:安全區域距離頂部邊界距離safe-area-inset-top
-
:安全區域距離底部邊界距離safe-area-inset-bottom
safe-area-inset-right,
safe-area-inset-bottom,
safe-area-inset-left safe-area-inset-*,
top由四個定義了視口邊緣内矩形的
right,
bottom,
left和
iPhoneX` 螢幕),在使用者代理設定的四個值形成的矩形内,所有内容均可見。的環境變量組成,這樣可以安全地放入内容,而不會有被非矩形的顯示切斷的風險。對于矩形視口,例如普通的筆記本電腦顯示器,其值等于零。對于非矩形顯示器(如圓形表盤,
-
H5
調試相關方案政策
H5
-
控制台插件vconsole
import Vconsole from 'vconsole' new Vconsole()
-
手機端調試eruda
- 隻要在我們的
檔案中寫入下面這些代碼,在手機上,也能想浏覽器控制台一樣進行檢視。`html
<script src="//cdn.jsdelivr.net/npm/eruda"></script>
<script>
eruda.init();
</script>
H5
頁面播放視訊
H5
-
頁面播放視訊,不全屏播放,在video标簽添加H5
playsinline
設定為true就行x5-playsinline
<video id="my-video" class="video-js" controls preload="auto" data-setup=" {} " playsinline="true" x5-playsinline="true"> </video>
橫屏适配
- 很多視口我們要對橫屏和豎屏顯示不同的布局,是以我們需要檢測在不同的場景下給定不同的樣式:
- JavaScript檢測橫屏
window.addEventListener('resize',() =>{ if(window.orientation === 180 || window.orientation === 0) { //正常方向或螢幕旋轉180度 console.log('豎屏') } if(window.orientation === 80 || window.orientation === -90) { //螢幕順時鐘旋轉90度或螢幕逆時針旋轉90度 console.log('橫屏') } })
CSS檢測橫屏
@media screen and (orientation:portrait){ /*豎屏...*/ } @media screen and (orientation:landscape){ /*橫屏...*/ }
移動端解決 0.5px
方案
0.5px
- 裝置像素比:dpr=window.devicePixelRatio,也就是裝置的實體像素與邏輯像素的比值
- 0.5px 方案
/*這是css方式*/ .border { border: 1px solid #999 } @media screen and (-webkit-min-device-pixel-ratio: 2) { .border { border: 0.5px solid #999 } } /*ios dpr=2和dpr=3情況下border相差無幾,下面代碼可以省略*/ @media screen and (-webkit-min-device-pixel-ratio: 3) { .border { border: 0.333333px solid #999 } }
-
viewport + rem
- 同時通過設定對應
的viewport
基準值,這種方式就可以像以前一樣輕松愉快的寫1px了。rem
時,設定devicePixelRatio=2
:meta
實作<meta name="viewport" content="width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
<!DOCTYPE html> <html lang="en"> <head> <title>移動端1px問題</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <meta name="viewport" id="WebViewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <style> html { font-size: 11px; } body { padding: 1rem; } * { padding: 0; margin: 0; } .item { padding: 1rem; border-bottom: 1px solid gray; font-size: 1.2rem; } </style> <script> var viewport = document.querySelector("meta[name=viewport]"); var dpr = window.devicePixelRatio || 1; var scale = 1 / dpr; //下面是根據裝置dpr設定viewport viewport.setAttribute( "content", + "width=device-width," + "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no" ); var docEl = document.documentElement; var fontsize = 10 * (docEl.clientWidth / 320) + "px"; docEl.style.fontSize = fontsize; </script> </head> <body> <div class="item">border-bottom: 1px solid gray;</div> <div class="item">border-bottom: 1px solid gray;</div> </body> </html>
移動端适配方案
- rem适配
适配的本質是布局等比例的縮放,通過動态設定rem
html
來改變font-size
的大小。rem
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
- 引入flexible
- flexible
方案是阿裡早期開源的一個移動端适配解決方案,引用
rem`來布局。後,我們在頁面上統一使用
(function(win, lib) { var doc = win.document; var docEl = doc.documentElement; var metaEl = doc.querySelector('meta[name="viewport"]'); var flexibleEl = doc.querySelector('meta[name="flexible"]'); var dpr = 0; var scale = 0; var tid; var flexible = lib.flexible || (lib.flexible = {}); if (metaEl) { console.warn('将根據已有的meta标簽來設定縮放比例'); var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/); if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); } } else if (flexibleEl) { var content = flexibleEl.getAttribute('content'); if (content) { var initialDpr = content.match(/initial\-dpr=([\d\.]+)/); var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/); if (initialDpr) { dpr = parseFloat(initialDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } if (maximumDpr) { dpr = parseFloat(maximumDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } } } if (!dpr && !scale) { var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio; if (isIPhone) { // iOS下,對于2和3的屏,用2倍的方案,其餘的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其他裝置下,仍舊使用1倍的方案 dpr = 1; } scale = 1 / dpr; } docEl.setAttribute('data-dpr', dpr); if (!metaEl) { metaEl = doc.createElement('meta'); metaEl.setAttribute('name', 'viewport'); metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(metaEl); } else { var wrap = doc.createElement('div'); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); } } function refreshRem(){ var width = docEl.getBoundingClientRect().width; if (width / dpr > 540) { width = 540 * dpr; } var rem = width / 10; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; } win.addEventListener('resize', function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false); win.addEventListener('pageshow', function(e) { if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); if (doc.readyState === 'complete') { doc.body.style.fontSize = 12 * dpr + 'px'; } else { doc.addEventListener('DOMContentLoaded', function(e) { doc.body.style.fontSize = 12 * dpr + 'px'; }, false); } refreshRem(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; flexible.rem2px = function(d) { var val = parseFloat(d) * this.rem; if (typeof d === 'string' && d.match(/rem$/)) { val += 'px'; } return val; } flexible.px2rem = function(d) { var val = parseFloat(d) / this.rem; if (typeof d === 'string' && d.match(/px$/)) { val += 'rem'; } return val; } })(window, window['lib'] || (window['lib'] = {}));
- 使用vw,vh布局
-
方案即将視覺視口寬度vh、vw
和視覺視口高度window.innerWidth
等分為 100 份。window.innerHeight
- 如果視覺視口為
,那麼375px
,這時1vw=3.75px
給定一個元素的寬為UI
(裝置獨立像素),我們隻需要将它設定為75px
75/3.75=20vw
- 這裡的比例關系我們也不用自己換算,我們可以使用
PostCSS
插件幫我們完成這個過程。寫代碼時,我們隻需要根據postcss-px-to-viewport
給的設計圖寫UI
機關即可。px
module.exports = { plugins: [ require('autoprefixer'), require('postcss-import'), require('postcss-url'), require('postcss-preset-env'), require('postcss-aspect-ratio-mini'), require('postcss-write-svg'), require('postcss-px-to-viewport')({ viewportWidth: 750, viewportHeight: 1334, unitPrecision: 3, viewportUnit: 'vw', selectorBlackList: [ '.ignore', '.hairlines', '.footer' ], minPixelValue: 1, mediaQuery: true }), require('cssnano') ] }
- flexible
快速生成HTML代碼結構
#page>div.logo+ul#navigation>li*5>a{Item $}
可以轉換為
<div id="page">
<div class="logo"></div>
<ul id="navigation">
<li><a href="">Item 1</a></li>
<li><a href="">Item 2</a></li>
<li><a href="">Item 3</a></li>
<li><a href="">Item 4</a></li>
<li><a href="">Item 5</a></li>
</ul>
</div>
-
運算符将元素互相嵌套>
div>ul>li 生成 <div> <ul> <li></li> </ul> </div>
-
運算符将元素彼此放置在同一水準上:+
div+p+bq 生成 <div></div> <p></p> <blockquote></blockquote>
- 使用括号将複雜縮寫的子樹分組
div>(header>ul>li*2>a)+footer>p 生成 <div> <header> <ul> <li><a href=""></a></li> <li><a href=""></a></li> </ul> </header> <footer> <p></p> </footer> </div>