What are the problems
- 1 px border
- Click event 300ms delay
- Touch event click through
- Mobile terminal picture
1 px border
1. Why the 1px border is “thicker” under the HD screen
- It’s not really thicker, it’s the 1 pixel that the design wants, not the 1CSS pixel that the programmer thinks it is, but the 1 physical pixel
- If DPR =2, what the design really wants is 1px/2=0.5px
- If DPR =3, what the design really wants is 1px/3=0.3333px
2. Solutions
- Discuss with the designer, if you don’t care about this problem, don’t bother
- Set the “thin” border directly
- There are compatibility issues, and different browsers will behave differently
- This method is recommended for iOS operating systems later than iOS8
- Pseudo-class + Transform (recommended)
- Other schemes can be referred to:www.cnblogs.com/zzsdream/ar…
The specific implementation
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>1 px border</title>
<style>
body {
background-color: #f5f5f5;
}
.list {
padding: 0;
margin: 0;
font-size: 30px;
}
.item {
list-style: none;
line-height: 60px;
border-bottom: 1px solid #ccc;
}
/* Directly set the "thin" border */
.item1 {
border-width: 0.5 px.;
}
/* pseudo-class + transform */
@media (-webkit-min-device-pixel-ratio: 2) {
.border-1px {
position: relative;
border: none;
}
/* Add a dummy class to set the border */
.border-1px::after {
box-sizing: border-box;
content: ' ';
position: absolute;
top: 0;
left: 0;
/* In the future, scale will be halved */
width: 200%;
height: 200%;
/* Sets the corresponding border */
border-bottom: 1px solid #ccc;
/* border: 1px solid #ccc; * /
/* Set rounded corners */
/* border-radius: 20px; * /
transform-origin: 0 0;
transform: scale(0.5);
/* background-color: rgba(255, 0, 0, 0.5); * /}}@media (-webkit-min-device-pixel-ratio: 3) {
.border-1px::after {
width: 300%;
height: 300%;
transform: scale(0.3333); }}</style>
</head>
<body>
<ul class="list">
<li class="item">"Thickened" 1px border</li>
<! - < li class = "item" > coarsen the reason < / li > < li class = "item" > solution < / li > -- >
<li class="item item1">Set the "thin" border directly</li>
<li class="item border-1px">Pseudo-classes + transform</li>
</ul>
</body>
</html>
Copy the code
Click event 300ms delay
The click screen on the mobile end produces a delayed response of 200-300 ms, often resulting in button click delay or even click failure.
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Click event 300ms delay</title>
<style>
.btn {
width: 100%;
height: 300px;
font-size: 100px;
/* touch-action: manipulation; * /
}
</style>
</head>
<body>
<button id="btn" class="btn">submit</button>
<script src="https://cdn.bootcdn.net/ajax/libs/fastclick/1.0.6/fastclick.min.js"></script>
<script>
const $btn = document.getElementById('btn');
$btn.addEventListener(
'touchstart'.() = > {
console.time('click');
},
false
);
$btn.addEventListener(
'click'.() = > {
console.timeEnd('click');
console.log('Submit form');
},
false
);
</script>
</body>
</html>
Copy the code
Cause of 300ms delay in mobile click event
- Cause: double-tap to zoom (wait to check whether your operation is double-tap to zoom)
The solution
Solution 1
- Instead of using the Click event, place the click event to be processed in touchStart or TouchEnd
$btn.addEventListener(
'touchend'.() = > {
console.timeEnd('click');
console.log('Submit form');
},
false
);
Copy the code
Solution 2
- Disable double click zooming (browser vendor effort)
- Patrickhlauke. Making. IO/touch/tests…
- Zoom is disabled in viewPort
- touch-action: manipulation; (Allows scrolling and continuous zooming only)
Solution 3
- Using Fastclick library
- Github.com/ftlabs/fast…
- Mainly for older browsers
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="Width = device - width, initial - scale = 1.0, the minimum - scale = 1, maximum - scale = 1, the user - scalable = no"
/>
<title>Click event 300ms delay</title>
<style>
.btn {
width: 100%;
height: 300px;
font-size: 100px;
/* touch-action: manipulation; * /
}
</style>
</head>
<body>
<button id="btn" class="btn">submit</button>
<! Fastclick library -->
<script src="https://cdn.bootcdn.net/ajax/libs/fastclick/1.0.6/fastclick.min.js"></script>
<script>
// Use the Fastclick library
if ('addEventListener' in document) {
document.addEventListener(
'DOMContentLoaded'.function () {
FastClick.attach(document.body);
},
false
);
}
const $btn = document.getElementById('btn');
$btn.addEventListener(
'touchstart'.() = > {
console.time('click');
},
false
);
// $btn.addEventListener(
// 'touchend',
// () => {
// console.timeEnd('click');
// console.log(' Submit form ');
/ /},
// false
// );
$btn.addEventListener(
'click'.() = > {
console.timeEnd('click');
console.log('Submit form');
},
false
);
</script>
</body>
</html>
Copy the code
Touch event click through
About 300ms after the occurrence of touch action, the mobile terminal will simulate the generation of click action. If the touch event hides the original element, click will always act on the element with click feature underneath it, triggering the click event and jump of the new element. This phenomenon is called click penetration
Cause of Touch event click through
Events are triggered in the following order: TouchStart -> TouchEnd -> click. It is this lag design of click events that foils event penetration (click penetration).
- The element’s click event is triggered by default when the touch event ends
- The Touch event on the mobile side fires immediately, while the click event fires after some time
Common event penetration scenarios:
- The upper element listens for the touch event, after which the layer element disappears
- Underlying elements have click properties (listening for click events or default properties (A tag, input tag, button tag))
- For example, if a standard element triggers a touch event to hide or remove itself, the corresponding location element triggers a click event or a link jump.
- The target element uses a touch event to jump to a new page, and the corresponding element in the new page fires a click event or a link to jump.
Note: the link jump event of the A tag is a click event
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="Width = device - width, initial - scale = 1.0, the minimum - scale = 1, maximum - scale = 1, the user - scalable = no"
/>
<title>Touch event click through</title>
<style>
.btn {
width: 100%;
height: 300px;
font-size: 100px;
}
.mask {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0.0.0.0.5);
opacity: 1;
transition: opacity 0.5 s;
}
</style>
</head>
<body>
<button id="btn" class="btn">submit</button>
<div id="mask" class="mask"></div>
<script>
const $btn = document.getElementById('btn');
const $mask = document.getElementById('mask');
// Both TouchEnd and TouchStart will cause the click to pass through the click mask layer and trigger the click event below
Since the mask element triggers the TouchStart touch event and immediately hides itself, the touchend and click events for the mask element should then be triggered in sequence.
// However, the div click event is triggered because the mask element is already hidden.
$mask.addEventListener(
'touchend'.() = > {
$mask.style.display = 'none';
},
false
);
$mask.addEventListener(
'touchstart'.() = > {
console.time('click');
},
false
);
$btn.addEventListener(
'click'.() = > {
console.timeEnd('click');
console.log('Submit form');
},
false
);
</script>
</body>
</html>
Copy the code
The solution
Solution 1
There are many solutions to event penetration, which can be broadly divided into two categories: the first is to prohibit the mixing of click and touch events; The other is to delay the hiding or removal of elements.
- Delay hiding elements that are hidden
$mask.addEventListener(
'touchend'.() = > {
// $mask.style.display = 'none';
// The delay disappears
setTimeout(() = > {
$mask.style.display = 'none';
}, 200);
CSS adds transition and initial opacity = 1
$mask.style.opacity = 0;
},
false
);
// Hide the element at the end of the transition
$mask.addEventListener(
'transitionend'.() = > {
$mask.style.display = 'none';
},
false
);
Copy the code
Solution 2
Blocking default behavior
// Prevent the default click behavior from firing
$mask.addEventListener('touchstart'.function(e){
e.preventDefault();
console.log('hello')
$mask.style.display = 'none';
})
Copy the code
Solution 3
Remove the click feature from the back element and replace click with touchXxxx
banner_img.addEventListener('touchstart'.() = >{
location.href = 'http://www.baidu.com'
})
Copy the code
Solution 4
Make the element behind it temporarily lose the click event and restore it in about 300 milliseconds
#anode{
pointer-events: none;
}
Copy the code
btn.addEventListener('touchstart'.(event) = >{
shade.style.display = 'none';
setTimeout(() = >{
anode.style.pointerEvents = 'auto'
},500)})Copy the code
Mobile terminal picture
- Img image
- The background image
Img image
- Generally use percentages, and only set one of the width or height, not at the same time, so that the width and height can be scaled equally, the image is not distorted
- When the actual width of the image is smaller than the width of the parent container, the image will not stretch further as the parent container width increases
- This will solve the problem of stretching the image width but will leave the image blank if it exceeds its original width
/* Leave the image white to center */
.img-container {
display: flex;
justify-content: center;
}
Copy the code
The background image
<style>
.bg-container {
width: 100%;
/* If the height is fixed */
height: 200px;
background: url(./bg.png) no-repeat;
/* Zoom the background image to completely cover the background area
background-size: cover;
}
</style>
<div class="bg-container"></div>
Copy the code
<style>
.bg-container {
width: 100%;
/* If the height is not fixed */
/* 563px 224px 224 / 563 */
/* padding relative to width */
padding-top: 39.7869%;
background: url(./bg.png) no-repeat;
/* Zoom the background image to completely cover the background area
background-size: cover;
}
</style>
<div class="bg-container"></div>
Copy the code
You can also use media queries
/* Small screen uses small images */
background: url(./bg.png) no-repeat;
/* Use */ in conjunction with media query
/* Large screen uses large images */
@media (min-width: 560px) {
.bg-container {
background-image: url(./bg_lg.png); }}Copy the code