相關標簽
rem谱轨、viewport、mediaQuery吠谢、vw,vh土童、...
前言
最近空余時間,還是在找些react小項目練手工坊。練手的項目不是別的献汗,正好是目前在做的iOS項目敢订,在邊做iOS邊寫react的對比中,自然而然地牽扯到了webApp的適配問題罢吃。
一楚午、移動端適配前期準備
meta標簽設置ideal viewport
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
meta viewport 標簽首先是由蘋果公司在其safari瀏覽器中引入的,目的就是解決移動設備的viewport問題刃麸。因為好用后面的各種瀏覽器都紛紛對此進行了兼容醒叁。這里就不解釋viewport的方方面面了,這篇文章解釋的很詳細泊业。移動前端開發(fā)之viewport的深入理解
二把沼、理解rem是什么
“font size of the root element”,W3C官網(wǎng)是這樣定義的。直白點說就是根節(jié)點元素吁伺,(一般為<html>標簽)的fontSize饮睬。
打個比方:
如果根節(jié)點的元素fontSize設為100px,意味著1rem=100px。那么我們?nèi)绻幸粋€邊距在UI標注中為200px篮奄,就可以寫為2rem捆愁。
嗯...很好理解。這也是我查看N多前端童鞋寫的相關rem文章時他們主要提到的窟却。問題是昼丑,這和傳說中適配有什么關系?
別著急夸赫,耐心看下去~
三菩帝、先來談一下iOS端的比例適配
直接看代碼,以下是我在iOS端處理的適配方案:
OC代碼:
/**
* 375為UI標注采用的屏幕寬度標準
* 實際屏幕寬 / 375茬腿,獲取真實尺寸與UI尺寸比例
*/
#define BEI6 (MIN(Screen_Width, Screen_Height) / 375)
/**
* size為UI標準的期望值
* 根據(jù)真實尺寸與UI尺寸的比例呼奢,計算出期望值的真實尺寸
*/
#define AutoSize(size) ((size) * BEI6)
/**
* 根據(jù)UI標注的frame獲取真實frame
*/
#define AutoFrame(frame) CGRectMake(frame.origin.x*BEI6,frame.origin.y*BEI6, frame.size.width*BEI6, frame.size.height*BEI6)
swift代碼:
public func kBEI6() -> CGFloat {
return min(kScreenWidth, kScreenHeight) / 375.0
}
public func kAutoSize(size: CGFloat) -> CGFloat {
return kBEI6() * size
}
public func kAutoFrame(frame: CGRect) -> CGRect {
return CGRect(x: (kBEI6() * frame.origin.x), y: (kBEI6() * frame.origin.y), width: (kBEI6() * frame.size.width), height: (kBEI6() * frame.size.height))
}
代碼很簡潔,很容易就能明白切平。
就是通過手機真實屏幕的寬度除以UI標注上的寬度尺寸握础,獲得一個比例。再以這個比例為媒介獲取每一個期望值在真實手機上的真實尺寸悴品。
實際上rem適配的精髓和這種iOS適配方式如出一轍禀综!
題外話:非移動端的童鞋可以忽略!Lρ稀菇存!
移動端原生控件的寬高其實并不是指單純的像素,因為有retina屏的原因邦蜜,所以原生中的1 有可能為2px或3px。這就導致了原生控件中假如給定寬為100亥至,實際上在相同物理屏幕寬度下悼沈,其有可能是200像素贱迟,也有可能是300像素。移動端懂得自然懂絮供。6s和6plus就是個極為典型的例子衣吠,其屏幕寬度都是414point。但其一個為2倍屏壤靶,即寬度為828像素缚俏;一個為3倍屏,寬度為1242像素贮乳。
三忧换、rem是如何進行比例適配的
子標題這樣說,細究起來是不對的向拆。因為rem只是一個單位亚茬,1rem=根節(jié)點的fontSize值而已。其本身是不具備適配功能的浓恳。
但是其與根節(jié)點的fontSize有這種特殊關系刹缝,那我們大可以對根節(jié)點的fontSize做做手腳~通過動態(tài)設置根節(jié)點fontSize,即動態(tài)設置單位rem值颈将,實現(xiàn)比例適配梢夯。
剛才說了rem適配其實與我那種iOS比例適配有異曲同工之妙,iOS適配的比例因子是真實屏幕寬度與UI標注寬度的商晴圾。那在我們web端颂砸,如果獲取到瀏覽器的真實寬度(webApp中就是webView寬度),通過其與UI標注的寬度進行除法運算疑务,商就是我們需要的適配比例因子沾凄。再通過這個比例因子,動態(tài)比例地設置根標簽的fontSize知允,從而達到1 rem值對應像素單位px的比例升降撒蟀。
知道了步驟,我們編寫代碼如下:
請仔細閱讀注釋温鸽,句句精髓
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<title>rem適配</title>
<!--因為是設置樣式的js代碼保屯,所以寫在head標簽中了-->
<script type="text/javascript">
//自執(zhí)行匿名函數(shù)
(function (uiWidth, expectFontSize) {
//獲取瀏覽器真實寬度
let deviceWidth = document.documentElement.clientWidth
function setRemUnit() {
//計算適配比例
let scale = deviceWidth / uiWidth
//乘以100的目的是,這樣我們將UI標注的px值除以100涤垫,就是我們需要的rem值
document.documentElement.style.fontSize = scale * expectFontSize + 'px'
}
//執(zhí)行初始rem函數(shù)
setRemUnit()
//設置監(jiān)聽姑尺,當window重新resize的時候,重新初始rem
window.addEventListener('resize', setRemUnit)
})(375, 100)
</script>
</head>
以上代碼中的375蝠猬,是假設的UI標注的標準寬度切蟋。依具體的UI標注進行替換。
核心思想就是設備屏幕寬度不同榆芦,比例因子不同柄粹。從而使得根標簽的fontSize不同喘鸟,也就是單位rem對應的px值不同。 1rem = 比例因子 * 默認期望值
我們根據(jù)上面的代碼捋一下產(chǎn)生的結果:
- 假如iPhone6設備(屏幕寬度為375px)上驻右,設置一個控件寬度設為0.7rem什黑,此時換算為px單位為(375 / 375.0 * 70) = 70px;
- 而在iPhone8設備(屏幕寬度為414px)上,0.7rem換算為px單位為(414 / 375.0 * 70) = 77.28px堪夭。這樣就很完美地實現(xiàn)了比例適配功能愕把。
四、媒體查詢對特殊情況進行適配
做iOS開發(fā)的時候森爽,使用上面我提到的比例適配方案恨豁,有時候并不能完美地去進行適配。比如處理劉海屏拗秘、適配iOS11等情況圣絮。這個時候命令式的iOS語法會單獨地對這些情況去做處理。那么前端語言要怎么去解決這個問題呢雕旨?
- 第一種最直白的方法就是利用js獲取真實dom扮匠,然后針對特殊情況去設置樣式屬性,顯然這種面向過程的方式太low太繁瑣凡涩。
- 利用媒體查詢mediaQuery的方式進行處理棒搜,語法如下
@media 媒體類型 and (媒體特性: 600px) {
選擇器 {
屬性:屬性值;
}
}
具體的媒體類型和特性可以在W3C官網(wǎng)上查看活箕,我個人覺得沒必要看力麸,會一些常用的。其他到用到時再去查閱即可育韩。
舉個例子說明一下:
//處理屏幕寬小于等于320px時克蚂,類名為inner的標簽樣式
@media screen and (max-width: 320px) {
.inner {
height: 100%;
width: 25%;
float: left;
}
}
//處理屏幕寬大于等于321px時,類名為inner的標簽樣式
@media screen and (min-width: 321px) {
.inner {
height: 50px;
width: 100%;
}
}
五筋讨、vh埃叭、vw方案適配
這種好像算是目前最流行的移動端適配方案,暫時還沒接觸悉罕。待定...