Người dùng di động hiện chiếm một phần lớn lưu lượng web, nhưng vẫn có nhiều trang web xử lý phát hiện di động trong JavaScript một cách yếu. Kết quả là các trang tải chậm, tương tác chạm bị hỏng, pop-up không cần thiết, hoặc các tính năng hoạt động khác nhau trên điện thoại và máy tính bảng so với máy tính để bàn. Đối với các nhà phát triển, freelancer và chủ doanh nghiệp nhỏ đang cố gắng xây dựng trải nghiệm web thực dụng và nhanh, đây không phải là một chi tiết nhỏ. Nó ảnh hưởng trực tiếp đến khả năng sử dụng, tỷ lệ chuyển đổi và niềm tin của khách hàng.
Vấn đề khó khăn là phát hiện di động trên JavaScript không phải là một kỹ thuật đơn lẻ. Nó có thể có nghĩa là kiểm tra kích thước màn hình, đọc chuỗi user agent, phát hiện khả năng cảm ứng, hoặc quan sát hỗ trợ tính năng trong trình duyệt. Mỗi phương pháp giải quyết một vấn đề khác nhau, và mỗi phương pháp có giới hạn. Phương pháp tốt nhất thường là đừng hỏi, “Đây có phải là thiết bị di động không?” mà là, “Những khả năng mà thiết bị và trình duyệt này thực sự có?”
Phát hiện di động là gì?
Ở cốt lõi, phát hiện di động trên JavaScript là quá trình nhận diện xem khách truy cập có khả năng đang dùng một thiết bị di động hay không, và đôi khi là loại môi trường di động họ đang sử dụng. Thông tin này có thể được dùng để điều chỉnh điều hướng, tối ưu hóa tương tác, tải tài nguyên nhẹ hơn, điều chỉnh bố cục, hoặc tinh chỉnh hành vi cho các trường hợp sử dụng ưu tiên cảm ứng.
Nhiều người cho rằng điều này chỉ đơn giản là kiểm tra xem cửa sổ trình duyệt có nhỏ hay không. Trong thực tế, nó tinh tế hơn. Một cửa sổ trình duyệt nhỏ trên desktop không phải là một điện thoại. Một máy tính bảng lớn có thể có màn hình rộng hơn một số laptop. Một thiết bị gập có thể thay đổi hình dạng khi người dùng tương tác với ứng dụng của bạn. JavaScript có thể giúp phát hiện các tình huống này, nhưng chỉ khi bạn hiểu rõ tín hiệu bạn đang đo lường.
Kiểu phát hiện di động cũ dựa nhiều vào chuỗi user agent, là một nhận dạng văn bản được trình duyệt gửi đi. Trong nhiều năm, các nhà phát triển phân tích chuỗi này để suy đoán xem thiết bị có phải iPhone, điện thoại Android, iPad, hay trình duyệt desktop. Phương pháp đó vẫn tồn tại, nhưng ít đáng tin cậy như trước. Các trình duyệt ngày càng giảm hoặc chuẩn hóa dữ liệu user agent vì lý do bảo mật và tương thích. Xem thêm về chuỗi user agent trên MDN: chuỗi user agent.
Phát triển frontend hiện đại nghiêng nhiều hơn về thiết kế đáp ứng và phát hiện tính năng. Thay vì đưa ra giả định rộng về danh mục thiết bị, các nhà phát triển dùng truy vấn media CSS và kiểm tra JavaScript để đáp ứng kích thước viewport, hỗ trợ cảm ứng, định hướng, loại con trỏ, điều kiện mạng hoặc các tính năng của trình duyệt. Điều này tạo ra ứng dụng kiên cường hơn và giảm thiểu các lỗi biên.
Tại sao các nhà phát triển vẫn dùng phát hiện di động
Dù thiết kế đáp ứng xử lý phần lớn công việc bố cục, vẫn có những lý do thực tế để phát hiện ngữ cảnh di động bằng JavaScript. Một trang web doanh nghiệp có thể muốn đơn giản hóa bảng giá phức tạp trên các viewport nhỏ hơn. Một ứng dụng đặt chỗ có thể chuyển từ tương tác dựa trên hover sang điều khiển dựa trên chạm. Một bảng điều khiển có thể trì hoãn các tập lệnh không thiết yếu cho người dùng có kết nối di động hạn chế.
Cũng có một góc độ hiệu suất. Nếu bạn biết người dùng có khả năng đang ở một môi trường di động, bạn có thể chọn tải chậm media độ phân giải cao, nén các tương tác, hoặc tránh các hoạt ảnh tốn kém. Điều đó không có nghĩa là phục vụ một trải nghiệm kém hơn. Nó có nghĩa là phục vụ một trải nghiệm phù hợp hơn.
Phát hiện thiết bị so với phát hiện khả năng
Phân biệt này có ý nghĩa. Phát hiện thiết bị cố gắng trả lời thiết bị là gì. Phát hiện khả năng cố gắng trả lời trình duyệt có thể làm được những gì. Nếu mục tiêu của bạn là cải thiện khả năng sử dụng, phát hiện khả năng thường an toàn hơn.
Ví dụ, nếu bạn muốn biết có nên hiển thị tooltip dựa trên hover hay không, việc kiểm tra một chuỗi user agent “mobile” là một giải pháp yếu. Một cách tiếp cận tốt hơn là hỏi xem thiết bị có một con trỏ chính xác hay hỗ trợ hover hay không. Đó là một câu hỏi về khả năng, và JavaScript có thể làm việc với các tín hiệu đó hiệu quả hơn nhiều so với một nhãn di động rộng.

