layout

  • Static layout: fixed width and height layout, does not change with the device and viewport [fixed width center, PC]
  • Flow layout: size change, layout unchanged, width used in percentage and min/ Max, height fixed
  • Adaptive layout: Size changes, body content and layout remain the same, disadvantages, too small screen content is too crowded (size stays the same, position changes)
  • Flexible layout: Size and position can vary (Flex/REM/EM/VW/VH)
  • Responsive layout: Display content, size and location will change, media query + streaming layout (media query, VW, REM/EM)

Relevant concepts

Device Pixels

The physical pixels of a device’s screen, indicating how many dots can be spread on the screen, rather than an absolute unit of length (e.g., in,mm); The units are px, like the iPhone6 (750 x 1334px).

Resolution

A physical concept For a screen, resolution is generally the sum of physical pixels displayed on the screen. For example, let’s say the iPhone6 screen resolution is (750 x 1334px). For images, the concept is equivalent to image size, image size, pixel size, etc. For example, let’s say the icon of (20 x 20px)

CSS Pixels

The concept of Web programming refers to the logical pixels used in CSS style code, or device independent pixels because they are device-specific; One CSS Pixel may correspond to a different number of physical pixels on different devices. This Ratio is the Device’s property (for example, iPhone6:375 x 667px)

Through the document. The documentElement. ClientWidth clientHeight/document. The documentElement. GetBoundingClientRect (). The width

In the CSS specification, units of length can be divided into absolute and relative units. Px is a relative unit, the opposite is Device Pixels.

Device-independent Pixels (DIP)/Density- Independent Pixels (DP)

Android devices are characterized by a large screen size, so in order to make the display as device-independent as possible, dip was proposed, and density was 160.

// if the density of the screen is 160 (ppi/dpi), px === dip px = dip * density //Copy the code

Note: This is only for Android, Windows also has a different meaning, IOS does not seem to exist

Device Pixel Ratio (DPR)

Device pixel ratio, the ratio between physical pixels and logical pixels used by cascading style sheets (CSS): Other names for it are “CSS Pixel Ratio” and “DPPX” means that 1 CSS Pixel (width) equals several physical pixels (width)

DPR = Physical pixel (device pixel)/logical pixel (CSS pixel/device independent pixel) // [unscaled]Copy the code

Pixel density

Pixel density is also called display density or screen density, abbreviated DPI(Dots Per Inch) or PPI(Pixel Per Inch)

SQRT (750*750 + 1334*1334) / 4.7 = 326ppiCopy the code

ViewPort

The viewport width on the desktop is the same as the browser width, but it’s different on the phone.

Layout ViewPort

Mobile phone in order to accommodate the designs for the desktop browser web site, the default layout viewport width greater than the width of the screen, in order to let the user see website, it will narrow web document. DocumentElement. ClientWidth

Visual ViewPort

The visual viewPort width = ideal ViewPort width/the current zoom value can be obtained using window.innerWidth. It is not available correctly on Android 2, Oprea Mini, and UC 8.

Ideal Viewport

Ideal ViewPort is the best viewport for mobile devices, In meta[name=’viewport’], set width = device-width to ideal viewport Otherwise the width defaults to 980 layout viewport

There is no fixed size for the Ideal ViewPort, different devices have different Ideal Viewports. The ideal viewport for all early iphones was 320x480px

So, without scaling, the CSS pixel width of the screen is actually the width of the desired viewport, and the meta tag:

<meta name="viewport" content="Width =device-width, inital-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
Copy the code

Layout viewport = ideal viewport is specified and scaling is disabled. Add the viewport meta width=device-width to make the page larger, which actually makes the layout viewport smaller

Initial-scale =1 (ideal Viewport) for iPhone and iPad when the width is set to portrait. Width =device-width The width of the

Relationship between visual port and ideal port:

Visual ViewPort width = Ideal ViewPort width/Visual ViewPort widthCopy the code

