Tạp Chí Đồ Họa Việt Nam

Tìm hiểu Media Query trong CSS3

Tìm hiểu Media Query trong CSS3 – Media Query là một trong những module mới được thêm vào trong CSS3. Nó là một sự cải thiện của Media Type đã có từ CSS2, bằng việc thêm vào những cú pháp query để ta có thể đáp ứng được cho nhiều device với nhiều kích cỡ màn hình khác nhau.

Tìm hiểu Media Query trong CSS3

Tìm hiểu Media Query trong CSS3 Tìm hiểu Media Query trong CSS3
Tìm hiểu Media Query trong CSS3

Module Media Query hiện đã được implement đầy đủ trong các trình duyện hiện đại như Webkit, Firefox, Opera hay IE (kể từ version 9).

Tại sao lại sử dụng Media Query

Hiện tại đang là thời điểm bùng nổ của các thiết bị di động. Máy tính để bàn hay laptop không còn là những phương tiện duy nhất giúp mọi người có thể truy cập vào website của bạn.

Người ta có thể dùng điện thoại, hay tablet …

Và vấn đề phát sinh khi mà những thiết bị với kích cỡ màn hình nhỏ bé truy cập vào trang web của bạn.

Kích cỡ chữ trở nên quá nhỏ bé. Việc zoom out có thể giải quyết được vấn đề nhưng zoom out sẽ đồng nghĩa với việc phát sinh ra nhiều chỗ cần scroll một cách không cần thiết
Việc phải load những hình ảnh có kích cỡ quá lớn dẫn đến giảm tốc độ load trang web trên thiết bị di động. Trong khi đáng ra với những màn hình kích cỡ nhỏ như vậy thì ta chỉ cần hiện thị những tấm hình có kích cỡ nhỏ hơn.

Một trong những cách giải quyết trước đây đã từng được sử dụng rộng rãi đó là việc thiết kế view riêng cho những thiết bị moblie, và những view này được access qua một domain khác (hoặc là subdomain). Những request được gửi tới website sẽ được check xem là từ thiết bị nào, nếu là thết bị mobile thì sẽ bị redirect sang domain được tạo riêng như đã nói ở trên.

Ngoài việc phải tạo ra script để xác nhận thiết bị truy cập thì cách giải quyết ở trên còn gặp phải một nhược điểm khác nữa đó là ta luôn phải tạo ra 2 view khác nhau cho cùng một trang, và mỗi khi cần tay đổi một nội dung gì đó thì ta cần phải thay đổi cả hai.

Và Media Query ra đời đã giúp những nhà lập trình viên giải quyết được những vấn đề trên. Media Query có thể giúp ta nhận biết được thiết bị truy cập thông qua những thuộc tính của nó. Media Query giúp chúng ta áp dụng những CSS rules khác nhau cho những thiết bị có khích cỡ màn hình khác nhau. Từ đó ta có thể đạt được mục đích của mình đó là hiện thị những nội dung khác nhau (cả hình ảnh, hay text) với những thiết bị khác nhau.

Media Type

Trước khi tìm hiểu về cú pháp của Media Query, trước hết ta hãy nói qua về Media Type trước.

Media Type vốn đã có từ CSS2, nó giúp ta xác định định dạng của mỗi loại thiết bị. Tất cả các giá trị của Media Type bao gồm

  • All: Dùng cho tất cả các loại Media Type
  • Aural: Dùng cho speech and sound synthesizers
  • Braille: Dùng cho các devices liên quan đến chữ nổi (braille)
  • Embossed: Dùng cho các loại máy in các trang braille
  • Handheld: Dùng cho các thiết bị nhỏ, thiết bị cầm tay
  • Print: Dùng cho máy in
  • Projection: Dùng cho các loại máy chiếu
  • Screen: Dùng cho computer screen
  • Tty: Dùng cho các thiết bị sử dụng fixed-pitch character grid
  • Tv: Dùng cho các loại TV

Ta có thể sử dụng Media Type theo cú pháp sau đây:

@media media_type {rules}

Chẳng hạn như ta có đoạn code sau:

/*Áp dụng cho computer screens*/
@media screen {
  body {
    width: 960px;
  }
}
/*Áp dụng cho các thiết bị cầm tay nhỏ*/
@media handheld {
  body {
    width: 320px
  }
}

Chú ý rằng từ HTML5 thì giá trị default của media type là all, thế nên mặc định thì các CSS rules của bạn viết sẽ được áp dụng cho tất cả các loại màn hình.

