HTML direction

Calling system functions

< A > can quickly call the three communication functions of mobile devices, such as telephone, SMS and email, and <input> can quickly call the gallery/file of mobile devices. These functions facilitate the interaction between the page and the system. The key is that the call format must be accurate, otherwise it will be ignored by the mobile browser.

<! -- Dial the phone --><a href="tel:10086">Call little Sister 10086</a><! -- Send SMS --><a href="sms:10086">Send text messages to little sister 10086</a><! -- Send email --><a href="mailto:[email protected]">Send email to JowayYoung</a><! - choose the pictures or take photographs - > < input type = "file" accept = "image / *" > <! - select the video or shoot video - > < input type = "file" accept = "video / *" > <! <input type="file" multiple>Copy the code

Ignore automatic identification

Some mobile browsers automatically recognize alphanumeric symbols as phone/email and render them as <a> in the above call system function. It's convenient but it can be against your needs.

<! <meta name="format-detection" content="telephone=no"> <! <meta name="format-detection" content="email=no"> <! <meta name="format-detection" content="telephone=no, email=no">Copy the code

Pop-up numeric keypad

Use <input type="tel"> to press the numeric keypad with # and *, suitable for typing phone calls. It is recommended to use <input pattern="\ D *"> to play the numeric keypad. It is suitable for entering pure numeric formats such as verification codes.

<! <input type="tel"> <! <input pattern="\d*">Copy the code

Wake up native apps

The communication channel is established with the native application through location.href. This communication mode between the page and the client is called URL Scheme, and its basic format is Scheme ://[path][? Query]. The author has published the Communication Mode between H5 and App to describe the use of URL Scheme. Scheme: application identifier, which uniquely identifies an application in the system path: application behavior, which indicates the page or function to be applied Query: application parameters, which indicates the condition parameters required by the page or function to be applied URL Scheme is generally negotiated by the front-end and client. The prerequisite to wake up native apps is that the app must be installed on mobile devices. Some mobile browsers cannot wake up native apps even if the app is installed, because they consider URL Scheme a potentially dangerous behavior and disable it, such as Safari and wechat browsers. Fortunately, wechat browser can enable whitelist to make URL Scheme valid. If the URL Schema of a third-party native application is referenced on the page, you can capture the URL of the third-party native application.

<! -- Open wechat --><a href="weixin://">Open the WeChat</a><! -- Open Alipay --><a href="alipays://">Open Alipay</a><! -- Open alipay scan --><a href="alipays://platformapi/startapp? saId=10000007">Open the sweep of pay treasure</a><! Open alipay's ant forest --><a href="alipays://platformapi/startapp? appId=60000002">Open alipay's ant forest</a>
Copy the code

Disable page zooming

With the popularity of smartphones, many websites offer both desktop and mobile versions of browsing, so there is no need to double click to zoom in and out of the page. Disabling page zooming ensures that mobile browsers can display all page layouts without missing a page.

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

Disable page caching

Cache-control specifies the Cache mechanism followed by requests and responses.

<meta http-equiv="Cache-Control" content="no-cache">

Prohibit capitalization

Sometimes when you enter text in the input field, the default uppercase correction will be enabled, that is, the input lowercase letter will be automatically corrected to uppercase. Directly declare autocapitalize=off and autocorrect=off.

<input autocapitalize="off" autocorrect="off">

Safari Configuration

Post some of Safari’s more fragmented and rarely used configurations.

<! <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes"> -- Change Safari always, optional default/black/ black-always, <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="apple-touch-startup-image" href="pig.jpg" media="(device-width: 375px)"> <! <link rel="apple-touch-icon" sizes="76x76" href="pig.jpg"> <! <link rel="apple-touch-icon-precomposed" href="pig.jpg">Copy the code

For other browser configurations

Post some scattered and less used configuration of other browsers, mainly commonly used QQ browser, UC browser and 360 browser.

<! <meta name="x5-orientation" content="portrait"> <! <meta name="x5-fullscreen" content="true"> <! <meta name="x5-page-mode" content="app"> <! <meta name="screen-orientation" content="portrait"> <! <meta name="full-screen" content="yes"> <! <meta name=" browserMode "content="application"> <! <meta name="renderer" content="webkit">Copy the code

Let :active work, let :hover not work

For some elements, the :active element may be disabled, while the :hover element remains in the clicked state after being clicked, requiring another click to remove the clicked state. Registering an empty TouchStart event reverses both states.

<body ontouchstart></body>

CSS direction

Adaptive layout