Reference: www.ayqy.net/blog/ fully understand px… Github.com/jawil/blog/…

rem (Font size of the root element)

A unit of relative length. Applied to the root element relative to the initial/default value; Scope non-root elements, relative to the root element HTML font size (common)

em

Font size of the parent, in the case of typographical properties like font-size, and font size of the element itself, in the case of other properties like width. Applies to the font size property, relative to the font size of the parent element (common); Works on non-font size properties, relative to their own font size

The layout scheme

Percentage + media query

mate device-width/width:

  • Device-width is the actual width of the device, which only depends on the resolution of the device. It is usually the ratio of the physical pixel of the device to the pixel of the device, and does not change with the rotation of the phone. Therefore, it is not suitable for developing responsive websites (CSS logical pixel).
  • Width refers to the width of the viewable area, which is related to the viewport’s scale property

The most common way to distinguish devices by screen width (the width described in CSS pixels) is as follows:

@media (min-width:320px) { /* smartphones, portrait iPhone, portrait 480x320 phones (Android) */ }
@media (min-width:480px) { /* smartphones, Android phones, landscape iPhone */ }
@media (min-width:600px) { /* portrait tablets, portrait iPad, e-readers (Nook/Kindle), landscape 800x480 phones (Android) */ }
@media (min-width:801px) { /* tablet, landscape iPad, lo-res laptops ands desktops */ }
@media (min-width:1025px) { /* big landscape tablets, laptops, and desktops */ }
@media (min-width:1281px) { /* hi-res laptops and desktops */ }


min-width: 480px: Will target mobile devices in landscape mode and up
Copy the code
// @media screen and (min-width: 320px) { html { font-size: 50px; } } @media screen and (min-width: 360px) { html { font-size: 56px; } } @media screen and (min-width: 414px) { html { font-size: 63px; }}Copy the code

Rem layout

Rem: The font size of the root element (HTML). That is, 1rem = font size as set in HTML

Access device width document. DocumentElement. GetBoundingClientRect (). The width/document. DocumentElement. ClientWidth

Principle: in essence, when the proportion of the problem, according to the design of the proportion of fixed REM value calculated: mainly through the modification of HTML fontSize

  1. Directly introducing [www.jianshu.com/p/b00cd3506]…
   (function (doc, win) {
        var docEl = doc.documentElement,
            resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
            recalc = function () {
                var clientWidth = docEl.clientWidth;
                if(! clientWidth)return;
                if(clientWidth>=640){
                    docEl.style.fontSize = '100px';
                }else{
                    docEl.style.fontSize = 100 * (clientWidth / 640) + 'px'; // 640: Can be determined according to the design drawing}};if(! doc.addEventListener)return;
        win.addEventListener(resizeEvt, recalc, false);
        doc.addEventListener('DOMContentLoaded', recalc, false);
    })(document, window);
Copy the code
  1. Using flexible. Js github.com/amfe/lib-fl…

Disadvantages:

  1. The iframe problem
  2. Rich text problem
  3. Hd solution
  4. Some Android models are not compatible
  5. When the system font is scaled, it changes, causing the page to mess up because it is closely tied to the root element font. Solution: Scale restore 1> juejin.cn/post/684490… 2> Add the following code based on flexibility.js: juejin.cn/post/684490…
var root = window.document.documentElement; var fontSize = parseFloat(root.style.fontSize); Var finalFontSize = parseFloat(window.getComputedStyle(root).getPropertyValue("font-size"));
if(finalFontSize ! == fontSize) { root.style.fontSize = fontSize * fontSize / finalFontSize +"px";
}
Copy the code
  • The getComputedStyle window.getComputedStyle () method returns an object that reports the values of all the CSS properties of the element after the active stylesheet is applied and any basic calculations that those values may contain are parsed. Private CSS property values can be accessed through apis provided by the object or simply indexed using CSS property names.

  • GetPropertyValue this CSSStyleDeclaration. GetPropertyValue () interface returns a DOMString, the return value will contain CSS properties in the process of the requested information.

lib-flexible

The old version

Old version #17 code

Ios scale=0.5 innerWidth=750 device-width=375 innerWidth * scale= (device-width = layout-viewport-width)Copy the code

The processing process is as follows:

  1. DPR = window.devicepixelRatio
  2. Scale = 1/ DPR
  3. Then have innerWidth innerWidth = 375 / scale = 750 px (device – width = document. DocumentElement. ClientWidth)
  4. Finally split the innerWidth into 10rem, font size = innerWidth / 10 = 75px
; (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 (metaEl) {
        console.warn('Scaling will be set based on existing meta tags');
        var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
        if(match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); }}else if (flexibleEl) {
        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) { var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio;if(isIPhone) {// On iOS, use 2x for screens 2 and 3, and 1x for the restif(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 1 times DPR = 1; } scale = 1 / dpr; } docEl.setAttribute('data-dpr', 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(){// Dynamically set the zoom size will affect the layout viewport size, Physical pixel size equipment/device/equipment logic pixels - physical pixel width = equipment/(devicePixelRatio * scale) var. Width = docEl getBoundingClientRect (). The width; // iphone6 => 750if (width / dpr > 540) {
            width = 540 * dpr;
        }
        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);

    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;
    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';
        }
        return val;
    }

})(window, window['lib'] || (window['lib'] = {}));
Copy the code

