多端適配
熟悉前端開發的一定會遇到這個問題,屏幕適配!有的項目要求同時適配PC、平板和移動端,那我們應該是寫幾套不同的樣式,還是隻寫一套呢?哪一種才是最好的?
其實沒有哪一種最好的,還是得根據項目的需求來定,一般情況下我是推薦只寫一套代碼,因為這樣可以降低開發成本和維護難度。那麼就有個問題,一套代碼如何去適配不同設備?尺寸該用什麼單位?px?em?rem?
我想大部分人的實現無非就那幾種方案:
在頁面初始化的時候做判斷,缺點是不能響應尺寸的變化,頁面需要手動刷新,可以寫一個 resize 監聽事件,當然極少情況下設備屏幕尺寸會發生改變
document.addEventListener("DOMContentLoaded", () => {
const design = 750;
const docEl = document.documentElement;
let clientWidth = docEl.clientWidth;
if (utils.clientAgent.isPc) {
// 如果是PC端
}
if (clientWidth > 0) {
docEl.style.fontSize = (clientWidth / design) * 100 + "px";
}
}, false);
使用 @media 判斷,可以做到尺寸變化的響應,缺點是大量的 @media,可讀性較差,維護起來非常麻煩,感覺還不如寫幾套不同的樣式
@media screen and (max-width: 375px) {
...
}
@media screen and (max-width: 576px) {
...
}
@media screen and (max-width: 768px) {
...
}
安裝各種第三方插件,就是配置項比較多,大多數人選擇的方案
npm install lib-flexible
npm install px2rem-loader
...
以上的幾種方案都可以解決屏幕自適應的問題,使用上沒什麼問題,只不過都是基於 rem 佈局方案,對移動端來説效果是最好的,但是在PC端用 rem 顯然不太合適,那有沒有辦法在PC和移動端切換的時候自動轉換 px 和 rem 單位呢?
Less Functions
參考文檔
能否不用 javascript?直接在 less 中實現自動切換?為了實現這個目的,飯吃不好,覺也睡不好,嘗試了各種各樣的方法,通過 less 各種函數偏方最終實現了。
我用的 less 版本是 3.0,查看最新的版本好像是 4.0 以上了,高版本中多了一些新函數,例如 if、each 等,能更方便的編碼,不過既然能用低版本實現,那兼容性肯定會更強。
實現方法主要是對 value 進行遍歷,length、extract 函數能夠識別空格當成數組對象,遍歷找出數字型的值,通過 @media 查詢自動切換尺寸單位。
原理不難,用 javascript 分分鐘就實現了,但是在 less 中就有點蛋疼了,因為作用域的問題,@media 查詢中的函數無法被外部調用,一開始還是被難住了。
/* 根據不同設備適配屬性單位 */
.mixin-property-rules(@property, @value, @device) {
@n: length(@value);
.each(@i, @parent: "") when (@i < @n + 1) {
@arg: extract(@value, @i);
/* 屏幕大於或等於768px的設備 */
.ifNumber() when (isnumber(@arg) = true) and (@device = 001) {
@child: unit(@arg, px);
}
/* 屏幕小於768px的設備 */
.ifNumber() when (isnumber(@arg) = true) and (@device = 002) {
@child: unit(@arg * 2 / 100, rem);
}
/* 非數值屬性 */
.ifNumber() when (isnumber(@arg) = false) {
@child: @arg;
}
.ifNumber();
@newValue: ~"@{parent} @{child}";
.ifLast() when (@i = @n) {
@{property}: @newValue;
}
.ifLast();
.each(@i + 1, @newValue);
}
.each(1);
}
.mixin-property(@property, @value) {
/* 屏幕大於768px的設備 */
@media screen and (min-width: 768px) {
.mixin-property-rules(@property, @value, 001);
}
/* 屏幕小於768px的設備 */
@media screen and (max-width: 768px) {
.mixin-property-rules(@property, @value, 002);
}
}
html {
font-size: 14px;
/* 屏幕小於768px的設備 */
@media screen and (max-width: 768px) {
font-size: ~"calc(100vw / 1536 * 100)";
}
/* 屏幕小於576px的設備 */
@media screen and (max-width: 576px) {
font-size: ~"calc(100vw / 750 * 100)";
}
}
函數調用
.example {
.mixin-property(padding, 10 20 15 30);
.mixin-property(border, 1 solid #000);
.mixin-property(font-size, 16);
}
// 輸出 screenWidth >= 768
.example {
padding: 10px 20px 15px 30px;
border: 1px solid #000;
font-size: 16px;
}
// 輸出 screenWidth < 768
.example {
padding: .2rem .4rem .3rem .6rem;
border: .02rem solid #000;
font-size: .32rem;
}
該函數的優點是你無須寫單位,只寫大小數值,方法會根據設備自動返回單位!如果以後想更改尺寸大小或單位,只需修改函數中的計算邏輯即可,一勞永逸!要説缺點的話就是每個調用的函數在 css 中都會輸出 @media 查詢語句。
提示:函數中的 @media 查詢和數值計算邏輯都是要根據自己需求編寫的,上面只是我寫的例子而已
(・`ω´・) 點贊會有更多原創技術文章分享!