Rumah hujung hadapan web tutorial js 移动端页面开发适配 rem布局原理

移动端页面开发适配 rem布局原理

Nov 21, 2016 pm 05:41 PM

移动端页面开发适配 rem布局原理

什么是适配,为什么要适配

我们拿到的设计图一般是以640,750,1080分辨率为基准设计的,而现在的手机终端各式各样,分辨率不同,逻辑像素不同 ,视口不同,所以为了让我们的页面在每个设备上都可以良好的展示,那么就需要为这些设备做统一的处理,这个过程就称为移动端适配。

需要知道的一些概念:

物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,可以理解为我们平时说的分辨率。

设备独立像素(density-independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素,在这里可以理解为我们说的视觉视口的大小;

所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比。

设备像素比(device pixel ratio)

设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:设备像素比 = 物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向

设备像素比也是设备生产的时候设置好的,在javascript中,可以通window.devicePixelRatio获取到当前设备的dpr。

视口(viewport)

pc端视口指浏览器窗口内的内容区域,不包含工具条,滚动条.

移动浏览器中视口分为几种情况:

中content所设置的视口,称为布局视口,最大值由浏览器厂商规定 ,可以document.documentElement.clientWidth获取其宽度.

而我们看到的浏览器的窗口,网页区域的大小,称为视觉视口,用css像素表示(设备逻辑像素)

rem

rem是css3 的一个长度单位 ,相对文档跟元素 html;比如设置html font-size=100px;那么1rem=100px;之后的所有元素都可以用这个基准值来设置大小;

常用的方案:

固定高度,宽度自适应(百分比,em)

使用 rem布局

下面总结了网易 淘宝首页使用rem的方案

网易的做法:

1) 将布局适口设置为视觉视口,不进行缩放,即理想视口。

<meta name="viewport"content="initial-scale=1,maximum-scale=1, minimum-scale=1”>
Salin selepas log masuk

2) 以设计稿分辨率为基准,取100px为font-size的参照,那么设计稿的宽如果是640,body元素的宽度就可以设置为width:6.4rem(640/100),当我们将布局视口设置为320时,于是html的font-size=deviceWidth / 6.4。

3) 通过document.documentElement.clientWidth获取deviceWidth;

4) 当页面的dom ready后设置html font-size,

document.documentElement.style.fontSize =document.documentElement.clientWidth / 6.4 + ‘px’
Salin selepas log masuk

5) 通过mediaQuery 设置字体大小,字体大小不可以使用rem,原因是误差太大。

以640的设计稿为例最终的设置html font-size代码如下,布局时拿设计稿标注的尺寸除以100,就是rem的值,相当简单啊

var deviceWidth = document.documentElement.clientWidth;
if(deviceWidth > 640) deviceWidth = 640;
document.documentElement.style.fontSize = deviceWidth / 6.4 + &#39;px&#39;;
Salin selepas log masuk

这里if(deviceWidth > 640) deviceWidth = 640; 是因为当deviceWidth大于640时物理分辨率已经大于1280(取决于dpr),应该去访问pc的网站;

淘宝的做法:

原理

1) 通过dpr设置缩放比,实现布局视口大小,

var scale = 1 / devicePixelRatio;  
 document.querySelector(&#39;meta[name="viewport"]&#39;).setAttribute(&#39;content&#39;,&#39;initial-scale=&#39;+ scale + &#39;, maximum-scale=&#39; + scale + &#39;, minimum-scale=&#39; + scale + &#39;, user-scalable=no&#39;);
Salin selepas log masuk

2) 动态计算html的font-size

document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + ‘px’;
Salin selepas log masuk

这里的意思是,clientWidth / 10 得到是布局视口下的rem基准值(以iphone6为例 1rem=75px),那么设计稿正好也是 750,所以对应的关系 clientWidth / 10==设计稿的尺寸/x, 那么x=设计稿的尺寸/rem基准值。如果是iphone6 plus rem基准值等于clientWidth / 10 等于124.2,那么x=750/124.2。

关于具体的实现 淘宝提供了一个开源的方案lib-flexible:https://github.com/amfe/lib-flexible

具体逻辑 :

1)判断head中是否设置了viewport,如果有设置,按照已有viewport 设置缩放比;

if (metaEl) {
        console.warn(&#39;将根据已有的meta标签来设置缩放比例&#39;);
        var match = metaEl.getAttribute(&#39;content&#39;).match(/initial\-scale=([\d\.]+)/);
        if (match) {
            scale = parseFloat(match[1]);
            dpr = parseInt(1 / scale);
        }
    }
Salin selepas log masuk

2)如果没有设置meta viewport,判断是否设置dpr,如果有,通过dpr计算缩放scale。

        var content = flexibleEl.getAttribute(&#39;content&#39;);
        if (content) {
            var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
            var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);//maximum 设置最大值,与initial的值比较,取最小值;
            if (initialDpr) {
                dpr = parseFloat(initialDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));    
            }
            if (maximumDpr) {
                dpr = parseFloat(maximumDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));    
            }
        }
Salin selepas log masuk

3)如果 dpr &scale都没有设置,那么就通过设备的dpr设置起缩放 scale,

if (!dpr && !scale) {//meta[name="viewport"]&&meta[name="flexible"]都不存在。
    var isAndroid = win.navigator.appVersion.match(/android/gi);
    var isIPhone = win.navigator.appVersion.match(/iphone/gi);
    var devicePixelRatio = win.devicePixelRatio;
    if (isIPhone) {
        // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
        if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
            dpr = 3;
        } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
            dpr = 2;
        } else {
            dpr = 1;
        }
    } else {
        // 其他设备下,仍旧使用1倍的方案
        dpr = 1;
    }
    scale = 1 / dpr;
}
Salin selepas log masuk

