background

  1. Develop mobile TERMINAL H5 page
  2. Faced with mobile phones of different resolutions
  3. Facing phones with different screen sizes

Visual draft

Before front-end development, the visual MM gives us a PSD file called the visual draft.

For mobile development, in order to achieve the effect of page hd, visual draft specifications tend to follow the following two points:

  1. First, pick a phoneWide screen highAs aThe benchmark(it used to be an iphone4320 x 480Now it’s more iphone6375 x 667).
  2. For Retina screens (e.g. DPR =2), the canvas size of the artwork will beThe benchmarkthe2 times, that is, the number of pixels is the same as before4 times(for the iphone6:375×667 will be 750×1334).

Question:

  1. For phones with DPR =2, why canvas sizeX 2Will solve the HD problem?
  2. For 2x size visuals, how do I restore each block in the specific CSS codeReal wide high(aka layout)?

With questions, look down…

Some of the concepts

The following key basic concepts (terms) need to be known prior to the detailed analysis.

Physical Pixel

A physical pixel is the smallest physical display unit on the display (phone screen), and each device pixel has its own color value and brightness value under the scheduling of the operating system.

Density independent Pixel

A device-independent pixel (also known as a density-independent pixel) can be thought of as a point in a computer coordinate system that represents a virtual pixel (such as a CSS pixel) that can be used by a program and then converted into a physical pixel by the relevant system.

So, there is a correspondence between physical pixels and device-independent pixels, which is the device pixel ratio.

Device Pixel Ratio

Device pixel ratio (DPR for short) defines the corresponding relationship between physical pixels and device independent pixels, and its value can be obtained according to the following formula:

Device pixel ratio = physical pixels/device-independent pixels // in a certain direction, x or YCopy the code

In javascript, you can get the DPR of the current device using window.devicepixelRatio.

In the CSS, media query can be performed using -webkit-device-pixel-ratio, -webkit-min-device-pixel-ratio, or -webkit-max-device-pixel-ratio. For devices with different DPR, Do some style adaptation (for webKit-kernel browsers and WebViews only).

Synthesize the above concepts and illustrate them with examples:

Take the iphone6 for example:

  1. The width and height of the device is375 x 667, can be understood as device-independent pixels (or CSS pixels).
  2. DPR is 2, and according to the formula above, its physical pixels shouldX 2for750 x 1334.

Here’s a picture, like this (forgive my stealing picture) :

As you can see in the figure above, for CSS styles like this:

width: 2px;
height: 2px;Copy the code

The physical size of CSS pixels is the same on different screens (normal vs Retina), but the number of physical pixels per CSS pixel is not the same.

On a normal screen, one CSS pixel corresponds to one physical pixel (1:1). For Retina display, 1 CSS pixel corresponds to 4 physical pixels (1:4).

Bitmap pixel

A bitmap pixel is the smallest data unit of a raster image (e.g. PNG, JPG, GIF, etc.). Each bitmap pixel contains its own display information (e.g. display position, color value, transparency, etc.).

And that’s where I’m going to talk about, what’s the display of images with retina?

In theory, every bitmap pixel corresponds to every physical pixel, so that the image can be displayed perfectly and clearly.

On a normal screen this is fine, but on a Retina screen the bitmap doesn’t have enough pixels to blur the image.

Here’s a picture:

For the Retina screen with DPR =2, one bitmap pixel corresponds to four physical pixels. Since a single bitmap pixel cannot be further divided, the color can only be taken nearby, resulting in blurred images (note the above color values).

So, a good solution for image hd is to double the image (@2x).

For example: 200×300(CSS Pixel) IMG tag, need to provide 400×600 image.

The result is 4 times the number of bitmap pixels. On retina display, the number of bitmap pixels is 1:1 to the number of physical pixels, and the image is clear. .

So there’s another question, what happens if I have twice as many images on a normal screen?

