One, layout
The overall layout of the mobile end can generally be divided into the upper and lower three parts, respectively, header, main, footer, where the header, footer is fixed height, respectively fixed at the top of the page and the bottom of the page, and main occupies the rest of the page, and can scroll.
The page layout is as follows:
<body> <div class= "header" ></div> <div class= "main" ></div> <div class= "Footer" ></div></body>
Depending on the location of the page scrolling is divided into two layouts, one is the scrolling body, the other is a fixed body height of 100%, in main scroll.
One advantage of the first layout is that the page's address bar will be hidden as the body scrolls, and the scrolling body will be smoother in the Android device, if there is a similar requirement in the project to consider.
The layout is implemented in the following ways:
Body{Overflow:Auto;}. Header,.footer{position:fixed; Left:0; Right:0;Height:44px;}. Header{Top:0;}. Footer{Bottom:0;}. Main{Height:100%;padding:44px 0;}
The first case is more suitable for the long list page, the entire page in addition to the header and footer need to scroll, but many times, we only want an element of the page to scroll, this time, take the second layout.
There are three relatively simple ways to implement this page layout:
- Fixed positioning
- Absolute positioning
- Flex positioning
The easiest way to realize this is fixed positioning, which is implemented as follows:
html, Body{Height:100%;Overflow:Hidden;}. Header,.footer{position:fixed; Left:0; Right:0;Height:44px;}. Header{Top:0;}. Footer{Bottom:0;}. Main{Height:100%;padding:44px 0;box-sizing:Border-box;}
Fixed positioning is simple to implement, and can be displayed normally in most browsers, but fixed positioning will have compatibility issues on the mobile side, which is mentioned later, so this implementation is not recommended.
Absolute positioning and fixed positioning is similar, as long as the header of the footer position changed to absolute.
Careful little partner may find, here the main does not set overflow, because there is a pit, whether it is absolute positioning or fixed positioning are the same, in order to facilitate the description, the following only fixed positioning (in the absolute positioning is also established). There is no problem on the PC side, but on the mobile side, if main sets the overflow as True,header will be covered by main, yes, there is no mistake, although it is fixed positioning, but on the mobile side, if the following the fixed location node immediately after the sibling node is scrollable (that is, set Overflow is true), then the fixed node is obscured by the sibling nodes behind it.
There are many ways to solve this problem, since it is the fixed position behind the rolling sibling node will have this pit, as long as his condition has a not set up, there are the following solutions:
- Let the fixed location node not immediately follow the scrollable node
- Do not let the scroll node obscure the fixed node
The first-party scenario has the following optional methods:
1. Place all the fixed nodes behind the scroll element, i.e. place the header node behind the main node
<body> <div class= "main" ></div> <div class= "header" ></div> <div class= "Footer" ></div></body>
But this obviously does not conform to the general people's thinking habits, code readability is reduced.
2. Make main non-scrollable, nesting a scrollable child node for main
<body> <div class= "header" ></div> <div class= "main" > <div class= " Scroll-container "></div> </div> <div class=" Footer "></div></body>< Style> { overflow: hidden; } {height: 100%; Overflow: auto; } </style>
The second scenario has the following optional methods:
1. Make the scroll node not coincident with the fixed node
{ padding: 44px 0;} { padding: 0;}
2. Set the z-index for the fixed node
{ z-index: 8888;}
A simple way to--->>> a third way to implement flex layouts. Flex positioning is compatible with iOS 7.1+,android 4.4+ on the mobile side, and if tools such as autoprefixer can be downgraded to older versions of Flexbox, it can be compatible with iOS 3.2 and Android 2.1. And it's relatively simple to implement with Flex, and it's relatively consistent across browsers. The implementation is as follows:
{ display: flex; flex-direction: column;} { flex: 1; Overflow: auto; -webkit-overflow-scrolling: touch;} { height: 44px;} { height: 44px;}
Second, fixed and input
To use fixed positioning on a page that has the input tag, because there is always a weird problem when the two are together.
On IOS, when you click the Input tab to get the focus to evoke a soft keyboard, the fixed location temporarily fails, or it can be understood to be a absolute location, where the fixed positioned node scrolls with the other nodes in the page that contains the scrolling.
In fact, this problem is also very good to solve, as long as the fixed location of the parent node is not scrollable, so even if the fixed location fails, and other scrolling nodes will not scroll, affecting the interface.
But in addition, there are many pits more difficult to solve, such as the Android soft keyboard after the call block input tags, users can not see their input string, IOS need to enter at least one character, to the corresponding input tag to scroll to the appropriate location, So in order to avoid these difficult pits, in the form Input page, try to replace the fixed with absolute or flex.
Iii. Compositionstart and Compositionend events of input
In WEB development, the input of form elements is often restricted, such as the entry of special characters and punctuation. Usually we listen to the input event:
function (event) { =/[^1-9a-za-z]/g; = Event.target.value.replace (Regex, "); false });
This code is not a problem on Android, but in IOS, the input event will truncate the non-direct input, what is non-direct input, when we input Chinese characters, such as "Hi Tea", in the middle process will be input pinyin, each time the input of a letter will trigger the input event, However, it is non-direct input before selecting the candidate or clicking the "Select" button.
So input "Hi tea" two words, will trigger 6 input events, if the value of each input is printed out, the result is as follows:
This is obviously not the result we want, we want to trigger the input event after the direct input, which leads to the two events--compositionstart and compositionend I want to say.
The Compositionstart event is triggered when the user starts a non-direct input, and the Compositionend event is triggered by the end of the non-direct input, i.e. when the user selects the candidate or clicks the "Select" button.
varInputlock =false;function Do(inputelement) {varRegex =/[^1-9a-za-z]/G; Inputelement.value= InputElement.value.replace (Regex, ");} Inputelement.addeventlistener (' Compositionstart ',function() {Inputlock=true;}); Inputelement.addeventlistener (' Compositionend ',function(event) {Inputlock=false; Do(Event.target);}) Inputelement.addeventlistener (' Input ',function(event) {if(!Inputlock) { Do(Event.target); Event.returnvalue=false; }});
Add a Inputlock variable that, when the user does not complete the direct input, Inputlock is true, does not trigger the logic in the input event, and when the user completes the valid input, the Inputlock is set to false, triggering the logic of the input event. One thing to note here is that the Compositionend event is triggered after the input event, so the input event processing logic is also invoked when the Compositionend event is triggered.
Four, IOS 1px border implementation
On iOS devices, because of the retina screen, the 1px border will be displayed as two physical pixels, so it will look very coarse, which is a common problem with mobile development. There are a lot of solutions, but they all have their pros and cons.
0.5px border
Starting with iOS 8, iOS browser supports 0.5px border, but it is not supported on Android, 0.5px is considered 0px, so this method, compatibility is very poor.
Background gradient
CSS3 has a gradient background, can be achieved through the gradient background 1px border, the principle is to set 1px gradient background, 50% color, 50% is transparent.
@mixin Commonstyle () { background-size:100% 1px,1px 100%, 100% 1px, 1px 100%; Background-repeat:no-repeat; Background-position:top, right top, bottom, left top;} @mixin border ($border-color) { @include commonstyle (); Background-image:linear-gradient (180deg, $border-color, $border-color 50%, Transparent 50%), linear -gradient (270deg, $border-color, $border-color 50%, Transparent 50%), linear-gradient (0deg, $ Border-color, $border-color 50%, Transparent 50%), linear-gradient (90deg, $border-color, $ Border-color 50%, transparent 50%);}
Although this method is feasible, there is no way to achieve the fillet.
Pseudo class + transform
The implementation principle of this kind of method is to realize border with pseudo-element's Box-shadow or border, then use transform to reduce to half of the original. Even the need for rounded corners can be very well implemented.
@mixin Hairline-common ($border-radius) {position:relative; Z-index:0; &: before {position:absolute; Content:‘‘; Border-radius: $border-radius; Box-sizing:border-box; Transform-origin:0 0; }} @mixin Hairline ($direct:' All ', $border-color: #ccc, $border-radius:0) {@include hairline-common ($border-radius); &: Before {transform:scale (.5); @if$direct = = ' All '{top:0; Left:0; Width:200%; Height:200%; Box-shadow:0 0 0 1px $border-color; Z-index:-1; } @Else if$direct = = ' Left ' or $direct = = ' Right '{#{$direct}:0; Top:0; Width:0; Height:200%; Border-#{$direct}: 1px solid $border-color; } @Else{#{$direct}:0; Left:0; Width:200%; Height:0; Border-#{$direct}: 1px solid $border-color; } }}
Mobile Web front-end annotations