4)得到scale之后 ,如果meta 的viewport不存在,那么就创建一meta[name=“viewport”],将scale配置进去。

    metaEl = doc.createElement(&#39;meta&#39;);
    metaEl.setAttribute(&#39;name&#39;, &#39;viewport&#39;);
    metaEl.setAttribute(&#39;content&#39;, &#39;initial-scale=&#39; + scale + &#39;, maximum-scale=&#39; + scale + &#39;, minimum-scale=&#39; + scale + &#39;, user-scalable=no&#39;);

    if (docEl.firstElementChild) {

        docEl.firstElementChild.appendChild(metaEl);
         
    }
Salin selepas log masuk

5)动态改写html的font-size

    var width = docEl.getBoundingClientRect().width;//获取html的宽度
    if (width / dpr > 540) {//判断屏幕逻辑像素大于540时,取540
        width = 540 * dpr;
    }
    var rem = width / 10;
    docEl.style.fontSize = rem + &#39;px&#39;;
    flexible.rem = win.rem = rem;
Salin selepas log masuk

总结:

使用rem布局,实质都是通过动态改写html的font-size基准值,来实现不同设备下的良好统一适配;

网易与淘宝不同 的地方是 ,网易将布局视口设置成了 视觉视口,淘宝将布局视口设置成了物理像素大小,通过 scale缩放嵌入了 视觉视口中;

容器元素的字体大小都不使用rem,需要额外的media查询;


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Arahan sembang dan cara menggunakannya
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimana saya membuat dan menerbitkan perpustakaan JavaScript saya sendiri? Bagaimana saya membuat dan menerbitkan perpustakaan JavaScript saya sendiri? Mar 18, 2025 pm 03:12 PM

Artikel membincangkan membuat, menerbitkan, dan mengekalkan perpustakaan JavaScript, memberi tumpuan kepada perancangan, pembangunan, ujian, dokumentasi, dan strategi promosi.

Bagaimanakah saya mengoptimumkan kod JavaScript untuk prestasi dalam penyemak imbas? Bagaimanakah saya mengoptimumkan kod JavaScript untuk prestasi dalam penyemak imbas? Mar 18, 2025 pm 03:14 PM

Artikel ini membincangkan strategi untuk mengoptimumkan prestasi JavaScript dalam pelayar, memberi tumpuan kepada mengurangkan masa pelaksanaan dan meminimumkan kesan pada kelajuan beban halaman.

Apa yang perlu saya lakukan jika saya menghadapi percetakan kod yang dihiasi untuk resit kertas terma depan? Apa yang perlu saya lakukan jika saya menghadapi percetakan kod yang dihiasi untuk resit kertas terma depan? Apr 04, 2025 pm 02:42 PM

Soalan dan penyelesaian yang sering ditanya untuk percetakan tiket kertas terma depan dalam pembangunan front-end, percetakan tiket adalah keperluan umum. Walau bagaimanapun, banyak pemaju sedang melaksanakan ...

Bagaimanakah saya boleh debug kod javascript dengan berkesan menggunakan alat pemaju pelayar? Bagaimanakah saya boleh debug kod javascript dengan berkesan menggunakan alat pemaju pelayar? Mar 18, 2025 pm 03:16 PM

Artikel ini membincangkan debugging JavaScript yang berkesan menggunakan alat pemaju pelayar, memberi tumpuan kepada menetapkan titik putus, menggunakan konsol, dan menganalisis prestasi.

Siapa yang dibayar lebih banyak Python atau JavaScript? Siapa yang dibayar lebih banyak Python atau JavaScript? Apr 04, 2025 am 12:09 AM

Tidak ada gaji mutlak untuk pemaju Python dan JavaScript, bergantung kepada kemahiran dan keperluan industri. 1. Python boleh dibayar lebih banyak dalam sains data dan pembelajaran mesin. 2. JavaScript mempunyai permintaan yang besar dalam perkembangan depan dan stack penuh, dan gajinya juga cukup besar. 3. Faktor mempengaruhi termasuk pengalaman, lokasi geografi, saiz syarikat dan kemahiran khusus.

Bagaimanakah saya menggunakan peta sumber untuk debug kod JavaScript minified? Bagaimanakah saya menggunakan peta sumber untuk debug kod JavaScript minified? Mar 18, 2025 pm 03:17 PM

Artikel ini menerangkan cara menggunakan peta sumber untuk debug JavaScript minifikasi dengan memetakannya kembali ke kod asal. Ia membincangkan membolehkan peta sumber, menetapkan titik putus, dan menggunakan alat seperti Chrome Devtools dan Webpack.

Bagaimana untuk menggabungkan elemen array dengan ID yang sama ke dalam satu objek menggunakan JavaScript? Bagaimana untuk menggabungkan elemen array dengan ID yang sama ke dalam satu objek menggunakan JavaScript? Apr 04, 2025 pm 05:09 PM

Bagaimana cara menggabungkan elemen array dengan ID yang sama ke dalam satu objek dalam JavaScript? Semasa memproses data, kita sering menghadapi keperluan untuk mempunyai id yang sama ...

Perbezaan dalam Konsol.Log Output Result: Mengapa kedua -dua panggilan berbeza? Perbezaan dalam Konsol.Log Output Result: Mengapa kedua -dua panggilan berbeza? Apr 04, 2025 pm 05:12 PM

Perbincangan mendalam mengenai punca-punca utama perbezaan dalam output konsol.log. Artikel ini akan menganalisis perbezaan hasil output fungsi Console.log dalam sekeping kod dan menerangkan sebab -sebab di belakangnya. � ...

See all articles