一、思考
在移動端越來越重要的背景下,每位web開發者對移動适配都有自己的想法。是移動優先,還是PC優先,還是兩者兼得?在實際開發中這個問題是和項目産品定位有關的,也涉及到UI的設計,不是開發者能決定。但不管産品如何定位,作為開發者總是要提供最優的解決方案,是用一套樣式還是多套樣式?網上一搜,有靜态布局、流式布局,響應式布局,自适應布局,彈性布局等一堆,雲裡霧裡,到底要怎麼選呢?看完這篇文章相信心中就有數了。
二、viewport的使用
1、最常見的設定,大多數的架構(如bootstrap)和知名的站點基本是這個配置
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
2、這個配置重點在width=device-width,就是讓視視窗等于設配寬度,也就是我們開發中能用document的寬度,其它幾個“初始縮放大小”“最大縮放大小”“最小縮放大小”和“是否允許使用者縮放”可以了解為用來“固定”這個設定不被破壞的。
3、這個設定很簡單,但同時也會帶來一些需要解決的問題。
a、現在的手機都是兩倍三倍的Retina高清屏,1px實際的效果是不止一個像素的,對不同的裝置設定不同
的initial-scale可以有比較好的效果,比如在2倍Retina的iphone6(6s,7,8)中設定為0.5。一旦
動态設定這個,也就意味這視視窗不同了,需要不同樣式适配。這也是配置設定樣式的一套基準,如何配置設定樣式
後面會有更詳細的講解。
b、在PC端如果有最小寬度的限制,同樣需要配置不同的width值。
三、機關的使用
1、css中機關很多,這裡隻介紹最常用的幾種:
(1) px:這個可以了解為“基準”機關,就是不管在什麼裝置中其值是不會變的,就像cm,kg這些一樣
(2) em:這個是相對父容器的機關,一般用在字型font-size中比較好。如父容器font-size為16px,則
1em=16px
(3) rem:相對于根元素html的機關,如html的font-size為16px,則1rem=16px
(4) vw/vh: 視口寬高為100vw/100vh,這個和百分比類似,隻是百分比是相對于父容器,其相對于視口
2、移動适配最常用的應該是rem,很多架構和淘寶的flexible适配都是基于這個機關,而自己做的話,一般
在首頁加載時全局js設定html的font-size即可,代碼如下:
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
//這裡根據設計稿為750,設定1rem=100px,
docEl.style.fontSize = 100 * (clientWidth / 375) + 'px';
};
// Abort if browser does not support addEventListener
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
3.如果用了sass/less等預編譯語言可以更靈活的配置的,在上面方法内配置(設計稿為750的情況下):
docEl.style.fontSize = 40 * (clientWidth / 750) + 'px';
在編譯函數中配置:
@function px2rem($px, $base-font-size: 20px) {
@return ($px / $base-font-size) * 1rem;
}
這樣我們就可以直接使用設計稿的尺寸,如:px2rem(100px),省去了自己計算,如果沒用預編譯語言(推
薦使用),編輯器也有插件支援機關轉化。
4.上面是基于螢幕寬度來設定根元素font-size,如果設定不同的initial-scale,我們需要基于裝置像素比設定,通過window.devicePixelRatio擷取。
四、頁面布局方式
1.了解html的文檔流方式,其實就是流式布局,即橫向需要我們設定,縱向自動疊加。這個和移動端的設計體驗方式是比較像的。在寬度中就要用自适應的方式,如百分比,有設定相對機關的,可用相對機關,靈活使用,css3的display:flex也是很好的選擇,現代浏覽器和移動裝置基本都支援了。
2.剛才說到體驗,很明顯移動端和pc端的體驗真的很不同,是以光有上面的自适應是遠遠不夠,是不是需要對這兩個完全不同的體驗方式響應不同的布局和樣式。
五、媒體查詢
1.我們除了可以用js來判斷不同的裝置,設定相對機關所用的根元素。另一個強大的方式是可以通過css3強大的媒體查詢來指定不同的樣式。
2.媒體查詢的規則
@media all and ([min-width|max-width|orientation|min-device-width|...]) { ... }
中括号[]中表示需要添加的條件,可比對寬高/橫豎屏/裝置類型等,比如min-width:750px,表示最小寬度為750px,{}是在比對模式下的樣式。也有邏輯判斷and/or/not連接配接不同的規則
3.要是引入整個檔案,可以在link标簽中使用
<link rel="stylesheet" media="screen and (min-width:900px)" href="big.css" type="text/css" />
表示:當螢幕大于或等于900px時,将采用big.css樣式來渲染Web頁面。
4.Bootstrap響應式設計這類栅格布局采用的就是這套方式。
六、1px像素邊框問題
1.除了上面說到在viewport中設定縮放外,直接設定一個空元素縮放也是可以的
p{
width: 100px;
height: 1px;
background: red;
display: block;
transform: scaleY(.5);
}
不足:圓角無法實作,實作4條邊框比較麻煩,并且隻能單獨實作,如果嵌套,會對包含的效果産生不想要的效果,是以此方案配合:after和before獨立使用較多
2.利用CSS對陰影處理的方式實作0.5px的效果
box-shadow:0 1px 1px -1px rgba(0, 0, 0, 0.5);
不足:顔色不好處理, 黑色 rgba(0,0,0,1) 最深的情況了。有陰影出現,不好用大量使用box-shadow可能會導緻性能瓶頸。四條邊框實作效果不理想。
3.圖檔實作,使用 background-image 實作1px有兩種方式: 漸變 linear-gradient 或直接使用圖檔(base64)。漸變 linear-gradient (50%有顔色,50%透明)
div{
height: 1px;
background-image:-webkit-linear-gradient(top,transparent 50%,#000 50%);
background-position: top left;
background-repeat: no-repeat;
background-size: 100% 1px;
}
不足:大量使用漸變可能導緻性能瓶頸,代碼量大,多背景圖檔有相容性問題
七、圖檔高清化
1.可以使用srcset屬性設定,使用看https://www.zhangxinxu.com/wordpress/2014/10/responsive-images-srcset-size-w-descriptor/
2.背景圖高清
a.使用上面介紹的媒體查詢,如:
/* 普通顯示屏(裝置像素比例小于等于1)使用1倍的圖 */
.css{
background-image: url(img_1x.png);
}
/* 高清顯示屏(裝置像素比例大于等于2)使用2倍圖 */
@media only screen and (-webkit-min-device-pixel-ratio:2){
.css{
background-image: url(img_2x.png);
}
}
/* 高清顯示屏(裝置像素比例大于等于3)使用3倍圖 */
@media only screen and (-webkit-min-device-pixel-ratio:3){
.css{
background-image: url(img_3x.png);
}
}
b.image-set 實作高清化
.css {
background-image: url(1x.png); /*不支援image-set的情況下顯示*/
background: -webkit-image-set(
url(1x.png) 1x,/* 支援image-set的浏覽器的[普通螢幕]下 */
url(2x.png) 2x,/* 支援image-set的浏覽器的[2倍Retina螢幕] */
url(3x.png) 3x/* 支援image-set的浏覽器的[3倍Retina螢幕] */
);
}
c.很多網頁端對圖檔的要求還是沒那麼高的,不像app那樣,圖檔一般用一張2倍高清圖就行,最新的裝置對以上屬性的支援還是可以的,對于要求高的應用使用
八、移動端click螢幕産生300ms的延時響應
1.原因:在浏覽器需要如何判斷快速點選上,當使用者在螢幕上單擊某一個元素時候,例如跳轉連結<a href="#"></a>,此處浏覽器會先捕獲該次單擊,但浏覽器不能決定使用者是單純要點選連結還是要輕按兩下該部分區域進行縮放操作,是以,捕獲第一次單擊後,浏覽器會先Hold一段時間t,如果在t時間區間裡使用者未進行下一次點選,則浏覽器會做單擊跳轉連結的處理,如果t時間裡使用者進行了第二次單擊操作,則浏覽器會禁止跳轉,轉而進行對該部分區域頁面的縮放操作。那麼這個時間區間t有多少呢?在IOS safari下,大概為300毫秒。這就是延遲的由來。造成的後果使用者純粹單擊頁面,頁面需要過一段時間才響應,給使用者慢體驗感覺,對于web開發者來說是,頁面js捕獲click事件的回調函數處理,需要300ms後才生效,也就間接導緻影響其他業務邏輯的處理。
2.解決方案:
(1)使用fastclick.js,隻要全局加入該檔案并設定如下:
FastClick.attach(document.body);
(2) zepto的touch子產品,tap事件也是為了解決在click的延遲問題
九、更改預設樣式
//使用appearance改變webkit浏覽器的預設外觀
input,select { -webkit-appearance:none; appearance: none; }
//winphone下,使用僞元素改變表單元素預設外觀
//1.禁用select預設箭頭,::-ms-expand修改表單控件下拉箭頭,設定隐藏并使用背景圖檔來修飾
select::-ms-expand { display:none; }
//2.禁用radio和checkbox預設樣式,::-ms-check修改表單複選框或單選框預設圖示,設定隐藏并使用背景圖檔來修飾
input[type=radio]::-ms-check,
input[type=checkbox]::-ms-check { display:none; }
//3.禁用pc端表單輸入框預設清除按鈕,::-ms-clear修改清除按鈕,設定隐藏并使用背景圖檔來修飾
input[type=text]::-ms-clear,
input[type=tel]::-ms-clear,
input[type=number]::-ms-clear { display:none; }
// 禁止長按連結與圖檔彈出菜單
a,img { -webkit-touch-callout: none }
// 禁止ios和android使用者選中文字
html,body {-webkit-user-select:none; user-select: none; }
// 改變輸入框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; }
// android上去掉語音輸入按鈕
input::-webkit-input-speech-button {display: none}
十、總結
1.網站适配的終端可以用js或媒體查詢的方式擷取,配置設定對應的樣式。
2.布局上采用相對機關,百分比和flex的彈性方式。
3.對移動端的特殊性進行适配,如1px問題,預設樣式等。