Obviously, on the normal screen, the number of physical pixels corresponding to the 200×300(CSS pixel) IMG tag is 200×300, while the number of bitmap pixels corresponding to the double image is 200×300*4, so there will be 4 bitmap pixels corresponding to one physical pixel. Therefore, its color selection can only be carried out by certain algorithms (the display result is one quarter of the total number of pixels of the original image, which is called downsampling). Although the image will not be blurred to the naked eye, it will be perceived to lack some sharpness or have a little color difference (which is still acceptable).

Represented by a picture:

For the above two problems, I made a demo(Intranet access) crazy poke here.

In demo, 100×100 images are placed in 100×100, 50×50 and 25×25 IMG containers respectively, and the display effect under the Retina screen is shown.

In the bar chart, you can actually see the difference in the value of boundary pixels through a magnifying glass:

  • In Figure 1, when the color is nearby, the color value is between red and white, which is too light, and the picture will look blurred (it can be understood as picture stretching).
  • In Figure 2, the color value is either red or white without the nearest color, so the image looks very clear.
  • FIG. 3, nearby color, color value between red and white, heavy, the picture looks chromatic aberration, lack of sharpness (can be understood as picture extrusion).

You can distinguish between blurred and clear images by looking at the word “love”.

(PS: If it doesn’t look obvious, you can scan the web (Intranet address) with your mobile phone or click on the original picture to get a clearer view.

A few questions

Here are a few classic problems encountered in the development of mobile TERMINAL H5 with different resolutions and screens.

With Retina, the picture has hd issues

The solution to this problem was described above: double the image (@2x) and shrink the image container by 50%.

Such as: picture size, 400×600;

1. The img tags

width: 200px;
height: 300px;Copy the code

2. Background image

width: 200px;
height: 300px;
background-image: url([email protected]);
background-size: 200px 300px; // 或者: background-size: contain;Copy the code

Such disadvantages are obvious under ordinary screens:

  1. Also downloaded @2x pictures, resulting in a waste of resources.
  2. The image will lose some sharpness (or color difference) due to downsampling.

So the best solution is to load images of different sizes under different DPR.

Whether it is through CSS media query, or through javascript conditional judgment is ok.

So the question is, in this case, is not to prepare two sets of pictures? (@ 1 x and @ 2 x)

I think the best companies have an image server that takes the parameters from the URL and can control the quality of the image and crop the image to different sizes.

So we only need to upload the large image (@2x), the rest of the small image to the image server processing, we only need to be responsible for the URL Mosaic.

For example, this is the original picture:

HTTP: / / https://img.alicdn.com/tps/TB1AGMmIpXXXXafXpXXXXXXXXXX.jpg / / artworkCopy the code

You can crop the image like this:

/ / 200 / / 100 x 100 x 200 https://img.alicdn.com/tps/TB1AGMmIpXXXXafXpXXXXXXXXXX.jpg_200x200.jpg https://img.alicdn.com/tps/TB1AGMmIpXXXXafXpXXXXXXXXXX.jpg_100x100.jpgCopy the code

(PS: of course, clipping is only equal to the original image clipping, to ensure that the picture is clear ~)

Retina, border: 1px problem

This is probably the most sensitive designer, the most concerned about the problem.

First of all, why is there a border: 1px for Retina?

We normally write CSS like border: 1px; Is there a problem with retina display?

First, take a look at the picture below:

The above two pictures show the test effect under iphone3GS (DPR =1) and iphone5(DPR =2) respectively. From the comparison, they are consistent and have no difference for the display of 1px border.

So what’s the advantage of the Retina display, and why does the designer feel the line under the HD screen (right) is thick? Mingming and about the same ~

Here’s a graph (forgive me for stealing it again) :

Above, for a 1 px line, they are in the physical size on the screen (grey area) is the same, different is the smallest physical screen display unit, namely the physical pixels, so for a straight line, the iphone 5 it can display the minimum width of grey areas is actually the red circle in the graph, with CSS, In theory, 0.5px.

So, the designer wanted under Retinaborder: 1px;, is actually 1 physical pixel wide, for CSS, can be consideredBorder: 0.5 px;, this is the smallest unit that can be displayed at Retina (DPR =2).

Unfortunately, not all mobile browsers recognize border: 0.5px; In ios7 and below, on Android and other systems, 0.5px is treated as 0px. How to implement this 0.5px?

The simplest way to do this is like this (element scale) :

.scale{
    position: relative;
}
.scale:after{
    content:"";
    position: absolute;
    bottom:0px;
    left:0px;
    right:0px;
    border-bottom:1px solid #ddd;
    -webkit-transform:scaleY(.5);
    -webkit-transform-origin:0 0;
}Copy the code

We’ll write border-bottom: 1px solid # DDD as usual; Transform: scaleY(.5) is scaled down by 0.5 times to achieve the effect of 0.5px. However, this hack is not universal enough (e.g., rounded corners, etc.) and is also difficult to write.

Of course, there are many other hack methods, which can be searched on the Internet, but each has its own advantages and disadvantages. The scheme recommended here is page scale, which is relatively universal and can meet almost all scenarios.

For iphone5(DPR =2) add the following meta tag and set viewport(scale 0.5) :

Copy the code

Thus, all border: 1px on the page will be reduced by 0.5 to border: 0.5px; The effect.

Some people worry that the page scale will affect the performance, @miaojing did the performance test, see here (Intranet address).

Take a look at the comparison of the effect diagram after implementation (the optimized one is on the right) :

(PS: The picture is compressed, it may not look obvious, you can scan the code with your phone or click here (Intranet address) for comparison.)

Page scale, however, inevitably brings some problems:

  1. The font size will be scaled
  2. The page layout will be scaled (e.g., div width and height)

These two questions will come later…

The multi-screen adaptation layout is faulty

Mobile terminal layout, in order to adapt to a variety of large-screen phones, the best solution is to use the relative unit REM.

Based on rem principle, what we need to do is to dynamically change the font size (reference value) of the root HTML for different phone screen sizes and DPR.

Here we extract a formula (REM is the reference value)

rem = document.documentElement.clientWidth * dpr / 10Copy the code

Description:

  1. Multiply by DPR because the page has the potential to implement1px borderThe page is scaled by 1/ DPR times (if not, DPR =1),.
  2. Divide by 10, just to round it up, so it can be anything.

So an HTML font size might look like this:

iphone3gs: 320px / 10 = 32px

iphone4/5: 320px * 2 / 10 = 64px

iphone6: 375px * 2 / 10 = 75px

To dynamically change the font size of the root node’S HTML, we can do this using CSS or javascript.

Font-size: 16px; “> < span style =” font-size: 16px;

html{font-size: 32px; } //iphone 6 @media (min-device-width : 375px) { html{font-size: 64px; } } // iphone6 plus @media (min-device-width : 414px) { html{font-size: 75px; }} * /Copy the code

Disadvantages: It is not accurate to dynamically change rem reference values through media queries such as device width range. For example: 360px and 320px phones will be treated the same (same REM base) because their screens are in the same range (<375px), but in fact their screens are not the same width and their layouts should be different. In the end, the conclusion was that it wasn’t precise enough, but it worked. < p=””>

Javascript, using the above formula, calculates the reference value REM, and then writes the style, something like this (code reference from KIMi’s M-base module)

var dpr, rem, scale; var docEl = document.documentElement; var fontEl = document.createElement('style'); var metaEl = document.querySelector('meta[name="viewport"]'); dpr = window.devicePixelRatio || 1; rem = docEl.clientWidth * dpr / 10; scale = 1 / dpr; // Set viewPort to zoom, Metael.setattribute ('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no'); // Set the data-dpr attribute and use docel. setAttribute('data-dpr', DPR) for CSS hacks; / / dynamic writing style docEl. FirstElementChild. The appendChild (fontEl); fontEl.innerHTML = 'html{font-size:' + rem + 'px! important; } '; Rem2px = function(v) {v = parseFloat(v); // Window.rem2px = function(v) {v = parseFloat(v); return v * rem; }; window.px2rem = function(v) { v = parseFloat(v); return v / rem; }; window.dpr = dpr; window.rem = rem;Copy the code

In this way, you can accurately calculate the rem reference values for different screens. The disadvantage is that you need to load such a piece of JS code, but I think this is the best solution so far.

Because this solution solves three problems simultaneously:

  1. Border: 1 px problem
  2. Image hd problem
  3. Screen adaptation layout problem

When it comes to layout, it’s natural to answer the original question: How do I restore the true width and height of visual art in CSS coding?

Prerequisites:

  1. I got a hd visual for the iphone6750 x 1334
  2. Use the above hd scheme (JS code).

If you have a div that is 750×300px in width and height measured in a PSD file, how do you convert it into REM units?

The formula is as follows:

Rem = PX/reference value;Copy the code

For an iphone6 visual, the baseline value is 75(mentioned earlier);

So, after determining the visual draft (i.e. the baseline value), we usually write a mixin with less, like this:

// For example:.px2rem(height, 80); .px2rem(@name, @px){ @{name}: @px / 75 * 1rem; }Copy the code

So for div 750×300px, we’ll write less like this:

.px2rem(width, 750);
.px2rem(height, 300);Copy the code

Convert to HTML, like this:

width: 10rem; // -> 750px
height: 4rem; // -> 300pxCopy the code

Finally, since the DPR is 2 and the page scale is 0.5, the actual width and height displayed on the screen should be 375×150px, which is just fine.

If the page does not have Scale 0.5, our code would look like this:

.px2rem(width, 375);
.px2rem(height, 150);Copy the code

This width and height is what we usually get:

  1. will750 x 1334Visual draft into375 x 667Then measure the size of the block (feeling silly).
  2. in750 x 1334After measuring the width of the block to 750×300px, divide by 2.

Finally, a comparison of no layout adaptation (above) and REM layout adaptation (below) is given:

(iphone3gs, iphone5, iphone6)

Obviously, the width and height of each area adapted by REM will change with the width of the phone screen. The most obvious part is the list of pictures. The last picture has only a little visual requirement, and the REM layout is displayed well under any screen.

Font size

Since the above scheme will make the page scale, for the width and height of the page block, we can rely on hd visual copy, because the visual copy is ×2, we can directly measure, then how to deal with the font?

For font scaling, the original requirement of the designer is as follows: the font size should be uniform on any mobile phone screen, so we will do the following for different resolutions (DPR is different) :

font-size: 16px;
[data-dpr="2"] input {
  font-size: 32px;
}Copy the code

(Note that rem font cannot be used, the error is too large and cannot satisfy any of the same font sizes under screen)

For convenience, we’ll also write a mixin with less:

.px2px(@name, @px){ @{name}: round(@px / 2) * 1px; [data-dpr="2"] & { @{name}: @px * 1px; } / / for mx3 [data - DPR = "2.5"] and {@ {name} : round (@ px * 2.5/2) * 1 px; } / / for millet note [data - DPR = "2.75"] and {@ {name} : round (@ px * 2.75/2) * 1 px; } [data - DPR = "3"] & {@ {name} : round (@ px / 2 * 3) * 1 px} / / for samsung note4 [data - DPR = "4"] and {@ {name} : @ px * 2 px; }}Copy the code

(Note: the HTML data-dPR attribute is mentioned in the previous JS scheme, here is useful)

According to experience and testing, there will still be these strange strange fellows of DPR, here to do a unified compatible ~

When used, it looks like this:

.px2px(font-size, 32);Copy the code

Of course, other CSS properties can also be used if they require consistency across different DPR, such as:

.px2px(padding, 20);
.px2px(right, 8);Copy the code

The last

On the mobile terminal H5 HD and multi-screen adaptation of some scheme summary, and knowledge explanation, wrong place, please also point out.

Refer to the article

  1. www.smashingmagazine.com/2012/08/20/…
  2. www.paintcodeapp.com/news/iphone…
  3. www.inserthtml.com/2012/09/des…
  4. Iconmoon.com/blog2/iphon…
  5. Dieulot.net/css-retina-…