Why write this article?
Recently the company made a lot of fancy H5 activity, it is not difficult to H5 page actually each front end can write, but in detail has a lot of front-end detail is not so perfect, perfect the H5 page do actually, fit perfect is also a very difficult thing, at least I think so), we summarized below under those things about H5 adaptation
instructions
To better understand this article, you can first read why we often say 1px instead of 2px to get a basic understanding of the concepts of device-independent pixels, CSS pixels, logical pixels, and device pixel ratios
This article is adapted to a series of articles
Universal solutions
Before the study, we can see how big factories are adapting H5
taobao
Address: main.m.taobao.com/
Solution: Flexible
Analysis: It is worth talking about that although Flexible is a solution for mobile terminal adaptation of Taobao team, but mobile Taobao does not seem to use this solution, you can see the following several pictures to draw a conclusion
We are now changing the phone model
It can be found that other people’s adaptation unit is directly px without rem, but the value of PX is calculated through the different dynamics of the mobile phone screen, so when we change the size of Apple, the website will refresh the dynamic calculation of the corresponding PX value, so as to achieve the purpose of adaptation
Just go into a Taobao inside page, found that the use of the adaptation scheme is VW
jingdong
Address: m.jd.com/ solution :rem
Analysis: the adaptation of JINGdong is rough and directMedia queries change the root font size of HTMLThen use therem
ADAPTS
Bytes to beat
Address: job.bytedance.com/campus/m/po…
Solution: responsive. Js
I think responsive. Js and Flexible. Js of Taobao are essentially the same thing, both dynamically change the FONT size of HTML and then use REM to adapt
Adaptation to summarize
Through the products of these big factories, we can conclude that there are three solutions for mobile terminal adaptation
- Rem (Mainstream)
- Vw/VH (part)
- Direct PX (scene)
So? Is this the end of the article? 😶 This is actually just the beginning of our dry goods for today
Tell me aboutFlexible
Flexible, as the originator of mobile terminal adaptation, is of great research value. And now many mobile terminal H5 are using this scheme for adaptation. Today we will learn its principle
0.3.2 version
The Flexible adaptation principle of this version is to use meta tags to change the scale of the page to achieve the purpose of adaptation. At the same time, this solution can also solve the 1px problem
(function(win, lib) {
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {});
// If the
property has been set, it is based on the currently set property
if (metaEl) {
var match = metaEl
.getAttribute("content")
.match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1/ scale); }}else if (flexibleEl) {
/ / same as above
var content = flexibleEl.getAttribute("content");
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2)); }}}if(! dpr && ! scale) {// This is the core code for Flexible
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// For iOS, use the double solution for 2 and 3 screens, and use the double solution for the rest
if (devicePixelRatio >= 3&& (! dpr || dpr >=3)) {
dpr = 3;
} else if (devicePixelRatio >= 2&& (! dpr || dpr >=2)) {
dpr = 2;
} else {
dpr = 1; }}else {
// For other devices, still use the double solution
dpr = 1;
}
// Scale
according to the DPR tag of the current device
scale = 1 / dpr;
}
docEl.setAttribute("data-dpr", dpr);
// Set the
attribute automatically according to the current DPR
if(! metaEl) { metaEl = doc.createElement("meta");
metaEl.setAttribute("name"."viewport");
metaEl.setAttribute(
"content"."initial-scale=" +
scale +
", maximum-scale=" +
scale +
", minimum-scale=" +
scale +
", user-scalable=no"
);
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement("div"); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); }}function refreshRem() {
// Compatible with iPad and other devices
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
// Divide the screen into 10 equal parts and set the fontSize
var rem = width / 10;
docEl.style.fontSize = rem + "px";
flexible.rem = win.rem = rem;
}
win.addEventListener(
"resize".function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
},
false
);
win.addEventListener(
"pageshow".function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300); }},false
);
// Set font 12 * DPR
if (doc.readyState === "complete") {
doc.body.style.fontSize = 12 * dpr + "px";
} else {
doc.addEventListener(
"DOMContentLoaded".function(e) {
doc.body.style.fontSize = 12 * dpr + "px";
},
false
);
}
refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
// Utility functions
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.rem;
if (typeof d === "string" && d.match(/rem$/)) {
val += "px";
}
return val;
};
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.rem;
if (typeof d === "string" && d.match(/px$/)) {
val += "rem";
}
returnval; }; }) (window.window["lib"] | | (window["lib"] = {}));
Copy the code
The adaptation effect is as follows
We can easily see from the source code how to calculate the scale of data-dPR, HTML,body and meta
So let’s just briefly look at the calculation of DPR
if (isIPhone) {
// For iOS, use the double solution for 2 and 3 screens, and use the double solution for the rest
if (devicePixelRatio >= 3&& (! dpr || dpr >=3)) {
dpr = 3;
} else if (devicePixelRatio >= 2&& (! dpr || dpr >=2)) {
dpr = 2;
} else {
dpr = 1; }}else {
// For other devices, still use the double solution
dpr = 1;
}
Copy the code
You can see that in this version, only ios DPR is processed, for Android models are the default DPR = 1, obviously this processing is a little unreasonable
For the
tag, you can read a newspaper (the page content is 750px wide) through a frame (375px width of the phone screen). If the frame is close to the newspaper, you can only see the content in the frame area. In order to see all the content, Flexible means that after doing the above things, we can write the size according to the design draft. It will not help us divide the corresponding MULTIPLE of DPR, but it will help us to pull the viewport away to 1/ DPR
Flexible - 2.0 -
– in version 2.0, the viewport zoom has been removed, and the 0.5px judgment has been added.
(function flexible(window.document) {
var docEl = document.documentElement;
var dpr = window.devicePixelRatio || 1;
// Set the body font
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + 'px';
} else {
document.addEventListener('DOMContentLoaded', setBodyFontSize);
}
}
setBodyFontSize();
// Set rem reference value
function setRemUnit() {
var rem = docEl.clientWidth / 10;
docEl.style.fontSize = rem + 'px';
}
setRemUnit();
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit);
window.addEventListener('pageshow'.function (e) {
if(e.persisted) { setRemUnit(); }});/ / detect 0.5 px supports
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);
Copy the code
Let’s look at the treatment of the 0.5px problem
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);
}
Copy the code
If the device does not support 0.5px, add a class named hairlines above the body, so that our code can be written like this
/* DPR =1 */
.line{
border:1px solid red;
}
/* DPR >=2 and support 0.5px */
.hairlines .line{
border:0.5 px. solid red;
}
Copy the code
But there are two problems with this
- For those who
DPR >2 and 0.5px is not supported
Android, how do we unify it? - if
dpr=3
thenborder
It should be0.3333 px.
Rather than0.5 px.
Now, butflexible
Let’s use one for each of these caseshairlines
Contains the
It seems that Flexible is not perfect, but we can’t deny that flexible is perfect. Let’s get rid of the 1px problem
Tell me aboutvw/vh
Personally, I think vw adaptation principle is the same as Flexible, which is a split window, but one is divided into 10 and the other into 100
We will explain vw in detail when we use it in the next chapter
How to solve1px
The problem
As I mentioned in my article why 1px is a problem and not a 2px problem,1px is not a problem when it comes to UI requirements. There are often more important bugs to work on projects than 1px, but understanding the nature of 1px can help us understand how mobile adaptation works
solution
Since one CSS pixel represents two physical pixels and the device doesn’t recognize 0.5px, draw 1px and then try to cut the line width in half. Based on this thinking, we have the following solutions
Image method and background gradient
For example, make a 2px image where 1px is the color we want and 1px is transparent. The adaptation process is as follows
Scaling law
This is also the adaptation scheme used by Flexible 0.3.2. We can change the code a little bit
if(! dpr && ! scale) {var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
// For 2 and 3 screens, use 2x scheme, and for the rest, use 1x scheme
if (devicePixelRatio >= 3&& (! dpr || dpr >=3)) {
dpr = 3;
} else if (devicePixelRatio >= 2&& (! dpr || dpr >=2)) {
dpr = 2;
} else {
dpr = 1;
}
// Scale
according to the DPR tag of the current device
scale = 1 / dpr;
}
Copy the code
The principle is also very simple, according to the corresponding DPR to adjust the corresponding scaling, so as to achieve the purpose of adaptation, direct scaling of the page feels a little violent
Use pseudo-element scaling
It’s too violent to scale the whole page, can you just scale the borders? The answer is yes we have transform: scale, right
.border1px{
position: relative;
&::after{
position: absolute;
content: ' ';
background-color: #ddd;
display: block;
width: 100%;
height: 1px;
transform: scale(1.0.5); /* Scale */
top: 0;
left: 0; }}Copy the code
conclusion
This article mainly explains the common mobile terminal adaptation and 1px solutions, this chapter mainly talks about the theory, the next chapter we will draw the best practice of mobile terminal adaptation based on actual combat, if you are interested, remember to click 💓