Các khía cạnh chính của Phát hiện di động trên JavaScript

Để đưa ra quyết định thông minh, bạn cần hiểu rõ các phương pháp phát hiện chính và chúng hoạt động tốt ở đâu. Không có một phương pháp đơn lẻ hoàn hảo, do đó sức mạnh đến từ việc chọn đúng công cụ cho đúng việc.
Phát hiện dựa trên user agent
Phát hiện dựa trên user agent vẫn được sử dụng rộng rãi vì nó đơn giản và quen thuộc. Trong JavaScript, các nhà phát triển thường kiểm tra navigator.userAgent và tìm các dấu hiệu như Android, iPhone, hoặc iPad.
function isMobileByUserAgent() {
return /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(
navigator.userAgent
);
}
console.log(isMobileByUserAgent());
Phương pháp này có thể hoạt động cho các heuristics nhanh chóng, đặc biệt trong các cơ sở mã kế thừa hoặc các tập lệnh phân tích. Nó cũng hữu ích khi bạn cần phân loại sơ bộ cho các họ thiết bị đã biết.
Nhược điểm là độ tin cậy. Các chuỗi user agent có thể bị giả mạo, thay đổi, hoặc chuẩn hóa giữa các trình duyệt. Chúng không đảm bảo tương lai, và chúng thường bị phá vỡ khi xuất hiện thiết bị mới. Nếu logic kinh doanh của bạn phụ thuộc nhiều vào chúng, việc bảo trì có thể gây đau đầu.
Phát hiện kích thước viewport và màn hình
Mô hình phổ biến hơn là phát hiện chiều rộng viewport và điều chỉnh hành vi tương ứng. Điều này gắn sát với thiết kế web đáp ứng và thường khớp với những gì người dùng thực sự trải nghiệm trên màn hình.
function isSmallViewport() {
return window.innerWidth <= 768;
}
console.log(isSmallViewport());
Điều này hữu ích khi bạn quan tâm đến bố cục hoặc không gian màn hình có sẵn. Nếu một menu cạnh bên nên thu gọn dưới một độ rộng nhất định, phát hiện viewport là một giải pháp hợp lý.
Tuy nhiên, điều quan trọng là phải rõ ràng về điều này có nghĩa gì. Nó không cho biết người dùng có đang dùng điện thoại hay không. Nó chỉ cho biết viewport hiện tại là nhỏ. Trình duyệt desktop được thay đổi kích thước có thể cho ra kết quả tương tự. Đối với nhiều quyết định giao diện, điều đó là ổn. Đối với phân loại thiết bị, nó không đủ.
Phát hiện khả năng cảm ứng
Một số nhà phát triển cho rằng hỗ trợ cảm ứng tương đương với việc dùng di động, nhưng lối suy nghĩ ấy có thể gây hiểu lầm. Nhiều laptop có cảm ứng, và một số trình duyệt di động có thể hoạt động khác so với mong đợi. Tuy nhiên, khả năng cảm ứng vẫn có giá trị khi giao diện của bạn cần các cử chỉ hoặc điều khiển khác biệt.
function supportsTouch() {
return (
'ontouchstart' in window ||
navigator.maxTouchPoints > 0 ||
navigator.msMaxTouchPoints > 0
);
}
console.log(supportsTouch());
Điều này hoạt động tốt nhất khi bạn đang trả lời một câu hỏi tương tác cụ thể. Nếu bạn cần mục tiêu chạm lớn hơn, cử chỉ vuốt hoặc thao tác kéo được tinh chỉnh cho cảm ứng, kiểm tra này có thể giúp. Nếu bạn đang cố gắng quyết định xem khách truy cập có phải là “di động” hay không, thì nó quá rộng khi chỉ dựa vào một kiểm tra đơn lẻ.
Media queries trong JavaScript
JavaScript cũng có thể đọc những điều kiện tương tự như trong CSS media queries. Đây thường là một trong những cách tinh gọn nhất để đồng bộ hóa logic CSS và JavaScript.
const mobileQuery = window.matchMedia('(max-width: 768px)');
function handleViewportChange(e) {
if (e.matches) {
console.log('Likely mobile-sized viewport');
} else {
console.log('Larger viewport');
}
}
handleViewportChange(mobileQuery);
mobileQuery.addEventListener('change', handleViewportChange);
Cách tiếp cận này đặc biệt hữu ích khi UI của bạn thay đổi động. Người dùng có thể xoay điện thoại, thay đổi kích thước trình duyệt, hoặc di chuyển giữa các chế độ chia màn hình. Phát hiện dựa trên media query cho phép các tập lệnh của bạn phản hồi theo thời gian thực thay vì giả định trạng thái thiết bị không đổi.
Phát hiện con trỏ và hover
Một chiến lược hiện đại hơn và thường bị bỏ qua là kiểm tra hành vi nhập liệu. Điều này quan trọng vì nhiều vấn đề UX đặc thù di động thực tế là vấn đề về nhập liệu.
const hasCoarsePointer = window.matchMedia('(pointer: coarse)').matches;
const supportsHover = window.matchMedia('(hover: hover)').matches;
console.log({ hasCoarsePointer, supportsHover });
Con trỏ thô (coarse pointer) thường cho thấy tương tác bằng ngón tay, trong khi hỗ trợ hover có xu hướng tương quan với chuột hoặc bàn di chuột. Điều này thường hữu ích hơn so với phát hiện di động rộng khi quyết định cách thức hoạt động của menu, tooltip và các điều khiển tương tác.
So sánh các phương pháp phổ biến
Chiến lược phát hiện di động hiệu quả nhất phụ thuộc vào câu hỏi bạn đang đặt ra. Bảng dưới đây cho thấy mỗi phương pháp phù hợp ở đâu.
| Phương pháp | Tốt nhất cho | Ưu điểm | Hạn chế |
|---|---|---|---|
| Phát hiện dựa trên user agent, Phân loại thiết bị sơ bộ | Phân loại thiết bị sơ bộ | Đơn giản, quen thuộc, triển khai nhanh | Dễ bị phá vỡ, dễ giả mạo, ít bền vững cho tương lai |
| Chiều rộng viewport, Bố cục và hành vi đáp ứng | Bố cục và hành vi đáp ứng | Phù hợp với không gian màn hình, dễ bảo trì | Không xác định đúng loại thiết bị |
| Phát hiện cảm ứng, Tương tác đặc thù cảm ứng | Tương tác đặc thù cảm ứng | Phù hợp cho logic liên quan cử chỉ và chạm | Cảm ứng không phải lúc nào cũng đồng nghĩa với di động |
| Media queries qua JavaScript, Hành vi đáp ứng động | Hành vi đáp ứng động | Đồng bộ với logic CSS, phản ứng với sự thay đổi | Vẫn tập trung vào điều kiện, không phải danh tính thiết bị |
| Phát hiện con trỏ và hover, Điều chỉnh UX theo đầu vào | Điều chỉnh UX theo đầu vào | Xuất sắc cho thiết kế tương tác | Không phải là hệ thống phân loại di động hoàn chỉnh |
Tại sao “mobile” thường không phải mục tiêu đúng
Một trong những sai lầm lớn nhất trong JavaScript là đối xử tất cả điện thoại và máy tính bảng như một danh mục duy nhất. Một điện thoại flagship hiện đại trên kết nối nhanh có thể vượt trội hơn một máy tính để bàn cũ ở một số tác vụ. Một máy tính bảng có bàn phím có thể hoạt động giống một máy tính xách tay hơn là một điện thoại. Một thiết bị gập có thể chuyển từ bố cục hẹp sang rộng ngay lập tức.
Đó là lý do tại sao một phương pháp tiếp cận dựa trên ngữ cảnh hoạt động tốt hơn. Nếu bạn cần điều chỉnh bố cục, hãy dùng logic viewport. Nếu bạn cần điều chỉnh tương tác, hãy dùng phát hiện con trỏ và hover. Nếu bạn cần giảm các hiệu ứng nặng trên các thiết bị hạn chế, hãy kết hợp tín hiệu tính năng và hiệu suất. Điều này giúp bạn ít giả định sai hơn và kiến trúc sạch hơn.
Cách bắt đầu với Phát hiện di động trên JavaScript
Cách dễ nhất để bắt đầu là bỏ chasing một định nghĩa di động hoàn hảo và thay vào đó xác định hành vi bạn thực sự muốn thay đổi. Khung làm việc này làm cho việc triển khai trở nên đơn giản hơn. Bạn không còn phải nhận diện mọi thiết bị có thể có. Bạn đang giải quyết một vấn đề trải nghiệm người dùng cụ thể.
Ví dụ, nếu điều hướng của bạn bị hỏng trên các thiết bị dùng cảm ứng làm chủ, hãy tập trung vào phát hiện con trỏ và cảm ứng. Nếu nội dung của bạn cảm thấy chật chội trên màn hình nhỏ, hãy tập trung vào logic dựa trên viewport. Nếu một script từ bên thứ ba gây chậm trên các thiết bị nhỏ, hãy tập trung vào chiều rộng màn hình, tải theo điều kiện mạng và tăng cường tiến bộ.
Bắt đầu với thiết kế đáp ứng trước
Trước khi viết logic phát hiện bằng JavaScript, hãy đảm bảo bố cục của bạn đã đáp ứng bằng CSS. Trong nhiều trường hợp, CSS media queries giải quyết vấn đề một cách tinh tế hơn JavaScript. Phát hiện di động trên JavaScript thường nên hỗ trợ hành vi, chứ không thay thế thiết kế đáp ứng.
Khi bố cục và khoảng cách nhìn thấy đã đáp ứng, JavaScript của bạn sẽ nhẹ và có chủ đích hơn. Bạn chỉ thêm logic nhận diện thiết bị ở những nơi tương tác, hiệu suất hoặc tải có điều kiện thực sự đòi hỏi.
Sử dụng phát hiện tính năng để thay đổi hành vi
Nếu mục tiêu là thay đổi cách một giao diện hoạt động, phát hiện tính năng thường là điểm khởi đầu đúng. Điều này có nghĩa là kiểm tra xem trình duyệt có hỗ trợ một khả năng hay không thay vì cố gắng suy ra từ nhãn thiết bị. Xem thêm về phát hiện tính năng: phát hiện tính năng.
Đây là một ví dụ thực tế thích ứng tương tác menu dựa trên hỗ trợ hover:
const canHover = window.matchMedia('(hover: hover)').matches;
const menuButton = document.querySelector('.menu-button');
const menu = document.querySelector('.menu');
if (canHover) {
menuButton.addEventListener('mouseenter', () => {
menu.classList.add('open');
});
menuButton.addEventListener('mouseleave', () => {
menu.classList.remove('open');
});
} else {
menuButton.addEventListener('click', () => {
menu.classList.toggle('open');
});
}
Đây là một mẫu mạnh vì nó thích ứng với cách người dùng tương tác, chứ không phải tên thiết bị họ đang dùng. Một laptop có cảm ứng và một điện thoại có thể đều tránh khỏi logic phụ thuộc vào hover, trong khi trình duyệt trên máy tính để bàn vẫn duy trì hành vi thân thiện với chuột.
Kết hợp tín hiệu khi cần thiết
Đôi khi một tín hiệu không đủ. Nếu bạn cần đưa ra nhận định rộng hơn về việc sử dụng di động, kết hợp các kiểm tra có thể cải thiện độ chính xác mà không giả định bạn có sự chắc chắn.
function isLikelyMobile() {
const smallScreen = window.matchMedia('(max-width: 768px)').matches;
const coarsePointer = window.matchMedia('(pointer: coarse)').matches;
const mobileUA = /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(
navigator.userAgent
);
return smallScreen && (coarsePointer || mobileUA);
}
console.log(isLikelyMobile());
Điều này vẫn không nên được dùng như một quy tắc an ninh cứng hoặc quan trọng đối với kinh doanh. Đây là một heuristik. Tuy nhiên, đối với tinh chỉnh UI, nó có thể hữu ích khi bạn cần một danh mục dự phòng cho phân tích hoặc điều chỉnh trải nghiệm nhẹ.
Theo dõi thay đổi kích thước và hướng màn hình
Một sai lầm phổ biến là kiểm tra một lần khi tải trang và không cập nhật lại. Điều kiện di động có thể thay đổi khi trang đang mở. Thay đổi hướng, ứng dụng chia màn hình, thiết bị gập và việc thay đổi kích thước trình duyệt đều ảnh hưởng tới môi trường.
function updateDeviceState() {
const mobileSized = window.matchMedia('(max-width: 768px)').matches;
document.body.classList.toggle('mobile-sized', mobileSized);
}
window.addEventListener('resize', updateDeviceState);
window.addEventListener('orientationchange', updateDeviceState);
updateDeviceState();
Loại cập nhật dựa trên sự kiện này giúp giao diện của bạn luôn đồng bộ với ngữ cảnh hiện tại. Điều này đặc biệt quan trọng đối với bảng điều khiển, ứng dụng web, hệ thống đặt chỗ và các công cụ duy trì mở trong các phiên dài.
Avoid common implementation mistakes
Sai lầm đầu tiên là dùng phát hiện dựa trên user agent làm nguồn sự thật duy nhất. Nó nghe tiện lợi, nhưng theo thời gian sẽ tạo ra các lỗi ẩn. Sai lầm thứ hai là dùng phát hiện di động để khóa nội dung thiết yếu. Người dùng không nên mất chức năng cốt lõi vì script của bạn đoán sai.
Một vấn đề phổ biến khác là quá phát triển. Không phải mọi trang web đều cần một lớp phát hiện thiết bị phức tạp. Nếu mục tiêu của bạn chỉ là xếp chồng thẻ trên màn hình nhỏ hoặc mở rộng vùng chạm, CSS và một vài kiểm tra JavaScript nhắm mục tiêu là đủ. Giữ logic gắn với nhu cầu thực tế của sản phẩm.
Cài đặt thực tế cho hầu hết các website
Đối với nhiều trang web doanh nghiệp và ứng dụng web, một cách tiếp cận hợp lý có thể như sau:
- Sử dụng CSS media queries cho bố cục và khoảng cách.
- Sử dụng matchMedia() trong JavaScript cho hành vi liên quan viewport hoặc loại đầu vào.
- Sử dụng phát hiện tính năng cho cảm ứng, hover, hoặc các tương tác liên quan con trỏ.
- Sử dụng kiểm tra user agent một cách hạn chế cho các trường hợp biên hoặc phân tích, không phải là chiến lược chính.
Quy trình làm việc này mang lại cho bạn sự linh hoạt mà không làm frontend của bạn dễ bị gãy. Nó cũng dễ kiểm tra, giải thích và bảo trì trên các dự án khác nhau.
Kiểm tra logic phát hiện di động
Kiểm tra có ý nghĩa vì lỗi phát hiện di động thường ẩn ở các trường hợp biên. Một trang có thể trông ổn trên trình duyệt máy tính để bàn được co nhỏ đến kích thước điện thoại, sau đó sẽ hành xử khác khi chạy trên một thiết bị thực có input cảm ứng và trình duyệt có thanh trình duyệt.
Sử dụng công cụ dành cho nhà phát triển trình duyệt cho kiểm tra nhanh kích thước, nhưng cũng thử trên điện thoại và máy tính bảng thực khi có thể. Hãy chú ý tới thay đổi hướng, chồng bàn phím, hành vi chạm, trạng thái hover, và hiệu suất khi điều kiện chậm. Nếu trang của bạn phục vụ khách hàng, không chỉ các nhà phát triển, các chi tiết này sẽ định hình trải nghiệm người dùng nhiều hơn so với phương pháp phát hiện.
Kết luận
Phát hiện di động trên JavaScript không phải là xác định một danh mục thiết bị hoàn hảo mà là chọn tín hiệu phù hợp cho công việc. Phát hiện dựa trên user agent vẫn có thể hữu ích trong một số trường hợp hạn chế, nhưng phát triển hiện đại hoạt động tốt hơn khi bạn tập trung vào kích thước viewport, hỗ trợ tính năng, khả năng cảm ứng và hành vi nhập liệu. Cách tiếp cận này kiên cố hơn, chính xác hơn cho quyết định UX và dễ bảo trì hơn.
Bước tiếp theo thật đơn giản. Xem xét một phần trang của bạn mà có sự khác biệt trên điện thoại, như điều hướng, biểu mẫu, media hoặc các tiện ích tương tác. Sau đó hỏi bạn thực sự cần phát hiện gì: không gian màn hình, cảm ứng, hover, hay một heuristic di động sơ bộ. Khi bạn trả lời rõ ràng, JavaScript của bạn sẽ sạch hơn, và người dùng sẽ có trải nghiệm mượt mà trên mọi thiết bị.


Để lại một bình luận