For mobile terminals, the author usually declares font size dynamically with JS according to the ratio of screen width to design drawing width, and declares geometric attributes of all nodes with REM as the length unit, so that the page compatibility of most mobile devices can be achieved, and special processing can be done through media query in places with large compatibility. I usually set the REM layout scale to 1REM =100px, that is, the length of 100px on the design is represented by 1rem on the CSS code.

function AutoResponse(width = 750) {
    const target = document.documentElement;
    if (target.clientWidth >= 600) {
        target.style.fontSize = "80px";
    } else {
        target.style.fontSize = target.clientWidth / width * 100 + "px";
    }
}
AutoResponse();
window.addEventListener("resize".() = > AutoResponse());
Copy the code

Of course, you can also use calc() to dynamically declare font size based on the ratio of screen width to design width to save the above code. No, completely replace the above code.

html {
    font-size: calc(100vw / 7.5);
}
Copy the code

If iPad Pro resolution 1024px is used as breakpoint on both mobile and desktop, breakpoint handling can also be combined with media query. Use REM layout below 1024px, otherwise do not use REM layout.

@media screen and (max-width: 1024px) {
    html {
        font-size: calc(100vw / 7.5); }}Copy the code

Adaptive background

Use REM layout to declare an element background. In most cases background-size is declared as cover. It is possible that on a mobile device with the corresponding resolution of the design, the background will fit perfectly, but on a mobile device with another resolution, there will be a gap between 1px and NPX left and right. At this point, background-size is declared to be 100% 100%, which changes with width and height. Anyway, width and height are the actual measured dimensions.

.elem {
    width: 1rem;
    height: 1rem;
    background: url("pig.jpg") no-repeat center/100% 100%;
}
Copy the code

Monitor screen rotation

Are you still using JS to judge landscape and portrait adjustments? That’s really Out.

/ * * / vertical screen
@media all and (orientation: portrait) {
    /* Custom style */
}
Landscape * / / *
@media all and (orientation: portrait) {
    /* Custom style */
}
Copy the code

Support for elastic rolling

Non-element scrolling may stall on The MAC, but not on Android. Optimize elastic scrolling by declaring overflow-scrolling:touch and calling system native scrolling events to increase scrolling fluency.

body {
    -webkit-overflow-scrolling: touch;
}
.elem {
    overflow: auto;
}
Copy the code

Forbid rolling propagation

Unlike desktop browsers, mobile browsers have a strange behavior. When the page contains multiple rolling areas, if there is still rolling momentum after rolling a region, the remaining momentum will be transmitted to the next rolling area, causing the region to also roll. This behavior is called rolling propagation. You can ban it if you don’t want it to happen.

.elem {
    overscroll-behavior: contain;
}
Copy the code

Disable screen jitter

For some pages with sudden appearance of scroll bars, there may be adverse effects of left and right jitter. In a scroll container, open the popover to hide the scroll bar, close the popover to show the scroll bar, and move back and forth to make the screen shake. Declaring the padding-right of the scroll container to be the width of the scroll bar can eliminate this effect.

The width of the scroll bar may vary from mobile browser to mobile browser and may not even occupy the same position. You can calculate the width of the scroll bar indirectly by using the following method. 100vw is the window width, 100% is the scroll container content width, subtract is the scroll bar width, no problem dynamic calculation.

body {
    padding-right: calc(100vw - 100%);
}
Copy the code

Do not long press

Sometimes you do not want users to click the link, make a call, send an email, save a picture or scan the QR code by pressing the element call menu.

Sometimes you don’t want users to copy and paste stolen copy. Declare user-select: None to prevent users from holding down and selecting copy.

* {
    /* pointer-events: none; * / /* wechat browser also needs to attach this attribute to be valid */
    user-select: none; /* Disallow long press to select text */
    -webkit-touch-callout: none;
}

Copy the code

But declaring user-select: None makes and unable to enter text, excluding user-select:auto.

input,
textarea {
    user-select: auto;
}
Copy the code

Prohibit font adjustment

While rotating the screen may change the font size, declare text-size-adjust:100% to leave the font size unchanged.

* {
    text-size-adjust: 100%;
}
Copy the code

Disable highlighting

Touch elements will appear translucent gray mask, do not want!

* {
    -webkit-tap-highlight-color: transparent;
}
Copy the code

Disable animated flash screen

When adding an animation to a mobile device, most of the time a flash screen will appear. Creating a 3D environment for the parent element of the animation element will keep the animation stable.

.elem {
    perspective: 1000;
    backface-visibility: hidden;
    transform-style: preserve-3d;
}
Copy the code

Make forms look good

Appearance: None to help you customize the form element style.