Media Query Syntax

Cú pháp của Media Query được mở rộng ra từ cú pháp của Media Type như sau:

@media media_type (feature:value) { rules }

Các thuộc tính feature và value sẽ giúp chúng ta xác định chính xác từng loại màn hình mà ta mong muốn.

Đôi khi có những Media Feature mà một mình nó đứng không cũng có ý nghĩa, mà không cần đến value, thì cú pháp của ta sẽ như sau:

@media media_type (feature) { rules }

Ngoài ra thì như đã nói mặc định của Media Type sẽ luôn là all, thế nên ta có thể lược bỏ phần media_type ở trên nếu muốn nó được apply cho tất cả các devices.

Một số Media Feature quan trọng

  • widthheight: Nếu sử dụng feature này thì các css rules sẽ chỉ được áp dụng cho những browser có chiều rộng hoặc chiều cao đúng với thông số mà ta đã đưa ra. Chẳng hạn như @media (width: 900px) {rules} thì sẽ chỉ áp dụng cho những browser nào có kích cỡ chiều rộng đúng bằng 900px. Thế nên hai feature này rất ít khi được sử dụng. Thay vào đó người ta thêm các tiền tố min- hay max- và để được các feature sau: min-widthmin-heightmax-widthmax-height. Đây là feature cho phép ta thiết lập những rules cho những browser có chiều rộng hay chiều dài nằm trong một khoảng nào đó. Ví dụ:
/*Áp dụng cho những browser có chiều rộng <= 900px*/
@media (max-width: 900px) { body {font-size: 16px;} }
/*Áp dụng cho những browser có chiều rộng >= 600px*/
@media (min-width: 600px) { body {font-size: 14px;} }
/*Áp dụng cho những browser có chiều rộng >= 800px*/
@media (min-width: 800px) { body {font-size: 15px;} }
/*Áp dụng cho những browser có chiều rộng <= 700px*/
@media (max-width: 700px) { body {font-size: 13px;} }

Cần chú ý là những rules khai báo sau sẽ đè lên những rules khai báo trước, vậy nên với đoạn code bên trên thì nếu browser của bạn có chiều rộng là 650px thì rule được áp dụng ở đây sẽ là font-size: 13px;, còn chiều rộng là 750px thì rule được áp dụng sẽ là font-size: 15px;.

  • device-widthdevice-heightdevice-min-widthdevice-max-widthdevice-min-heightdevice-max-height: Cũng giống như widthheight hay min-widthmin-heightmax-widthmax-height, thế nhưng với việc thêm device- ở phía trước thì các tính toán sẽ được dựa trên kích cỡ của thiết bị, thay vì kích cỡ của browser.
  • aspect-ratio và device-aspect-ratio: Đây là những feature cho phép ta áp dụng các rules dựa trên tỉ lệ của browser hay tỉ lệ của thiết bị. Ta có thể dùng các thông số như 16/9 hay 16/10, hoặc có thể viết cả kích cỡ cụ thể ra cho dễ đọc như 1280/720 chẳng hạn. Hai feature này cũng có thể sử dụng các tiền tố min- hay max-
  • resolution: Đây là những feature đánh giá dựa trên độ phân giải của màn hình device (đương nhiên là không có độ phân giải cho browser rồi). Feature này cũng có thể sử dụng các tiền tố min- hay max-. Ví dụ:
