機型 | 邏輯像素 | 物理像素 | Scale Factor |
---|---|---|---|
iphone 3GS | 320 x 480 | 320 x 480 | 1x |
iphone 4 | 320 x 480 | 640 x 960 | 2x |
iphone 4S | 320 x 480 | 640 x 960 | 2x |
iphone 5 | 320 x 568 | 640 x 1136 | 2x |
iphone 5C | 320 x 568 | 640 x 1136 | 2x |
iphone 5S | 320 x 568 | 640 x 1136 | 2x |
iphone 5SE | 320 x 568 | 640 x 1136 | 2x |
iphone 6 | 375 x 667 | 750 x 1134 | 2x |
iphone 6P | 414 x 736 | 1080 x 1920 | 2.6x |
iphone 6S | 375 x 667 | 750 x 1134 | 2x |
iphone 6SP | 414 x 736 | 1080 x 1920 | 2.6x |
iphone 7 | 375 x 667 | 750 x 1134 | 2x |
iphone 7P | 414 x 736 | 1080 x 1920 | 2.6x |
the visual viewport是在屏幕上顯示頁面的一部分,用戶能夠滾動以更改他看到的頁面部分,或者縮放以更改可視視口的大小
css
the visual viewport的大小等於window.innerWidth/Heighthtml
css佈局尤爲是百分比寬是相對於the layout viewport來計算的,the layout viewport比the visual viewport寬的多。
瀏覽器會控制layout viewport尺寸使其在徹底縮小的狀況下覆蓋整個屏幕,這時the visual viewport=the layout viewport
react
所以,the layout viewport的寬度和高度等於在最大縮小模式下能夠在屏幕上顯示的任何寬度和高度。當用戶放大這些尺寸時保持不變。
webpack
the layout viewport的大小等於document.documentElement.clientWidth/Heightgit
它爲每一個設備上的web頁面提供了一個理想尺寸,每一個設備的理想尺寸都會不一樣。在非Retina屏的時代,the ideal viewport等於物理像素數,但這不是必須的。具備高物理像素密度的新型設備任然保留了原有的ideal viewport,由於它很是適合設備。
4S以上版本包含4S,iPhone理想的視口是320x480,不管它是否有視網膜屏幕。那是由於320x480是這些iPhone上web頁面的理想尺寸。github
關於ideal viewport有兩點很關鍵:web
meta viewport標籤包含有關視口(viewports)和縮放(zooming)的瀏覽器指令。特別是,它容許Web開發人員設置layout viewport的寬度,這個寬度直接影響到width:20%這樣的css聲明的計算npm
meta viewport標籤具備如下語法:json
<meta name="viewport" content="name=value,name=value">
viewport mata標籤的每一對name/value都是一條指令。總共有6條指令:瀏覽器
width指令有一個特殊的值:device-width。它能將layout viewport的寬度設置成ideal viewport寬度。 理論上一樣有一個相似的device-height值,但實際上這個值並不起做用。
縮放是棘手的。理論上講很簡單:肯定用戶能夠放大或縮小的縮放係數(zoom factor)。這裏存在兩個問題:
所以關於縮放這個名字的問題,縮放其實是比例,而viewport meta的指令稱之爲initial-scale、minimum-scale、maximum-scale。其它瀏覽器爲了保持和針對iPhone適配的網站兼容也只好被迫實現了這些指令。
這三個指令指望一個縮放因子,例如2意味着「縮放到ideal viewport寬度的200%」
visual viewport width = ideal viewport width / zoom factor zoom factor = ideal viewport width / visual viewport width
這裏以手機拍照爲例,用手機後置攝像頭拍攝電腦上的一個網頁,調整手機與電腦之間的距離使得整個頁面恰好拍進手機裏,可是網頁變小了,這時layout viewport=visual viewport,這種狀況就叫作徹底縮小
縮放係數,若是我想讓網頁變大,調近手機與電腦之間的距離,這時網頁變大了,可是網頁看不全了也就是可視區域變小了;同理我想讓網頁變小,那麼調遠手機與電腦之間的距離,這時網頁變小了,可是網頁能看到的東西多了,也就是可視區域變大了
使用rem做爲移動端尺寸單位替代px,那麼1rem=?px
目前1rem有三種方案:
若是項目中使用的是1rem=16px,又集成了antd-mobile,那麼就會致使antd-mobile中的組件特別小,這就面臨着方案轉換的問題,若是咱們在項目的樣式中以rem做爲單位,如今是16px轉100px,若是之後用75px那麼全部的樣式文件中rem就都須要進行轉換工程量很大。因此,樣式文件中咱們還使用px做爲單位,而後使用插件將px轉成rem,這樣就算有方案轉換,咱們也只須要修改插件中的配置和一些腳本文件
'use strict'; /** * @param {Number} [baseFontSize = 100] - 基礎fontSize, 默認100px; * @param {Number} [fontscale = 1] - 有的業務但願能放大必定比例的字體; */ const win = window; export default win.flex = (baseFontSize, fontscale) => { const _baseFontSize = baseFontSize || 100; const _fontscale = fontscale || 1; const doc = win.document; const ua = navigator.userAgent; const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i); const UCversion = ua.match(/U3\/((\d+|\.){5,})/i); const isUCHd = UCversion && parseInt(UCversion[1].split('.').join(''), 10) >= 80; const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi); let dpr = win.devicePixelRatio || 1; if (!isIos && !(matches && matches[1] > 534) && !isUCHd) { // 若是非iOS, 非Android4.3以上, 非UC內核, 就不執行高清, dpr設爲1; dpr = 1; } const scale = 1 / dpr; let metaEl = doc.querySelector('meta[name="viewport"]'); if (!metaEl) { metaEl = doc.createElement('meta'); metaEl.setAttribute('name', 'viewport'); doc.head.appendChild(metaEl); } metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`); doc.documentElement.style.fontSize = `${_baseFontSize / 2 * dpr * _fontscale}px`; }; flex(100, 1);
代碼理解:以iphone6爲準,dpr=2,scale=1/2,fontSize=100;由以前介紹的viewport能夠知道,scale=1/2那麼visual viewport=2*ideal viewport
"theme": { "hd": "2px", "brand-primary": "red", "color-text-base": "#333" },
npm install react-app-rewire-postcss --save-dev
const { injectBabelPlugin, getLoader } = require('react-app-rewired'); const rewirePostcss = require('react-app-rewire-postcss'); const pxtorem = require('postcss-pxtorem'); const autoprefixer = require('autoprefixer'); const theme = require('./package.json').theme; const fileLoaderMatcher = function (rule) { return rule.loader && rule.loader.indexOf(`file-loader`) != -1; } module.exports = function override(config, env) { // do stuff with the webpack config... config = injectBabelPlugin(['import', { libraryName: 'antd-mobile', // style: 'css', style: true, // use less for customized theme }], config); console.log(config.module.rules[2].oneOf); // sass config.module.rules[2].oneOf.unshift( { test: /\.scss$/, use: [ require.resolve('style-loader'), require.resolve('css-loader'), require.resolve('sass-loader'), { loader: require.resolve('postcss-loader'), options: { // Necessary for external CSS imports to work // https://github.com/facebookincubator/create-react-app/issues/2677 ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }) ], }, } ] } ); //less config.module.rules[2].oneOf.unshift( { test: /\.less$/, use: [ require.resolve('style-loader'), require.resolve('css-loader'), { loader: require.resolve('postcss-loader'), options: { // Necessary for external CSS imports to work // https://github.com/facebookincubator/create-react-app/issues/2677 ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), ], }, }, { loader: require.resolve('less-loader'), options: { // theme vars, also can use theme.js instead of this. modifyVars: theme, }, }, ] } ); config = rewirePostcss(config,{ plugins: () => [ require('postcss-flexbugs-fixes'), require('postcss-preset-env')({ autoprefixer: { flexbox: 'no-2009', }, stage: 3, }), pxtorem({ rootValue: 100, //以100px爲準,不一樣方案修改這裏 propWhiteList: [], }) ], }); // file-loader exclude let l = getLoader(config.module.rules, fileLoaderMatcher); l.exclude.push(/\.scss$/); l.exclude.push(/\.less$/); return config; };
/*src/App.scss*/ .App { text-align: center; .App-Button{ width: 750px; height: 88px; } }
/*src/App.js*/ import React, { Component } from 'react'; import './App.scss'; import {Button} from 'antd-mobile'; class App extends Component { render() { return ( <div className="App"> <Button type='primary' className='App-Button'>{document.documentElement.clientWidth}</Button> </div> ); } } export default App;
能夠看到px已經被轉換成rem了,layout viewport = 750px