The new version

New version 2.0 code

The meta tag is fixed to

<meta name="viewport" content="Width =device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" >Copy the code

Width = 10rem; font-size = width / 10

Width = 3.75rem, font size = 100px, width = 3.75rem, font size = 100px

Code to add a partial comment

(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();

  // set1rem = viewWidth / 3.6, better to calculate when the design is 360pxfunction setRemUnit() {// var rem = docel.clientWidth / 10 // original code var rem = docel.clientwidth / 3.6 // modified code docel.style.fontsize = rem +'px'
  }

  setRemUnit()

  // reset rem unit on page resize
  window.addEventListener('resize'.setRemUnit)
  window.addEventListener('pageshow'.function(e) {// Reference: HTTP: / / https://juejin.cn/post/6844904002103033870 / / page from the browser's cache read this property returns true, optimization window. Performance. Navigation. Type / /if(e.persisted) {// Original code //setRemUnit()
    // }
    if(e.p ersisted | | (window. The performance & & window. Performance. Navigation. The type = = = 2)) {/ / modified codesetRemUnit()}}) // detect 0.5PX supports saves for 0.5px issuesif (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

Vw/VH (cSS3 new attribute)

  • Viewport Height (vh): This unit is based on the height of the viewport.
  • Viewport Width (vw): This unit is based on the width of the viewport
  • 1vw: 1% of the viewport’s width
  • 1vh: 1% of the viewport’s height
  • Vmin: 1% of the viewport’s smaller Dimension, i.e. min Math. Min (vw, vh)
  • Vmax: 1% of the viewport’s larger dimension (vw and vh) math.max (vw, vh)

Implementation:

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/> Design size: Design element size = 100vw:Y // Y indicates the size of an element in the CSS design, in vwCopy the code

Disadvantages:

  • There is no Max/min limit, and the same applies when the screen is too small, the font or content is too small to read, or too large
  • Compatibility: ios8/ ios 4.4 or higher (ios6/7 partially supported) see https://caniuse.com/#feat=viewport-units

vw + rem

Advantages:

  1. Simple to implement, do not rely on plug-ins and third-party libraries, a few lines of CSS code can be implemented
  2. Convenient development, convenient conversion
  3. Does not affect the use of PX, perfectly compatible with third-party component library
  4. There are no compatibility issues such as rich text and IFrame

