web移动端适配技巧

577 阅读3分钟

1. 配置视口viewport

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  • width=device-width:将视口宽度设置为设备宽度
  • initial-scale=1.0:初始缩放比例为1
  • user-scalable=no:禁用用户缩放, 可配置no或者yes
  • viewport-fit=cover:适配刘海屏

2. 使用vw实现布局

假设设计稿尺寸为 750*1334
网页宽度=100vw
网页宽度=100vh

所以,在 750*1334 的屏幕分辨率下
750px = 100vw

1px = (100 / 750)vw

3. 使用rem实现布局

rem是相对于根元素(html)的字体大小的单位

// 设置 rem 基准值  
(function flexible() {  
    const docEl = document.documentElement;  

    function setRemUnit() {  
        const rem = docEl.clientWidth / 10;  
        docEl.style.fontSize = rem + 'px';  
    }  

    setRemUnit();  
    window.addEventListener('resize', setRemUnit);  
    window.addEventListener('orientationchange', setRemUnit);  
})();

配套的CSS使用:

.container {
    width: 7.5rem;  /* 750px / 100 */
    height: 1rem;   /* 100px / 100 */
    font-size: 0.28rem; /* 28px / 100 */
}

4. 媒体查询处理不同尺寸

/* iPhone SE */
@media screen and (max-width: 374px) {
    .container {
        font-size: 14px;
    }
}

/* iPhone 6/7/8/X */
@media screen and (min-width: 375px) and (max-width: 413px) {
    .container {
        font-size: 16px;
    }
}

/* iPhone 6/7/8 Plus */
@media screen and (min-width: 414px) {
    .container {
        font-size: 18px;
    }
}

5. 解决1px边框问题

在高清屏幕下1px边框显示过粗的解决方案。

.border-1px {
    position: relative;
    &::after {
        content: '';
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        height: 1px;
        background-color: #000;
        transform: scaleY(0.5);
        transform-origin: bottom;
    }
}

// 2x屏
@media (-webkit-min-device-pixel-ratio: 2) {
    .border-1px::after {
        transform: scaleY(0.5);
    }
}

// 3x屏
@media (-webkit-min-device-pixel-ratio: 3) {
    .border-1px::after {
        transform: scaleY(0.33);
    }
}

6. 安全区域适配

适配iPhone X等机型。

/* 适配刘海屏 */
.safe-area-inset {
    padding-top: constant(safe-area-inset-top);
    padding-top: env(safe-area-inset-top);
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}

/* 底部固定导航适配 */
.fixed-bottom {
    position: fixed;
    bottom: 0;
    bottom: constant(safe-area-inset-bottom);
    bottom: env(safe-area-inset-bottom);
}

7. 图片适配

srcset 与 sizes 配合使用, 针对不同分辨率设备的图片适配策略。

  • srcset 与 sizes 配合使用,分别包含图片 URL 和描述符,不同情况有不同规则;
  • x 描述符按像素比,w 描述符按像素大小

x 描述符

<img
    srcset="
        /images/2500 5x,
        /images/1500 3x,
        /images/1000 2x,
        /images/500 1x
    "
    src="/images/500"
/>

w 描述符

w 描述符可以简单理解为描述源图的像素大小(大部分情况下可以理解为宽度)。

<img
    srcset="
       /images/2000 2000w,
       /images/1500 1500w,
       /images/1000 1000w,
       /images/500 500w
    "
    sizes="
        (max-width: 500px) 500px,
        (max-width: 1000px) 1000px,
        (max-width: 1500px) 1500px,
        2000px
    "
    src="/images/500"
/>

配合CSS的处理:

.responsive-image {
    max-width: 100%;
    height: auto;
    display: block;
}

8. 横屏适配

/* 检测横屏 */
@media screen and (orientation: landscape) {
    .landscape-container {
        display: flex;
        flex-direction: row;
    }
}

/* 检测竖屏 */
@media screen and (orientation: portrait) {
    .portrait-container {
        display: flex;
        flex-direction: column;
    }
}

js监听屏幕旋转:

window.addEventListener('orientationchange', function() {
    if (window.orientation === 180 || window.orientation === 0) {
        // 竖屏
        console.log('竖屏');
    }
    if (window.orientation === 90 || window.orientation === -90) {
        // 横屏
        console.log('横屏');
    }
});

9. 软键盘弹出处理

处理软键盘弹出时的页面适配问题。

// 监听软键盘
const originalHeight = document.documentElement.clientHeight;

window.addEventListener('resize', () => {
    const currentHeight = document.documentElement.clientHeight;
    const input = document.activeElement;
    
    if (originalHeight > currentHeight) {
        // 软键盘弹出
        if (input.tagName === 'INPUT' || input.tagName === 'TEXTAREA') {
            input.scrollIntoView({ block: 'center' });
        }
    } else {
        // 软键盘收起
        window.scrollTo(0, 0);
    }
});

CSS处理:

/* 防止键盘顶起页面 */
.container {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
}

10. chrome设置微信环境

Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1 wechatdevtools/1.03.2006090 MicroMessenger/7.0.4 Language/zh_CN webview/16166377824525103  port/48436