This article is mainly aimed at beginners of mobile web development readers, the author is also a beginner, there are many misnomers in the article look for readers to correct.
preface
From the beginning of web app development to now, there has been a vague concept of mobile terminal size adaptation. Could say to the media query, rasterize layout, some technical term such as’ fluid layout and the way of implementation, but every time you do a web app development, make product is always unsatisfactory, such as text overflow on the iphone 5, adjust good layout in small size found on mobile location is wrong, It’s masking other elements, or it’s wrapping lines.
If it was before, I did it like this:
Keep writing media queries for compatibility until PM or QA is satisfied.
Such a method has the following problems:
- It’s hard to fit all phone screen sizes. There will always be incompatible sizes. The problem is still there, it’s just not discovered yet.
- It’s so tired. it’s so exhausting. In particular, these problems will generally be concentrated in the online before being put forward, and that time is the greatest pressure.
I thought about why there would be a case of treating the symptoms but not the root cause:
- Did not coordinate the specification with the UI at the beginning of the project.
- There are not too many test machines around, can not test too comprehensive.
- Not realizing that mobile adaptation is a tricky issue.
So, is there one of thoseOnce and for all
.Full size support
.It's a no-brainer
Mobile terminal size adaptation scheme?
** Of course there is. ** The author combined with their own read a few popular blogs, summed up a few useful knowledge points, hoping to let readers quickly grasp and use this’ once and for all method ‘. Be lazy when you can be lazy. 🐷 (a popular blog title with flexible Github Repo shown here)
What we’re trying to achieve
- Develop directly from the dimensions above the UI annotated visual draft. As indicated
230px
, which is converted by a functionrem
You don’t have to do it by hand. - The page looks the same visually on most phones.
What is a rem
In short: if the < HTML > tag is set to font-size:16px, then 1rem = 16px. So:
Collaboration with UI
First, I need to say a word to UI:
“Mark elements as 750px by 1334px.”
So, what you’ll get is an annotated image like this:
【 Core 】 Dynamic calculation + REM
At this point, we still haven’t addressed the core issue:
- You have to convert px into REM yourself. (Probably with a calculator next to it)
- Full size fit.
Next, is the most core link, the author through the step diagram to restore the calculation process.
Step 1: Suppose there are three phones with different lengths and widths.
Step 2: Divide the width of the phone into 10 pieces, so each of the above three phones is 35px/36px/37px wide. And add a different font size to the < HTML > tag.
That is: one 35px/36px/37px
Step 3: Calculate the corresponding REM according to the PX annotation diagram of UI:
Step 4: REM will convert it into different px sizes and present it on different mobile phones: (ps: The division result in the picture is wrong)
In this way, you can have the same display effect on different sizes of phones. And the cool part is that this whole process is auto-adaptive. Instead of winking at Chrome Devtools and trying to debug it, developers can just write minustily from the UI annotations.
Code implementation
Dividing the width of the phone into 10 pieces, the width of each of these three phones is 35px/36px/37px. And add a different font size to the < HTML > tag.
Use JavaScript to dynamically calculate the current screen width, cut it into 10 pieces and set the fontSize of < HTML > to 1 unit width.
document.addEventListener('DOMContentLoaded'.function(e) {
document.getElementsByTagName('html') [0].style.fontSize = window.innerWidth / 10 + 'px';
}, false);
Copy the code
The DOMContentLoaded event is fired after the initial HTML document has been fully loaded and parsed, without waiting for the stylesheet, images, and subframes to complete loading. A different event, Load, should only be used to detect a fully loaded page. MDN::DOMContentLoaded
Calculate the corresponding REM according to the PX annotation diagram of UI
This step requires you to define a px2rem utility function using Sass:
// utils.scss
@function px2rem($px) {$rem : 75px; // '750/10': divided into 10 parts
@return ($px/$rem) + rem;
}
// foo.scss
.box1 {
width: px2rem(320px); // '(320/750) * 10 = 4.266rem'
}
Copy the code
So what we actually have in our styleSheet is a height of 4.266rem, and how many pixels corresponds to 1rem is precalculated by the JavaScript code above based on the different window. InnerWidth. So auto-adaptation is implemented.
If you don’t want to write px2rem(), you can define the function simply.
Can’t get around viewport and DPR
At the beginning of this blog post, I tried to steer clear of the abstract concepts of viewport and DPR, because it already addresses most problems in one dimension. But if you want to do it better, you have to start from another dimension, and that dimension is DPR.
First, distinguish two concepts:
- The device’s pixels
- CSS pixels
Here’s a scenario
A front end engineer typed it out
.box {
width: 100px;
height:100px;
}
Copy the code
So in this case, he means that the actual size of the box on our screen is 100px by 100px, and here’s what he has in mind:
After the project went live, one user ‘maliciously’ used the magnifying glass function to double the width and length of the project, which now looks like this:
You’ll notice that it takes the Device 200px width and width to render the 100px width and width defined in the CSS. The Ratio of the Device pixels to the style pixels is called the DPR, which is the Device Pixel Ratio. If you still have questions about this concept, see the Viewport analysis.
We all know about Retina displays. The reason they look so high definition is that apple devices take two pixels to render one pixel object, so they must look more refined.
So, if we’re targetingdpr=1
Writing therem2px(100px)
And so ondpr=2
The device will look like a 2x magnified element.
So, if we can query the DPR of the current device and do the corresponding scaling, we can solve this problem.
For example: Some Android devices have a DPR =1, but the UI uses a DPR =2 to create the image, like 750px * 1334px. Elements written directly as 750px by 1334px will be twice as large, so we will make the page twice smaller, how to control?
In the viewport
In short, we’re using viewport here to control the zoom of the screen.
var dpr = window.devicePixelRatio;
meta.setAttribute('content'.'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
// To help understand if DPR =2, it means that I wrote 100px and rendered it to 200px, so I need to shrink it to 1/2, or 1/ DPR
Copy the code
It’s also worth mentioning that the UI is usually designed at 750px by 1334px because it makes the design more detailed. For example, if we write rem2px(375px), then we will go through the following process to convert the device pixels width of the phone 390px and DPR =3.
rem2px(375px)
—->5rem
5rem
—–>195px (Style Pixels)
Style 195 px
——> Now it seems to have pixels195*3 = 585px
The length of theSet the DPR = 1/3
——-> At this point it looks like only195px
In this way, we complete the adaptation from the DPR dimension.
Show me the code:
<script>
var dpr = window.devicePixelRatio;
var meta = document.createElement('meta');
// dpr
meta.setAttribute('content'.'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
document.getElementsByTagName('head')[0].appendChild(meta);
// rem
document.addEventListener('DOMContentLoaded'.function (e) {
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
}, false);
</script>
Copy the code
To prevent global variables from contaminating or overwriting others’ variables, encapsulate them into modules and reuse them.
One More Thing
In the process of writing this blog, I was struggling with the problem that the REM layout and percentage layout felt the same because the REM layout was based on cutting the width to 10 pieces, like 1REM = 10% = 10vw. At one point, I thought I could use percentage layouts. It turns out that if the boxes are nested (which happens a lot), the percentage layout is a problem because the reference frame for the percentage is the parent element, so if we define the 10% width of the child box, we are referring to the parent box instead of the 10% we want for the entire window. InnerWidth. Vw’s code maintainability is not as good as the above scheme, and its compatibility is not as good as REM’s (the difference is not too great).
For more information on PC or mobile layouts, see resources & Credits.
Resources & Thanks
Mobile page adaptation solution
Use Flexible to realize terminal adaptation of H5 page
An introduction to the six layouts + REM layout
DOMContentLoaded vs. Load
How is REM achieved
AlloyTeam Mobile Web adapter
Viewport analysis
lib-flexible