Implementation: The following implementation divides the screen into 10 parts on average, that is, the screen width is 10REM, and the relationship between REM and VW is as follows: Rem :vw = 10:1 or 1rem = 10vw based on 100vw === 10 REM === document.document.documentelement premise:

  1. Font size for HTML is equal to 1/10 of the viewport width. 1 * 100 vw rem = 1/10 = > is equivalent to the lib – flexible document. The documentElement. Style. FontSize = clientWidth / 10) [1/10 here, Because taobao scheme is also to take this value, for better calculation can go to other values]
// $vw_design: Design drawing size //$vw_fontsize/ 10 Suppose the design is divided into 10 pieces, each of which is 1rem of the design, and based on that.$vw_fontsize / $vw_design) * 100vw; @media Queries and (max-width: 320px) {font-size: 32px; } @media screen and (min-width: 540px) { font-size: 54px; }}Copy the code
  1. Calculation using SCSS function: design drawing element size/(design drawing size / 10) * 1rem
// $basesize: Design diagram element size @function rem($basesize) {@return ($basesize / $vw_fontsize) * 1rem; } // simplify @function rem($basesize) {@return ($basesize / $vw_design) * 10rem; 
}
Copy the code

Calculation principle:

Assume that the viewport size occupied by an element in the design drawing is X, and the unit is: Vw Design drawing Size of an element/design drawing size = (X)vw / 100vw => (X)vw = (design drawing element size/design drawing size) * 100vw // is converted to the number Y in rem since (Y) REM = (X)vw / 10 (Evenly divided into 10 parts, VW: REM = 10:1) => (Y) REM = (design element size/design drawing size) * 10vwCopy the code

Observation leads to inference, so it can also be understood as follows:

$design_width: 750
$divideNum: 10 // The average number of shares on the screen @function px2rem($design_dom) {@return #{$design_dom/$design_width * $divideNum}rem
}

html {
    font-size: (100 / $divideNum)vw; @media Queries and (max-width: 320) {font-size: 32; } @media screen and (min-width: 640 ) { font-size: 64; }}Copy the code

Reference: juejin. Cn/post / 684490…

rem + js

HTML {font-size: (clientWidth/average share of screen)px}

$design_width: 750
@function px2rem($dom) {@return #{$dom/$design_width * Number of screen shares}rem
}
Copy the code

Prevent rem elements without font size from inheriting the root element’s font zsize, reset body font size to default (typically 16px) or use media query font responsiveness (320, 480, 640 mobile)

body {
    font-size: 16px;
}
Copy the code

conclusion

Responsive layout scheme

Zoom layout The user experience compatibility Rely on js Large screen support Need to fix font
rem+media-query Can be IOS4.1 AN2.1 x Square root Square root
rem+js good IOS4.1 AN2.1 Square root Square root Square root
rem+vw optimal IOS6.1 AN4.4 x Square root Square root
vw optimal IOS6.1 AN4.4 x x x

Conclusion:

  1. Rem compatibility: ios4.1/android2.1
  2. Vw compatibility: ios6.1/android4.4
  3. Rem controls the maximum/minimum value of font size through media Query when the screen is large
  4. Rem schemes all need to fix the body font

other

1 px implementation

.hairlines li{
  height: 50px;
  line-height: 50px;
  border:none;
  text-align: center;
  position: relative;
  margin-top: 10px;
}
.hairlines li:after{
  content: ' ';
  position: absolute;
  left: 0;
  top: 0;
  border: 1px solid #cccccc;// border-radius: 26px; width: 200%; height: 200%; - its - transform: scale (0.5); The transform: scale (0.5); -webkit-transform-origin: left top; transform-origin: left top; }Copy the code

Percentage calculation

  1. A percentage is used in the height or width of a child element relative to its immediate parent
  2. Child element of the top/bottom | percentage, used in the left/right is directly relative to the static positioning (default location) of the height of the parent element | width
  3. The padding/margin of the child element uses a percentage, which is the width relative to the child element’s immediate parent element
  4. Child element of the border – the radius/translate/percentage is used in the background – size, relative to its wide | high

Reference: github.com/sunmaobin/s…