Viewports là khu vực hiển thị nội dung trang web trên màn hình trình duyệt. Hệ thống viewport trong thiết bị di động gồm ba loại chính: layout viewport, visual viewport và ideal viewport.
Layout viewport là chiều rộng ảo do trình duyệt cung cấp để hiển thị các trang web desktop trên thiết bị nhỏ — thường mặc định là 980px trên iOS và Android. Điều này giúp trang web PC hiển thị được, nhưng nội dung bị thu nhỏ và yêu cầu phóng to thủ công.
Visual viewport là phần người dùng thực tế đang nhìn thấy — thay đổi khi zoom hoặc cuộn.
Ideal viewport là kích thước lý tưởng nhất cho từng thiết bị: chiều rộng bằng đúng độ phân giải màn hình vật lý (ví dụ: 375px trên iPhone SE, 414px trên iPhone 12 Pro). Mục tiêu của thẻ <meta name="viewport"> là đồng bộ layout viewport với ideal viewport.
Cấu hình viewport chuẩn
- Chiều rộng bằng chiều rộng thiết bị (
width=device-width) - Tỷ lệ phóng to ban đầu là 1.0 (
initial-scale=1.0) - Không cho phép người dùng phóng to/thu nhỏ (
user-scalable=no) - Giới hạn tỷ lệ phóng tối đa và tối thiểu đều là 1.0
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, minimum-scale=1.0,
user-scalable=no">
<title>Ứng dụng Di động</title>
</head>
Hình ảnh độ phân giải cao (Retina & DPR)
Mỗi thiết bị có tỷ lệ pixel vật lý (device pixel ratio – DPR). Ví dụ: iPhone 6 có DPR = 2 — nghĩa là 1px CSS tương ứng với 2×2 pixel vật lý. Khi hiển thị ảnh gốc 100×100px trên thiết bị DPR=2, trình duyệt sẽ kéo giãn ảnh lên 200×200 pixel vật lý → làm mờ.
Giải pháp: Cung cấp ảnh có kích thước gấp DPR lần (thường là 2x), sau đó điều chỉnh kích thước hiển thị qua CSS:
.hero-banner {
background-image: url('banner@2x.jpg');
background-size: 100% auto; /* Hoặc 'cover', 'contain' */
width: 100%;
height: 200px;
}
Các giá trị background-size:
cover: Kéo giãn ảnh vừa đủ để che phủ toàn bộ vùng nền (có thể cắt phần thừa)contain: Kéo giãn tối đa mà vẫn giữ nguyên tỷ lệ và hiển thị toàn bộ ảnh100% 100%: Lấp đầy theo chiều rộng và cao
Box-sizing và mô hình hộp hiện đại
Trong phát triển di động, nên áp dụng mô hình hộp border-box:
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
/* Thay vì tính toán thủ công:
width + padding + border = tổng chiều rộng */
/* Với border-box: width đã bao gồm padding và border */
Styling đặc thù cho thiết bị cảm ứng
button,
input,
textarea {
-webkit-appearance: none; /* Bỏ giao diện mặc định iOS */
-webkit-tap-highlight-color: transparent; /* Loại bỏ viền highlight khi nhấn */
}
img,
a {
-webkit-touch-callout: none; /* Vô hiệu hóa menu dài nhấn */
}
Kỹ thuật bố cục phổ biến
- Layout dựa trên phần trăm: Dùng
%cho chiều rộng, kết hợpmax-width/min-widthđể kiểm soát giới hạn - Flexbox: Giải pháp linh hoạt, hỗ trợ tuyệt vời trên thiết bị di động
- Responsive kết hợp media query + rem + preprocessor (SCSS/Less)
Flexbox: Nguyên lý và thuộc tính then chốt
Flexbox là mô hình bố cục đàn hồi, trong đó một phần tử cha được khai báo display: flex trở thành flex container, và tất cả con trực tiếp trở thành flex items.
Các thuộc tính trên container:
flex-direction: Hướng trục chính (row,column, v.v.)justify-content: Căn chỉnh dọc theo trục chínhalign-items: Căn chỉnh dọc theo trục phụ (cho một hàng)flex-wrap: Cho phép ngắt dòng (wrap) hoặc không (nowrap)align-content: Căn chỉnh giữa các hàng (chỉ có hiệu lực khi có nhiều hàng)flex-flow: Thuộc tính viết tắt choflex-direction+flex-wrap
Các thuộc tính trên item:
flex: Chỉ định tỷ lệ chiếm dụng không gian còn dư (vd:flex: 2chiếm gấp đôiflex: 1)align-self: Ghi đèalign-itemscho từng item riêng lẻorder: Xác định thứ tự hiển thị (giá trị số nhỏ hơn xuất hiện trước)
Khởi tạo dự án di động
Khuyến nghị sử dụng normalize.css thay vì reset CSS — vì nó:
- Bảo toàn các giá trị mặc định hữu ích
- Sửa lỗi hiển thị giữa các trình duyệt
- Được tổ chức theo module và có tài liệu chi tiết
→ Tải tại: https://necolas.github.io/normalize.css/
Mẫu khởi tạo cơ bản:
body {
margin: 0;
font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
color: #333;
background: #fafafa;
max-width: 540px;
min-width: 320px;
margin: 0 auto;
-webkit-tap-highlight-color: rgba(0,0,0,0);
overflow-x: hidden;
}