最近一直在做移動端的頁面,發現很多的坑,這里做一下總結,填填坑……
css常見的問題(一)
一、iOS鍵盤首字母自動大寫
IOS的機子,默認英文輸入法狀態下,首字母是自動大寫的,有時候挺煩人的。
在iOS中,默認情況下鍵盤是開啟首字母大寫的功能的,如果業務不想出現首字母大寫,可以這樣:
<input type="text" autocapitalize="off" />
二、iOS輸入框默認內陰影和樣式問題
在iOS上,輸入框默認有內部陰影,但無法使用 box-shadow 來清除,如果不需要陰影,可以這樣關閉,不過加了上面的屬性后,iOS下默認還是帶有圓角的,不過可以使用 border-radius屬性修改:
input, textarea { border: 0; -webkit-appearance: none; }
三、andriod輸入框type = "number"存在樣式問題
去除input[type=number]的默認樣式
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; }
四、輸入框光標不居中問題
通常,移動端如果我們不設置line-height值時,大部分機器輸入框的光標是可以居中的,但是如果我們用line-height:$height值,卻導致光標不居中問題
遇到這個問題,我們只能用line-height:$height\9來處理居中問題,這里就不能用line-height:$height,示例代碼:
height:40px; line-height:40px\9; font-size:16px;
五、輸入框前置用text-indent縮進問題
css中text-indent縮進,但是在部分andriod機中,光標是輸入框先獲得光標依然在最左邊,然后輸入文字才到縮進的值,這樣很不好,建議通過padding-left設置縮進,完美解決。
六、a標簽默認激活高亮框問題
在做移動端頁面時,會發現所有a標簽在觸發點擊時或者所有設置了偽類 :active 的元素,默認都會在激活狀態時,顯示高亮框,如果不想要這個高亮,那么你可以通過css以下方法來禁止:
.xxx { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
這個設置,在大部分機子上都是起效果的。但是,移動端三星自帶瀏覽器,點擊頁面任意a標簽時,設置-webkit-tap-highlight-color:rgba(0,0,0,0)還是會有陰影底色,這應該是瀏覽器強制加上去的,通過代碼設置也無法覆蓋。
有一種妥協的方法是把頁面非真實跳轉鏈接的a標簽換成其它標簽,可以解決這個問題。
七、Android 2.3 自帶瀏覽器不支持border-radius 中 %
建議大家寫在使用border-radius寫圓角時,還是不要border-radius:50%實現圓,建議用具體的數值。
八、border邊框1像素問題
移動端 當設置 通用viewport 后。代碼中的 1px 單位的邊框實際在高清屏( @2x )pixel-ratio:2上顯示的是2像素,pc ( 非高清屏幕 ) 上顯示的正常的1px。
border:1px solid #000
可能看到這里,大家又有疑問了,干嘛我們不把border-width:0.5px呢,可是早的瀏覽器不支持,到了ios8.0才支持這個。
現在通常來說有兩種解決方案:1.通過border-image實現(但缺點是不能實現四邊邊框,而且加載浪費資源) 2.通過scale進行縮放
1.border-image 實現演示(掃碼地址):
2.通過scale進行縮放
①單邊1像素邊框處理方法通過偽類畫出邊框,然后通過scale將其縮放,最后處理@1.5x(安卓機器) @2.0x(ios機器) @3.0x(注意是 1080p)的縮放比例
%border-btm-1pt{ content: ''; height: 0px; display: block; border-bottom:1px solid #ddd; position: absolute; left:0; right:0; bottom:0; } .some_div{ position:relative; // 因為偽類用的absolute 所以需要添加 relative &:after{ @extend %border-btm-1pt border-color:#f09; // 在這里自定義邊框顏色。 } } //適配早期的andriod機器 1/1.5 = 0.666 @media only screen and (-webkit-min-device-pixel-ratio: 1.5) { .some_div{ -webkit-transform: scaleY(0.666) } } //高清屏( @2x ) iphone這種 1/2 = 0.5 @media only screen and (-webkit-min-device-pixel-ratio: 2) { .some_div{ -webkit-transform: scaleY(0.5) } } //1080機子@3x @media only screen and (-webkit-min-device-pixel-ratio: 3) { .some_div{ -webkit-transform: scaleY(0.333) } }
案例:
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),(min-resolution: 120dpi),(-ms-high-contrast: active),(-ms-high-contrast: none) { .jd_space:after{ -webkit-transform:scaleY(0.5); -webkit-transform-origin: 50% 100% } .jd_space:before{ -webkit-transform: scaleY(0.5); -webkit-transform-origin: 50% 0% } .jd_brand{ -webkit-transform: scaleX(0.5); -webkit-transform-origin: 0% 0% } .jd_brand{ -webkit-transform: scaleX(0.5); -webkit-transform-origin: 0% 0% } .jd_madden{ -webkit-transform: scale(0.5); -webkit-transform-origin: 0% 0%; bottom: -100%; right: -100% } } @media only screen and (-webkit-min-device-pixel-ratio: 3) { .jd_space:before{ -webkit-transform: scaleY(0.333) } .jd_madden{ -webkit-transform: scale(0.333); -webkit-transform-origin: 0% 0%; bottom: -200%; right: -200% } } @media only screen and (-webkit-device-pixel-ratio: 1.5) { .jd_space:before{ -webkit-transform: scaleY(0.666) } .jd_madden .jd_item:before{ -webkit-transform: scale(0.666); bottom: -50%; right: -50% } }
②處理四邊邊框1px問題,兩種思路:1.子邊框兩邊通過偽類,父邊框兩邊通過偽類 2.一個偽類,畫出四邊邊框,然后通過width:200%;height:200%(這里主要說的是@2.0x機器,由於@1.5 @3比例無法算整會導致不夠精確,不予討論);即把內容縮放兩倍,進行縮放scale ,處理。
這里舉例第二種情況(但是這里要注意的是,如果容器里面有a鏈接,就會導致設置的偽類遮住元素,無法點擊,所以容器里面的內容也要設置絕對定位):
<style type="text/css"> h3{text-align:center} div.border_scale{ margin:100px auto; width:600px; height:150px; position:relative; } div.border_scale:before{ display:block; position:absolute; content:"\20"; width:200%; height:200%; border:1px solid #000; -webkit-transform-origin:0 0; transform-origin:0 0; -webkit-transform:scale(0.5); transform:scale(0.5); top:-1px; left:-1px; } div.border_scale a{ display:block; width:100%; height:100%; text-align:center; } </style>
<h3>border的1像素框 scale</h3> <div class="border_scale"> <a href="http://www.baidu.com">百度</a> </div>
sass庫 1像素邊框:
%border-1pt{ content: '\20'; display: block; position: absolute; top:0; bottom:0; left:0; right:0; pointer-events:none; } @media only screen and (-webkit-min-device-pixel-ratio:1.5),(min-resolution:120dpi),(-ms-high-contrast:active),(-ms-high-contrast:none){ %border-1pt{ -webkit-transform:scale(0.5); -webkit-transform-origin:0% 0%; bottom:-100%; right:-100%; } } @media only screen and (-webkit-min-device-pixel-ratio:3){ %border-1pt{ -webkit-transform:scale(0.333); -webkit-transform-origin:0% 0%; bottom:-200%; right:-200%; } } @media only screen and (-webkit-device-pixel-ratio : 1.5){ %border-1pt{ -webkit-transform:scale(0.666); bottom:-50%; right:-50%; } } div.border_test{ margin:20px; height:200px; position: relative; background: orange } div.border_test:before{ @extend %border-1pt; border:1px solid #fff; }
九、通過transform進行skew變形,rotate旋轉會造成出現鋸齒現象
在制作H5頁面我們難免會對一些元素進行旋轉、變形,可是這樣卻惡來許多麻煩,出現鋸齒他媽的咋辦,還不如直接圖片,對吧。
我們可以通過這樣直接解決煩惱:我發現呢微信更新到6.2.4之后對旋轉鋸齒有些修復
-webkit-transform: rotate(-4deg) skew(10deg) translateZ(0); transform: rotate(-4deg) skew(10deg) translateZ(0); outline: 1px solid rgba(255,255,255,0)
十、h5頁面中內容滾動滾動條問題
在我們做h5頁面時,經常遇到要在容器內容里面做滾動調的問題,但是,當我們用那些滾動條時,發現,在andriod里面實在是太丑陋了,通常還會出問題,產品MM也接受不了,所以這里給大家提供一個解決方案:
.scroll::-webkit-scrollbar{width:5px; height:5px;} .scroll::-webkit-scrollbar-button{width:0;height:0;} .scroll::-webkit-scrollbar-corner{display:block; } .scroll::-webkit-scrollbar-thumb{background-clip:padding-box;background-color:rgba(0,0,0,.2);border-radius:8px;}//還可以設置滾動條的顏色 .scroll::-webkit-scrollbar-thumb:hover{background-clip:padding-box;background-color:rgba(0,0,0,.5);border-radius:8px;}
讓我們的滾動條變成這樣,從此媽媽再也不用擔心滾動條問題了,上圖:
十一、CSS3 timing-function: steps()理解運動函數的問題
steps() 第一個參數 number 為指定的間隔數,即把動畫分為 n 步階段性展示,第二個參數默認為 end,設置最后一步的狀態,start 為結束時的狀態,end 為開始時的狀態。
steps 有兩個參數
第一個肯定是分幾步執行完
第二個有兩個值
start 第一幀是第一步動畫結束 //第一個階段結束之后的值
end 第一幀是第一步動畫開始 //第一個階段開始的值
理解 start 第一幀是第一步動畫結束 end 第一幀是第一步動畫開始,number為階段數
demo:http://pingfan1990.sinaapp.com/honor7/anim.html
我們看最后一個tab,可以反襯出以下
十二、inline-display 在andriod2.3下通過:before偽類導致擠下去的問題
這里建議用:after將容器撐起。
steps()
第一個參數將動畫分割成三段。當指定躍點為 start
時,動畫在每個計時周期的起點發生階躍(即圖中空心圓 → 實心圓)。由於第一次階躍發生在第一個計時周期的起點處(0s),所以我們看到的第一步動畫(初態)就為 1/3 的狀態,因此在視覺上動畫的過程為 1/3 → 2/3 → 1 。
當指定躍點為 end,動畫則在每個計時周期的終點發生階躍(即圖中空心圓 → 實心圓)。由於第一次階躍發生在第一個計時周期結束時(1s),所以我們看到的初態為 0% 的狀態;而在整個動畫周期完成處(3s),雖然發生階躍跳到了 100% 的狀態,但同時動畫結束,所以 100% 的狀態不可視。因此在視覺上動畫的過程為 0 → 1/3 → 2/3(回憶一下數電里的異步清零,當所有輸出端都為高電平的時候觸發清零,所以全為高電平是暫態)。
但是當我們看到這樣的圖片的時候,知道這個有12幀,我么就會理解為steps(12),其實這里是11個階段完成的,應該是steps(11);
demo:http://pingfan1990.sinaapp.com/honor7/anim1.html
steps(11)幀等價於,總長1680,默認是steps(11,end):
@-webkit-keyframes run1{ 0%{ background-position: 0 0; } 9.09%{ background-position: -140px 0; } 18.18%{ background-position: -280px 0; } 27.27%{ background-position: -420px 0; } 36.36%{ background-position: -560px 0; } 45.45%{ background-position: -700px 0; } 54.54%{ background-position: -840px 0; } 58.33% { background-position: -980px 0; } 63.63% { background-position: -1120px 0; } 72.72% { background-position: -1260px 0; } 81.81% { background-position: -1400px 0; } /*中間缺10張圖,11個階段*/ 100% { background-position: -1540px 0; // 12幀 } }
而steps(12)幀等價於,總長1680,默認是steps(12,end):
//這里background-position-x按幀均分,我就不算了 @keyframes run { 0% { background-position: 0 0; } 8.33% { background-position: -140px 0; } 16.67% { background-position: -280px 0; } 25% { background-position: -420px 0; } 33.33% { background-position: -560px 0; } 41.67% { background-position: -700px 0; } 50% { background-position: -840px 0; } 58.33% { background-position: -980px 0; } 66.67% { background-position: -1120px 0; } 75% { background-position: -1260px 0; } 83.33% { background-position: -1400px 0; } 91.67% { background-position: -1540px 0; } 100% { background-position: -1540px 0; } }
做動畫時請不要在:before和:after這些偽類身上做動畫,移動端不支持。做animation動畫時,我們可以結合,webkitAnimationEnd 這個事件來監聽,改變動畫,做出更炫的效果。
十二、animation不簡寫,可能造成的問題
今天做動畫時遇到animation不簡寫導致的問題,為了讓動畫達到步奏迭代,我們通常會用animation-delay來設置延遲時間,但是我發現單獨分開寫時,會導致在紅米手機上面出現,動畫元素失真的問題。
十三、animation屬性值js控制
常見的文字左右滾動通常實現形式就用animation實現設置好duration時間,但是有些時候,我們希望動態改變animation-duration的執行時間,但是發現ios生效,android不生效這種情況,是由於animation初始渲染之后,android改動是不允許生效的,這時我們只能在頁面初始加載的時候,在頭部加入js,document.write()寫入樣式進行控制了。
十四、transform中scale放大圖形導致失真的問題
昨天遇到一個問題,就是一個白色小圓通過scale放大,導致在移動端出現不同程度的失真,ios邊緣很刺,andriod就顯示成邊緣半透明的方向了。
最終發現我們通過transform的scale進行縮放,其實是對位圖放大(不管圖片還是圖形),會導致失真,解決辦法,先用大的圖形,進行縮小操作。
十五、translate3d引起的問題
1.translate3d會引起兄弟元素的z-index層級無效;原因是t3d實際是有z軸層的變換,解決辦法自己處理的是在兄弟元素上也加上t3d。
2.translate3d內部的fixed元素效果失效;從css角度無解,只能js控制或者把它抽離成t3d的兄弟元素。
十四、position定位引起的ios樣式問題
兩種情況:
<i class="fix_jd">獎勵20豆</i> 樣式 i.fix_jd{ position:fixed; bottom:60px; display: block; padding:0 10px; background: #e4393c ; height:16px; line-height: 16px; font-size: 12px; @include boradius(8px); color:#fff; left:48.4%; z-index: 1; &:before{ display: block; position: absolute; content:"\20"; @include base64Img("border_san.png"); bottom:-4px; left:10px; } }
1.父級 position:fixed, 子級position:absolute,可能導致色塊隨滾動條的變化,變藍色。
左邊是需要的正常效果,右邊是由於滾動條滾動出錯的效果。
我最終的解決辦法就是調整結構,用兩個position:fixed,或者,整個層,只用一個position:fixed.
2.父級 position:relative,子級position:absoltue,從子級position:absolute,導致,從子級的圓角無法溢出隱藏。
這個問題主要出現在一些ios版本比較舊的機型上面,也是一樣,調整結構,盡可能的少用position。
十五、position:fixed吸頂菜單,js監聽阻塞,吸頂延遲問題
解決ios8.4版以上移動端,吸頂延遲問題
- sticky 元素只能在父容器內活動
- sticky 元素父容器不能含有overflow:hidden 和 overflow:auto 屬性
示例代碼:
<div class="wx618_tabs"> <ul> <li class="cur">手機</li> <li>IT數碼</li> <li>家電<span class="sign_c_tip">小氣泡</span></li> <li>時尚服飾</li> </ul> </div>
css樣式:
.wx618_tabs { position: relative; .wx618_tabs.fixed ul { position: fixed; top: 0; left: 0; width: 100%; } } @supports (position: -webkit-sticky) { .wx618_tabs { position: -webkit-sticky; top: 80px; } .wx618_tabs.fixed ul { position: relative; } }
js常見的問題(二)
一、移動端點擊300ms延遲的問題
click300ms延遲是由於iphone采用的是雙擊默認是放大頁面,實現click是判斷第二次點擊間隔時間300ms認定為click,許多廠家沿用而導致的,click 事件因為要等待雙擊確認,會有 300ms 的延遲,體驗並不是很好。
開發者大多數會使用封裝的 tap 事件來代替click 事件,所謂的 tap 事件由 touchstart 事件 + touchmove 判斷 + touchend 事件封裝組成。
FastClick.js和tap.js可以有效的解決300ms延遲的問題。
參考資料 單擊300ms延遲
二、移動端點透問題
簡單的說,由於在移動端我們經常會使用tap(touchstart)事件來替換掉click事件,那么就會有一種場景是:
<div id="mengceng"></div> <a href="www.jd.com">www.jd.com</a>
div是絕對定位的蒙層z-index高於a,而a標簽是頁面中的一個鏈接,我們給div綁定tap事件:
$('#mengceng').on('tap',function(){ $('#mengceng').hide(); });
我們點擊蒙層時 div正常消失,但是當我們在a標簽上點擊蒙層時,發現a鏈接被觸發,這就是所謂的點透事件。
分析原因:
touchstart 早於 touchend 早於 click。亦即click的觸發是有延遲的,這個時間大概在300ms左右,也就是說我們tap觸發之后蒙層隱藏,此時click還沒有觸發,300ms之后由於蒙層隱藏,我們的click觸發到了下面的a鏈接上。
解決辦法:
1 盡量都使用touch事件來替換click事件。
2 阻止a鏈接的click的preventDefault
點透資料:http://segmentfault.com/q/1010000000691822
三、移動端touch事件問題,在andriod4.0
移動端touch事件:
touchstart //當手指接觸屏幕時觸發
touchmove //當已經接觸屏幕的手指開始移動后觸發
touchend //當手指離開屏幕時觸發
touchcancel//當某種touch事件非正常結束時觸發
這4個事件的觸發順序為:
touchstart -> touchmove -> touchend ->touchcancel
對於某些android系統touch的bug:
比如手指在屏幕由上向下拖動頁面時,理論上是會觸發 一個 touchstart ,很多次 touchmove ,和最終的 touchend ,可是在android 4.0上,touchmove只被觸發一次,觸發時間和touchstart 差不多,而touchend直接沒有被觸發。這是一個非常嚴重的bug,在google Issue已有不少人提出 ,這個很蛋疼的bug是在模擬下拉刷新是遇到的尤其當touchmove的dom節點數量變多時比出現,當時解決辦法就是用settimeout來稀釋touchmove。
或者通過在touchmove阻止默認行為preventDefault,這里就會導致要通過js來實現頁面的滾動:
//發現在android4.0以上的webkit瀏覽器touchmove事件只觸發一次,加event . preventDefault()就可以,但是這里就導致只能通過js來實現頁面的滾動 addEventListener("touchmove",function(e){ e.stopDefault(e); },false)
四、 html5重力感應事件
這個不是什么問題,我只是覺得好,所以說一下,當回搬運工,簡單的搖一搖案例。
if (window.DeviceMotionEvent) { window.addEventListener('devicemotion',deviceMotionHandler, false); } var speed = 30;//speed var x = y = z = lastX = lastY = lastZ = 0; function deviceMotionHandler(eventData) { var acceleration =event.accelerationIncludingGravity; x = acceleration.x; y = acceleration.y; z = acceleration.z; if(Math.abs(x-lastX) > speed || Math.abs(y-lastY) > speed || Math.abs(z-lastZ) > speed) { //簡單的搖一搖觸發代碼 alert(1); } lastX = x; lastY = y; lastZ = z; }
關於deviceMotionEvent是HTML5新增的事件,用來檢測手機重力感應效果具體可參考:
http://w3c.github.io/deviceorientation/spec-source-orientation.html
四、 多音頻的問題
我們知道,ios設備可以多音頻支持,但是andriod不支持多音頻,很多時候做法往往是我們先靜止背景音樂,然后去播放另一音樂,感覺上實現多音頻。
這里大家也可以嘗試第三方插件:
*優先使用 Web Audio API
*SoundJS 等音頻處理庫
五、 橫屏監測
樣式判斷
//橫屏 @media only screen and (orientation: landscape) { .warn_wp { display: block } } //豎屏 @media only screen and (orientation: portrait) { .warn_wp { display: none } }
腳本判斷:
//橫屏監聽 var updateOrientation = function(){ var $landscapeWrap = $('.landscape_wrap'); if(window.orientation === -90 || window.orientation === 90){ $landscapeWrap.show(); }else{ $landscapeWrap.hide(); } } } window.orientationchange = updateOrientation;
經典材料:
meta標簽大全 http://segmentfault.com/blog/ciaocc/1190000002407912
使用border-image實現類似iOS7的1px底邊:https://github.com/AlloyTeam/Mars/blob/master/solutions/border-1px.md
devicePixelRatio:http://imququ.com/post/devicepixelratio-and-border-width.html
移動問題小結:http://www.alloyteam.com/2015/06/yi-dong-web-wen-ti-xiao-jie/