Kỹ Thuật Tối Ưu Hóa Tương Thích Và Giao Diện Mobile H5

Cấu hình HTML và Meta Tags

Trong phát triển ứng dụng web di động, việc thiết lập các thẻ meta phù hợp giúp kiểm soát hành vi hiển thị trên các trình duyệt khác nhau. Dưới đây là các cấu hình thường gặp để quản chế hướng màn hình, chế độ toàn màn hình và ngăn chặn các nhận diện tự động không mong muốn.

Thiết lập thuộc tính Meta cơ bản

Các trình duyệt như UC hay QQ trên Android thường có chế độ ứng dụng riêng. Chúng ta có thể ép buộc chế độ hiển thị dọc hoặc toàn màn hình thông qua các thẻ meta đặc thù:

<meta name="screen-orientation" content="portrait"> <!-- Khóa hướng màn hình dọc trên Android -->
<meta name="full-screen" content="yes"> <!-- Chế độ toàn màn hình -->
<meta name="browsermode" content="application"> <!-- Chế độ ứng dụng UC Browser -->
<meta name="x5-orientation" content="portrait"> <!-- Khóa hướng dọc cho QQ Browser -->
<meta name="x5-fullscreen" content="true"> <!-- Toàn màn hình trên QQ -->
<meta name="x5-page-mode" content="app"> <!-- Chế độ ứng dụng QQ -->

Quản lý nhận diện số điện thoại và Email

Safari trên iOS thường tự động chuyển đổi các chuỗi số giống số điện thoại thành liên kết gọi điện. Để kiểm soát hành vi này, ta sử dụng format-detection.

Tắt nhận diện tự động:

<meta name="format-detection" content="telephone=no" />

Nếu muốn kích hoạt tính năng gọi điện thủ công, sử dụng thẻ a với protocol tel:

<a href="tel:0901234567">Gọi ngay</a>

Tương tự, trên Android, chuỗi ký tự dạng email có thể bị nhận diện. Để tắt tính năng này:

<meta name="format-detection" content="email=no" />

Để kích hoạt chức năng gửi mail khi nhấn vào:

<a href="mailto:contact@example.com">Gửi email</a>

Các Mẹo Xử Lý CSS Trên Mobile

Khắc phục vấn đề viền 1px bị đậm

Trên các màn hình mật độ điểm ảnh cao (Retina, DPR > 1), đường viền 1px CSS thường hiển thị dày hơn mong muốn. Giải pháp là sử dụng pseudo-element kết hợp với transform: scale để tạo ra viền mảnh (0.5px).

.hairline-bottom {
  position: relative;
}
.hairline-bottom::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background-color: #ddd;
  transform: scaleY(0.5);
  transform-origin: 0 0;
}

.hairline-top {
  position: relative;
}
.hairline-top::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 1px;
  background-color: #ddd;
  transform: scaleY(0.5);
  transform-origin: 0 0;
}

.hairline-all {
  position: relative;
}
.hairline-all::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 200%;
  border: 1px solid #ccc;
  transform: scale(0.5);
  transform-origin: 0 0;
  box-sizing: border-box;
  pointer-events: none;
}

Ngăn chặn chọn văn bản và sao chép ảnh

Để tăng trải nghiệm giống ứng dụng native, ta có thể vô hiệu hóa khả năng bôi đen văn bản hoặc lưu ảnh:

.no-select {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

img.prevent-save {
  -webkit-touch-callout: none;
  pointer-events: none;
}

Xử lý giao diện input và form

Một số trình duyệt mặc định thêm bóng mờ hoặc thay đổi style của input. Để đồng bộ hóa giao diện:

input, textarea {
  -webkit-appearance: none;
  border-radius: 0;
}

/* Đổi màu chữ gợi ý (placeholder) */
input::placeholder, textarea::placeholder {
  color: #999;
  opacity: 1;
}
input::-webkit-input-placeholder {
  color: #999;
}

Chống缩放 văn bản và highlight khi click

Ngăn chặn trình duyệt tự động phóng to chữ khi xoay màn hình và loại bỏ vùng sáng khi chạm vào liên kết trên Android:

body {
  text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

a, button, input {
  -webkit-tap-highlight-color: transparent;
  -webkit-user-modify: read-write-plaintext-only;
}

Tối ưu hóa cuộn trang trên iOS

Trên iOS, cuộn trang mặc định có thể bị giật lag. Sử dụng -webkit-overflow-scrolling: touch để kích hoạt cuộn mượt mà dựa trên phần cứng:

.scroll-wrapper {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  height: 100%;
}

Xử Lý Sự Kiện và Logic JavaScript

Độ trễ click 300ms

Trình duyệt mobile thường đợi 300ms sau khi chạm để xác định xem người dùng có thực hiện thao tác zoom hay không. Để loại bỏ độ trễ này, có thể sử dụng sự kiện touch thay vì click hoặc các thư viện như FastClick.

Thứ tự sự kiện chạm thường gặp:

  1. touchstart
  2. touchmove
  3. touchend
  4. click (sau cùng)

Tự động phát Audio/Video

Chính sách của iOS và Android ngăn chặn tự động phát media để tiết kiệm dung lượng. Cần có tương tác từ người dùng (như chạm màn hình) mới có thể phát nhạc.

document.documentElement.addEventListener('touchstart', function handleTouch() {
    var audioElement = document.querySelector('audio');
    if (audioElement && audioElement.paused) {
        audioElement.play();
    }
    // Chỉ chạy một lần
    document.documentElement.removeEventListener('touchstart', handleTouch);
}, { once: true });

Hiện tượng vùng trắng khi kéo quá giới hạn (iOS)

Khi kéo trang web vượt quá giới hạn trên iOS, một vùng trắng sẽ xuất hiện. Để chặn hành vi này khi không cần thiết:

document.body.addEventListener('touchmove', function(event) {
    // Cho phép cuộn trên các phần tử có class .scrollable
    if (event.target.closest('.scrollable')) {
        return;
    }
    event.preventDefault();
}, { passive: false });

Lỗi chuyển đổi ngày tháng thành NaN trên iOS

iOS không hỗ trợ định dạng ngày tháng sử dụng dấu gạch ngang - trong một số trường hợp. Cần thay thế bằng dấu gạch chéo /:

function parseDate(dateString) {
    return new Date(dateString.replace(/-/g, '/'));
}

Xử Lý Các Vấn Đề Liên Quan Đến Bàn Phím Ảo

Bàn phím che khuất input

Khi bàn phím xuất hiện, nó có thể che mất ô nhập liệu. Cần lắng nghe sự kiện thay đổi kích thước cửa sổ để cuộn phần tử vào vùng nhìn thấy:

window.addEventListener('resize', function() {
    var activeElement = document.activeElement;
    if (activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA')) {
        setTimeout(function() {
            if (activeElement.scrollIntoView) {
                activeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
            }
        }, 100);
    }
});

Sự kiện bàn phím không đồng bộ trên iOS

Các sự kiện keyup hoặc keydown trên iOS đôi khi không hoạt động ổn định khi sử dụng bộ gõ tiếng Việt. Nên ưu tiên sử dụng sự kiện input để lắng nghe thay đổi giá trị.

Lỗi focus trên iOS 12+

Một số phiên bản iOS gặp vấn đề khi click vào input không hiện bàn phím, thường do xung đột với thư viện FastClick. Có thể khắc phục bằng cách điều chỉnh lại hàm focus:

function fixInputFocus(target) {
    if (target.setSelectionRange && target.type !== 'date') {
        var len = target.value.length;
        target.setSelectionRange(len, len);
    }
    target.focus();
}

Trạng thái fixed bị lỗi khi bàn phím xuất hiện

Phần tử position: fixed thường bị đẩy lên hoặc biến thành absolute khi bàn phím ảo mở ra. Giải pháp là tránh dùng fixed cho toàn bộ trang, thay vào đó tạo một container cuộn riêng và giữ footer cố định relative với container đó.

<body>
  <div class="app-container">
    <div class="content-scroll">
      
    </div>
    <div class="footer-sticky">
      
    </div>
  </div>
</body>
.app-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.content-scroll {
  height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.footer-sticky {
  position: absolute;
  bottom: 0;
  width: 100%;
}
window.addEventListener('focusout', function() {
    window.scrollTo(0, 0);
});

Thẻ: mobile-web-development css-hairline ios-keyboard-fix javascript-touch-events h5-compatibility

Đăng vào ngày 9 tháng 6 lúc 22:27