button,
input,
select,
textarea {
    appearance: none;
    /* Custom style */
}
Copy the code

Beautify scrolling placeholders

The scrollbar style is too ugly to want to customize, ::-webkit-scrollbar-* to help you. Remember the following three key words to be flexible.

::-webkit-scrollbar ::-webkit-scrollbar ::-webkit-scrollbar-track ::-webkit-scrollbar-thumb ::-webkit-scrollbar {width: 6px;
    height: 6px;
    background-color: transparent;
}
::-webkit-scrollbar-track {
    background-color: transparent;
}
::-webkit-scrollbar-thumb {
    border-radius: 3px;
    background-image: linear-gradient(135deg, #09f, #3c9);
}
Copy the code

Beautify the input placeholder

Input box placeholder text is too ugly, ::-webkit-input-placeholder to help you.

input::-webkit-input-placeholder {
    color: #66f;
}
Copy the code

Align input placeholders

Students with obsessive-compulsive disorder always feel that the text position of the input box is on the whole, and the feeling is not centered. In the desktop browser, declare line-height equal to height. In the mobile browser, declare line-height equal to height.


input {
    line-height: normal;
}
Copy the code

Align the drop-down options

The dropdown options are aligned to the left by default, so it’s time to align them to the right.


select option {
    direction: rtl;
}

Copy the code

Fixed invalid click

On Apple systems, there are cases where listening for click events on non-clickable elements may not be effective; this can be solved by declaring cursor:pointer on elements that do not trigger click events.

.elem {
    cursor: pointer;
}

Copy the code

Recognize text newlines

Most of the time you’ll use JS newline text, and that’s really Out. If the interface returns a field containing \n or, do not replace it, declare white-space:pre-line to the browser for line breaking.

* {
    white-space: pre-line;
}
Copy the code

Enabling Hardware Acceleration

If you want to animate more smoothly, turn on GPU hardware acceleration!

.elem {
    transform: translate3d(0.0.0);
    /* transform: translateZ(0); * /
}
Copy the code

Draw pixel borders

Ten thousand years topic, how to depict a pixel border?

.elem {
    position: relative;
    width: 200px;
    height: 80px;
    &::after {
        position: absolute;
        left: 0;
        top: 0;
        border: 1px solid #f66;
        width: 200%;
        height: 200%;
        content: "";
        transform: scale(. 5); transform-origin: left top; }}Copy the code

Control overflow text

Ten thousand years topic, how to control text to do single line overflow and multi-line overflow?

.elem {
    width: 400px;
    line-height: 30px;
    font-size: 20px;
    &.sl-ellipsis {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    &.ml-ellipsis {
        display: -webkit-box;
        overflow: hidden;
        text-overflow: ellipsis;
        -webkit-line-clamp: 3; -webkit-box-orient: vertical; }}Copy the code

JS direction

Disable click penetration

It is well known that there will be 300ms delay in click operation in mobile browser, which often causes click delay and even invalid click.

Safari, the first iPhone released by Apple in 2007, uses double-click zooming to make desktop web sites look good on mobile browsers. This scheme is the main reason for the 300ms delay. After the user clicks for the first time, 300ms will be reserved to check whether the user clicks again. If the user clicks again, the zoom operation will be performed. Given its success, the solution has been copied by other mobile browsers and is now available in almost all mobile browsers. The click delay caused by this scheme is called click penetration.

The first solution to clickthrough in the front-end domain was Zepto in the era of jQuery. It is estimated that most of you have never used Zepto. In fact, it is the mobile version of jQuery. Zepto encapsulates tap events to effectively solve tap penetration by listening to touch events on document to complete the simulation of TAP events and bubbling tap events onto document to trigger.

Use touch events instead of click events on mobile browsers because click events have significant latency, followed by FastClick. The solution listens to see if the user has made a double click, so you can use the click event directly, and the FastClick will automatically determine the click penetration. More fastClick principle can be self-baidu, in this not too much introduction.

Fastclick has a ready-made NPM package that can be installed directly into your project. Fastclick allows you to use click events instead of tap events in a very simple way.

import Fastclick from "fastclick";

FastClick.attach(document.body)

No sliding penetration

It’s a well-known fact that when pop-ups appear in mobile browsers, swiping on the screen triggers the content underneath to scroll along.

The first step is to clarify what interaction needs to be maintained by sliding through. That is, nothing can be clicked or scrolled except popover content. Many current solutions fail to do this, and rolling behavior, which all solutions prohibit, causes other problems.

Internal contents cannot scroll after popover opens

The scrolling position of the page is lost after the popover is closed

The Webview can slide up and down to reveal the background color

When popover opens, declare position: Fixed; left:0; Width :100% and dynamically declare top. Declaring position: Fixed causes the scroll bar to disappear. In this case, it will be found that although there is no slide penetration, the page scroll position has been lost. Get the current scroll bar offset of the page by scrollingElement, take it negative and assign it to TOP, and there is no visual change. Remove position:fixed while closing popover; left:0; Width :100% and dynamic top. ScrollingElement is compatible with properties such as scrollTop and scrollHeight, and works well in mobile browsers. Document. ScrollingElement. ScrollHeight can perfect instead of once the document. The documentElement. ScrollHeight | | document. Body. ScrollHeight, At first glance, it looks like less code. This solution has no visual change, and is better than any other solution. It is a reverse thinking and a smoke screen. The solution perfectly solves the impact of fixed popovers and rolling popovers on global rolling, and of course can also be used in local rolling containers, so it is worth promoting.

body.static {
    position: fixed;
    left: 0;
    width: 100%;
}
const body = document.body;
const openBtn = document.getElementById("open-btn");
const closeBtn = document.getElementById("close-btn");
openBtn.addEventListener("click".e= > {
    e.stopPropagation();
    const scrollTop = document.scrollingElement.scrollTop;
    body.classList.add("static");
    body.style.top = ` -${scrollTop}px`;
});
closeBtn.addEventListener("click".e= > {
    e.stopPropagation();
    body.classList.remove("static");
    body.style.top = "";
});
Copy the code

Round-trip refresh support

Clicking the forward or back buttons of the mobile browser sometimes does not automatically execute the JS code of the old page, due to round-trip caching. This is especially true in Safari, where the round-trip page cannot be refreshed. Round-trip caching (BFCache) is a strategy used by browsers to make moving forward and backward between pages smoother. The strategy is as follows: when the user goes to the new page, the DOM state of the old page is saved in BFCache; when the user returns to the old page, the DOM state of the old page is removed from BFCache and loaded. Most mobile browsers deploy BFCache, which greatly reduces the time and bandwidth of interface requests. The solution to what BFCache is can be found at Window. onunload.

// Listen for page destruction events on the new page
window.addEventListener("onunload".() = > {
    // Execute old page code
});
Copy the code

If using keep-alive on Vue SPA does not refresh the page, place the interface request in beforeRouteEnter(). There is, of course, another solution. The PagesHow event fires every time a page loads, whether it is the first time it is loaded or the next time it is loaded, which is what distinguishes it from the Load event. The PagesHow event exposes persisted to determine whether the page is persisted from BFCache. window.addEventListener(“pageshow”, e => e.persisted && location.reload()); If the browser does not use disabled caching, this solution is still worth using.

Analytic date of validity

On apple systems, the Date format YYYY-MM-DD HH: MM :ss returns an Invalid Date error, but on Android systems, the Date format has no problem.

new Date("2019-03-31 21:30:00"); // Invalid Date

The date format YYYY/MM/DD HH: MM :ss is available in the Safari development manual. Of course, Android supports this format, but the date format of the interface return field is usually YYYY-MM-DD HH: MM :ss, so replace the – with /.

const date = "The 2019-03-31 21:30:00";
new Date(date.replace(/\-/g."-"));
Copy the code

Repair height collapse

When the following three conditions are present on the page at the same time, the keyboard placeholder will compress a portion of the page. When the keyboard placeholder disappears after the input is completed, the page height may not return to the original height, resulting in collapse and resulting in the appearance of the background color of the Webview. A simple summary is that the page does not rebound after the input box is out of focus. The page height is too small. Procedure

The input box is at the bottom of the page or at the bottom of the window

Input fields focus on input text

This problem does not occur as long as the offset of the front and back scroll bars is the same. The current scroll bar offset of the page is obtained when the input box is focused, and the scroll bar offset obtained before the page is assigned when the input box is out of focus. In this way, the scroll bar offset of the page can be indirectly restored to solve the height collapse of the page.

const input = document.getElementById("input");
let scrollTop = 0;
input.addEventListener("focus".() = > {
    scrollTop = document.scrollingElement.scrollTop;
});
input.addEventListener("blur".() = > {
    document.scrollingElement.scrollTo(0.this.scrollTop);
});
Copy the code

Fix input listening

The keyUP/KeyDown/keyPress event may be invalid if you enter text in the input box on the MAC. When the input box listens for the keyUP event, typing English and digits one by one is effective, but typing Chinese characters one by one is not effective. You need to press Enter to make the event effective. In this case, input events can be used instead of keyUP/KeyDown/keyPress events in the input box.

Simplify back to the top

There was a time when writing a function that returned to the top was a pain in the neck, requiring a combination of scrollTop, timer, and conditional judgment. There’s a nice function hidden in the DOM object that does all this in a single line of core code. This function, called scrollIntoView, scrolls the parent container of the target element to make it visible to the user. In short, it scrolls the container to the target element relative to the window. It has three optional arguments to make scrollIntoView scroll more gracefully.

Behavior: Animation transition effect (Default: auto). Optional: Smooth

Inline: Horizontal alignment with nearest by default, top of Start, center, and bottom of end are optional

Block: vertical alignment, default alignment on top of START, optional alignment on center, bottom of End and nearest

const gotopBtn = document.getElementById(“gotop-btn”);

openBtn.addEventListener(“click”, () => document.body.scrollIntoView({ behavior: “smooth” })); You can also scroll to the target element by changing document.body to the DOM object of the target element. Isn’t it tiring to write so much code when you can do it with one line of core code?

Simplify lazy loading

As with the simplification back to the top, writing a lazy loading function also requires a combination of scrollTop, timer, and conditional judgment. In fact, there is a very useful function hidden in the DOM object to accomplish the above function. This function does not need to listen for the container’s Scroll event, through the browser’s own mechanism to complete the scroll listening.

This function, IntersectionObserver, provides a way to asynchronously observe the intersecting state of the target element and its ancestor or top-level document window. Refer to the MDN documentation for more details, which will not be covered here. The first use scenario for lazy loading is image lazy loading. Just make sure the image is in the viewable area and assign to load the image. Once the assignment is complete, stop listening for the image.

<img data-src="pig.jpg"> <! <img> -->const imgs = document.querySelectorAll("img.lazyload");
const observer = new IntersectionObserver(nodes= > {
    nodes.forEach(v= > {
        if (v.isIntersecting) { // Determine whether to enter the viewable area
            v.target.src = v.target.dataset.src; // Assign to load the image
            observer.unobserve(v.target); // Stop listening for loaded images}}); }); imgs.forEach(v= > observer.observe(v));
Copy the code

The second use scenario for lazy loading is pull-down loading. Deploy a placeholder element at the bottom of the list without any height or physical appearance and ask the interface to load the data simply by confirming that the placeholder element is in the viewable area.

<ul>
    <li></li><! -- many <li> --> </ul> <! Insert #bottom into the last position inside the <ul><div id="bottom"></div>
const bottom = document.getElementById("bottom");
const observer = new IntersectionObserver(nodes= > {
    const tgt = nodes[0]; // There is only one
    if (item.isIntersecting) {
        console.log("Bottom. Request interface.");
        // Execute the interface request code
    }
})
bottom.observe(bottom);
Copy the code

Optimized scan recognition

Usually mobile browsers are equipped with the function of long pressing the TWO-DIMENSIONAL code image to identify links, but long pressing the two-dimensional code may not be recognized or misrecognized. Two-dimensional code surface looks like a picture, but two-dimensional code generation is multifarious, two-dimensional code generation has the following three kinds.

Render using < IMG > Render using < SVG > Render using <canvas>Copy the code

Data tested by netease MTL shows that most mobile browsers can only recognizeRender the QR code, in order to make all mobile browsers can recognize the QR code, that can only be usedRender the QR code. If using SVG and Canvas to generate two-dimensional code, then try to convert the two-dimensional code data into Base64 and then assign values toThe SRC.

There may be multiple two-dimensional codes on a page, if long press the two-dimensional code can only identify the last one, it can only control the existence of only one two-dimensional code on each page.

Autoplay media

Common media elements include audio and video. In order to provide users with a better media playback experience and avoid blindly wasting user traffic, most mobile browsers clearly specify that they cannot automatically play media or block Autoplay by default. In order for the media to play automatically after the page loads, you must explicitly declare it to play.

const audio = document.getElementById("audio");
const video = document.getElementById("video");
audio.play();
video.play();
Copy the code

For built-in browsers like wechat browser, the above code can be triggered only after the application SDK is loaded to ensure the normal rendering of WebView. The same goes for other built-in browsers, which I won’t cover too much here.

document.addEventListener("WeixinJSBridgeReady".() = > {
    // Execute the media autoplay code described above
});
Copy the code

The Apple system clearly stipulates that media can be played only after user interaction starts. If there is no response from the user, The media will be automatically blocked by Safari. Therefore, the listener needs to listen for the user’s first touch and trigger the media to play automatically.

document.body.addEventListener("touchstart".() = > {
    // Execute the media autoplay code described above
}, { once: true });
Copy the code

H5 Precautions