Mobile adaptation solutions (REM, Flexible, etc.)
The Necessity of Mobile Adaptation
The fragmentation of mobile device screen sizes is severe, ranging from 320px to 414px and even larger screen widths. Traditional fixed-pixel layouts cannot adapt to this diversity, causing pages to display abnormally on certain devices. The core goal of mobile adaptation is to ensure that pages are displayed reasonably on screens of different sizes while maintaining a consistent visual experience.
Viewport Basics
The foundation of adaptation lies in a correct understanding of the viewport. The default viewport width of mobile browsers is usually larger than the device width, which causes the page to be scaled. The viewport behavior can be controlled via the meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
This setting ensures the viewport width equals the device width, prevents user scaling, and lays the groundwork for subsequent adaptation solutions. Without proper viewport settings, any adaptation solution will fail.
The Principle of REM Adaptation
REM (root em) is a unit relative to the font size of the root element (html). By dynamically calculating the font-size
of the html
element, proportional scaling of page elements can be achieved. The basic formula is:
html font-size = (clientWidth / designWidth) * baseFontSize
Assuming the design width is 750px and the base font size is 100px, on a device with a width of 375px:
document.documentElement.style.fontSize = (375 / 750) * 100 + 'px';
Here, 1rem equals 50px, and all elements using rem units will scale proportionally.
Implementation Details of Flexible.js
Taobao's Flexible solution is a classic implementation of REM adaptation. It addresses issues like 1px borders and high-definition screen adaptation. The core logic is as follows:
(function flexible(window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// Adjust body font size
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
} else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize()
// Set 1rem = viewWidth / 10
function setRemUnit() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// Listen for page resize events
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function(e) {
if (e.persisted) {
setRemUnit()
}
})
// Detect 0.5px support
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
})(window, document)
PostCSS Plugins for Development
Manually calculating rem values is inefficient. PostCSS plugins can automate the conversion:
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 100, // Design width / 10
propList: ['*'],
selectorBlackList: ['.norem'] // Ignore classes starting with 'norem'
}
}
}
This allows writing design dimensions directly in CSS:
.box {
width: 750px; /* Converts to 7.5rem */
height: 200px; /* Converts to 2rem */
}
1px Border Solution
On high-definition screens, 1px physical pixels may correspond to multiple device pixels, making borders appear too thick. The Flexible solution addresses this with transform
scaling:
.border-1px {
position: relative;
}
.border-1px::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #000;
transform: scaleY(0.5);
transform-origin: 0 0;
}
For devices with different dpr
, targeted handling is possible:
[data-dpr="2"] .border-1px::after {
transform: scaleY(0.5);
}
[data-dpr="3"] .border-1px::after {
transform: scaleY(0.333);
}
High-Definition Image Adaptation
Load images of different resolutions based on device dpr
:
<img src="image@2x.png"
srcset="image@1x.png 1x, image@2x.png 2x, image@3x.png 3x">
Or use background images with media queries:
.icon {
background-image: url(image@1x.png);
}
@media (-webkit-min-device-pixel-ratio: 2) {
.icon {
background-image: url(image@2x.png);
background-size: 100% 100%;
}
}
Combining Flex Layout with REM
REM solves sizing issues, while Flex solves layout issues. Combining them yields better results:
.container {
display: flex;
padding: 0.2rem;
}
.item {
flex: 1;
margin: 0.1rem;
height: 1rem;
}
Optimizing Dynamic REM Calculation
Traditional solutions may scale too much on very large screens. Limit the maximum size:
function setRem() {
const designWidth = 750;
const maxWidth = 768;
const clientWidth = Math.min(document.documentElement.clientWidth, maxWidth);
const rem = (clientWidth / designWidth) * 100;
document.documentElement.style.fontSize = rem + 'px';
}
Combining Responsive Layout with REM
Adjust the REM baseline with media queries for finer control:
@media screen and (min-width: 320px) {
html {
font-size: 42.6667px;
}
}
@media screen and (min-width: 360px) {
html {
font-size: 48px;
}
}
Example of a Real-World Project Configuration
Complete webpack configuration example:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-pxtorem')({
rootValue: 75,
propList: ['*'],
minPixelValue: 2
})
]
}
}
}
]
}
]
}
}
Handling Common Issues
Font Size Issues: To prevent text from scaling with REM, use media queries to fix it:
.title {
font-size: 16px;
}
@media (min-width: 375px) {
.title {
font-size: 18px;
}
}
Third-Party Component Adaptation: Some UI libraries use px units. Override them globally:
.third-party-component {
transform: scale(0.5);
transform-origin: 0 0;
}
Comparing Modern CSS Solutions
CSS viewport units (vw/vh) are becoming a new alternative:
html {
font-size: 10vw; /* 10% of viewport width */
}
.box {
width: 7.5rem; /* Equivalent to 75vw */
}
However, compatibility and calculation precision issues must be considered.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:触摸事件与手势识别