Update: Thanks for reminding you in the comments section, I noticed that the use of REM layout ideas was first introduced by Flexible solution from Mobile. Use Flexible to achieve H5 terminal adaptation, and then talk about the adaptation of mobile terminal pages.


It is a common practice to use REM for image cutting adaptation on mobile terminals. Recently, I encountered an interesting compatibility problem in my work. Note this, at the same time combing the ideas of using REM adaptation, and a small skill in using SASS function.

Contrast between REM and EM

Rem and EM are both relative units of CSS based on font size. The difference between em and EM is that em uses the font size of the current element to determine the actual size, while REM uses the font size of the HTML root node.

Using em can be annoying, such as setting the font size of a parent element and a child element, such as 1.2em, assuming that the parent element inherits a font size of 10px and that the parent element has a font size of 12px and the child element has a font size of 14.4px. In a piece of code, the same size may vary from place to place. As you can imagine, if you use EM a lot, it’s easy to make your code confusing and confusing, so programmers don’t use it very often.

Rem, by contrast, shows a certain uniformity. Depending only on the font size of the HTML root node, 2REM anywhere in the code is absolutely twice the size of the root element, without the “surprise” of using EM.

Use rem cut diagrams

This is a simple but useful screen adaptation method. Note that the premise is that the page height is not limited, that is, this adaptation method can only adapt to screen width changes; If you also need to adapt the full screen height, rem alone may not be able to do this.

In simple terms, designers use a certain model size for their drawings, like the iphone6. We cut the image exactly as the pixel size in the design image, and chrome’s device emulator is set to the iphone6 view.

As a result, if you switch to a different width of the phone’s screen, or place the device landscape, the layout will be confusing.

Unit conversion

The next step is to convert all px units into REM units (see below). The default webview HTML font size on iphone6 is 16px, so if an element in your CSS is 32px wide, convert it to 2rem, and so on. The width of the iphone6 screen is 375px, assuming that a div element occupies half the width of the screen, the original CSS is width: 187.5px, so the conversion is width: 11.71875rem, keeping the original size.

However, as you can see, switching to a different screen width does not guarantee that the div will still take up half of the screen width, even though we are using rem layout. For example, Pixel2 in the Chrome Device Emulator is 411px wide, while the default HTML font size is 16px. Rem calculated the actual width is 187.5px, half of the screen width of iphone6, not 205.5px, half of the screen width expected of Pixel2.

The next step is the key to rem adaptation: adjust the font size of the HTML element.

Adjust font size for HTML elements

To switch from the layout on the iphone6 to the Pixel2, the elements need to be scaled up to 411/375. All units are based on REM, that is, on the FONT size of the HTML element. Font-size: 16px “font-size: 16px” font-size: 16px “font-size: 16px” font-size: 16px “font-size: 16px” font-size: 16px “font-size: 16px” font-size: 16px “font-size: 16px”;

So, when the page loads, add the following code:

var count = 23.4375;
document.documentElement.style.fontSize = document.documentElement.clientWidth / count + 'px';
Copy the code

The count in the code is calculated by dividing the screen width of the iphone6 by the default font size: 375/16. That means that with the width of the iphone6 screen, you can fit count of default text.

Pixel2 fontSize = (Pixel2 width/iphone6 width)

Or to put it another way: when you set font size, the screen is wide enough to hold count fonts, so the screen is count REM. If you use 2rem as the element width, then this element takes up 2 / count of the screen, which is the same ratio on any device of any width.

With the change to the default size of HTML, it is theoretically possible to layout with REM units without worry. Any layout you see on the screen is an equal-scale version of the layout on the iphone6.

Finally, bind the window’s resize to the event, and reset the font size when the window size changes. This way, the layout ADAPTS to screen size changes as you rotate the screen.

I’m having compatibility issues

Rem is good, but pay attention to the details of its use. Recently, for example, I encountered a strange phenomenon of layout confusion. It appears in Android hybrid apps, which are embedded webView components in native apps.

This isn’t a 100% recurring problem at first. On some phones, when webView is opened occasionally, the layout of the interface becomes chaotic, as text elements disappear altogether, leaving only images that fill the width of the screen stacked from top to bottom. After careful investigation, we finally locate the problem of the FONT size of the HTML element: it is 0.

Once again, found the problem from the document. The documentElement. ClientWidth.

On some phones, when opening a WebView, the clientWidth of the HTML element is initially retrieved without a value, causing the code to set the HTML font size to 0. So layout error is inevitable. The reason why the image is still visible is because the layout uses a percentage to set the image size, and if rem is also used to set the image size, the image will also disappear.

Although the positioning problem took some work, it was easy to fix, just use compatible writing to get the screen width:

var width = document.documentElement.clientWidth
                || document.body.clientWidth || window.innerWidth;
document.documentElement.style.fontSize = width / count + 'px';
Copy the code

Application of sASS function

We mentioned earlier that we need to convert px units in CSS to REM units. The usual practice is to configure a Loader in webpack, which automatically matches px units during compilation, and then converts them to the specified scale.

In fact, if your project uses SASS (typically written in SCSS, which is closer to the native CSS syntax) instead of CSS, there is a more subtle approach: use the SASS function.

Define the size conversion function as follows:

@function rem($size) {
   @return $size / 16 * 1rem;
}
Copy the code

When used, directly use this function to write the value of PX unit, which can be automatically converted to REM unit:

.foo {
    width: rem(20);
}
Copy the code

Codepen. IO/Jelleverzij…