/*Sử dụng đơn vị là dpi: dots per inch*/
@media (max-resolution: 300dpi) { body {font-size: 15px;} }
/*Sử dụng đơn vị là dpcm: dots per centimeter*/
@media (min-resolution: 600dpcm) { body {font-size: 14px;} }
  • orientation: Đây là những feature đánh giá dựa trên trạng thái của thiết bị đang là là portrait (xoay dọc: khi mà chiều dài >= chiều rộng, hay là landscape (quay ngang: chiều dài < chiều rộng). Ví dụ
/*Áp dụng khi device để dọc*/
@media (orientation: portrait) { body {font-size: 14px;} }
/*Áp dụng khi device để ngang*/
@media (orientation: landscape) { body {font-size: 15px;} }
  • Ngoài ra còn một số features khác, mà có thể ít được sử dụng hơn, đó là colorcolor-indexmonochromescan và grid
/*Áp dụng cho màn hình màu*/
@media (color) { body {font-size: 14px;} }
/*Áp dụng cho màn hình có ít nhất 256 màu*/
@media (min-color-index: 256) { body {font-size: 15px;} }

Ta có thể ghép nhiều media feature vào trong một câu lệnh kiểm tra bằng toán tử and hoặc , (mang ý nghĩa của phép or). Ngoài ra ta cũng có thể sử dụng not hoặc only. Khi ta viết

@media (color) { body {font-size: 14px;} }

như ở trên thì do all được mặc định lược bỏ, nên nó tương đương với

@media all and (color) { body {font-size: 14px;} }

Ngoài ra ta có các ví dụ khác như sau:

/*Áp dụng cho browser có chiều rộng >=800px và <= 900px*/
@media (max-width: 900px) and (min-width: 800px) { body {font-size: 14px;} }
/*Áp dụng cho màn hình nằm ngang hoặc có chiều rộng >=1200px */
@media (orientation: landscape), (device-min-width: 1200px) { body {font-size: 15px;} }
/*Áp dụng cho màn hình có tỉ lệ không phải là 4/3*/
@media not (device-aspect-ratio: 4/3) { body {font-size: 15px;} }

Sử dụng Media Query hiệu quả

Có 3 cách để sử dụng Media Query. Cách thứ nhất, như đã đề cập ở phía trước, đó là sử dụng từ khoá @media để tính toán rules bên trong một stylesheet:

@media (expression) { body {font-size: 15px} }

Cách thứ hai đó là khai báo trong tag link với thuộc tính là media. Như vậy ta có thể gọi đến hẳn mốt stylesheet bên ngoài.

<!--Sẽ load external stylesheet được khai báo nếu thoả mãn điều kiện của media feature -->
<link href="external files link" rel="stylesheet" media="all and (expression)">

Cách thứ 3 đó là sử dụng từ khoá @import để load một external stylesheet bên trong một external stylesheet.

/* Sẽ load external stylesheet được khai báo nếu thoả mãn điều kiện của media feature */
@import url('file') all and (expression);

Nên dùng Media Query để gọi đến external stylesheet nếu có thể. Nếu có thể hãy viết tách bạch những CSS rules dành cho những thiết bị khác nhau ra những stylesheet khác nhau, sau đó gọi qua tag link của html như đã đề cập ở trên. Nó sẽ giúp cho công việc quản lý và chỉnh sửa sau này trở nên dễ dàng hơn. Đương nhiên bạn nên viết một stylesheet chung cho tất cả các device/browser trước, sau đó sẽ load riêng các stylesheet cho từng loại khác nhau, và những rules mới được load sẽ đè lên những rules cũ. Vì thế ta chỉ cần khai báo những CSS rules mà thực sự cần thay đổi với từng loại device/browser mà thôi.

Nên viết, và load CSS rules của Desktop (những thiết bị có màn hình rộng) trước hay là Mobile (những thiết bị có màn hình bé) trước ? Chắc nhiều người sẽ nghĩ ngay đến việc nên thiết kế cho Desktop trước, bởi dù gì cũng dễ hơn, thuận lợi cho việc test hơn … Thế nhưng đúng ra là nên viết cho Mobile trước. Chẳng hạn khi ta cần viết CSS cho các thiết bị mobile và desktop, thì trước hết ta nên viết một file là basic.css, và nó chứa rules dành cho thiết bị mobile. Sau đó viết một file là desktop.css và nó chứa rules dành cho các thiết bị có màn hình lớn. Và ta sẽ load như sau:

<link href="basic.css" rel="stylesheet" media="all">
<link href="desktop.css" rel="stylesheet" media="min-device-width: 640px">

Tại sao lại nên làm như vậy ?

Đó là bởi giao diện dành cho những thiết bị màn hình lớn bao giờ cũng chứa những hình ảnh với kích cỡ to, và độ phân giải cao hơn so với những thiết bị màn hình nhỏ. Do đó nếu ta để những rules dành cho Desktop vào basic, và load trước thì bao giờ những assets có dung lượng tương đối lớn đó cũng được load. Giả dụ như ta có thêm trường display: none vào để ẩn nó đi trên những màn hình nhỏ đi chăng nữa thì nó vẫn được load vào lưu vào cache, điều đó dẫn đến tốc độ duyệt trang web của ta sẽ bị ảnh hưởng khi sử dụng các thiết bị mobile.

Bởi vậy, nếu bạn muốn hiển thị nhiều hình ảnh cho Desktop thì hãy viết ra một external stylesheet riêng, và hãy thiết lập Media Query để nó chỉ được load khi thiết bị truy cập có màn hình lớn mà thôi.