NỘI DUNG BÀI VIẾT
Media Query là gì?
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.
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}
Code language: CSS (css)
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
}
}
Code language: CSS (css)
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 }
Code language: CSS (css)
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 }
Code language: CSS (css)
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
width
,height:
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ằng900px
.- 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-
haymax-
và để được các feature sau:min-width
,min-height
,max-width
,max-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;} }
Code language: CSS (css)
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-width
,device-height
,device-min-width
,device-max-width
,device-min-height
,device-max-height
: Cũng giống nhưwidth
,height
haymin-width
,min-height
,max-width
,max-height
, thế nhưng với việc thêmdevice-
ở 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-
haymax-
- 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-
haymax-
. 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;} }
Code language: CSS (css)
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;} }
Code language: CSS (css)
- Ngoài ra còn một số features khác, mà có thể ít được sử dụng hơn, đó là
color
,color-index
,monochrome
,scan
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;} }
Code language: CSS (css)
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;} }
Code language: CSS (css)
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;} }
Code language: CSS (css)
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;} }
Code language: CSS (css)
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} }
Code language: CSS (css)
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)">
Code language: HTML, XML (xml)
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);
Code language: CSS (css)
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">
Code language: HTML, XML (xml)
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.
Media Query hoạt động như thế nào?
Media Query sử dụng @media
để áp dụng một khối thuộc tính css chỉ khi thoả mãn một điều kiện nào đó.
Ví dụ:
Trong ví dụ trên, thuộc tính background-color
chỉ được áp dụng cho thẻ body trong trường hợp độ rộng của màn hình nhỏ hơn 500px.
Xem ví dụ ở đây (hãy thu nhỏ trình duyệt để xem hiệu ứng): http://demo.codegym.vn/web/15/mediaqueries/color.html
Thêm các breakpoint
Breakpoint là các điểm mà chúng ta sử dụng để kích hoạt việc thay đổi bố cục của trang web. Chẳng hạn, ở ví dụ trước thì breakpoint của chúng ta là 500px của độ rộng.
Trong ví dụ sau đây, chúng ta sẽ sử dụng một breakpoint là 768px (độ rộng phổ biến của một tablet). Nếu độ rộng của trình duyệt nhỏ hơn hoặc bằng 768px thì tất cả các cột đều chiếm độ rộng 100% (có nghĩa là mỗi block sẽ chiếm một dòng).
/* For desktop: */
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
@media only screen and (max-width: 768px) {
/* For mobile phones: */
[class*="col-"] {
width: 100%;
}
}
Code language: CSS (css)
Xem ví dụ tại đây (thay đổi độ rộng của trình duyệt để thấy hiệu ứng): http://demo.codegym.vn/web/15/mediaqueries/responsive.html
Nên ưu tiên thiết kế cho thiết bị di động trước tiên (Mobile First)
Mobile First là cách thiết kế mà ở đó chúng ta ưu tiên cho các thiết bị di động trước, sau đó mới thêm mã CSS để trang web hiển thị tốt trên các thiết bị to hơn. Điều này sẽ giúp cho việc hiển thị các trang web ở trên các thiết bị di động được nhanh hơn. Tại sao?
Để làm được điều này, chúng ta thay đổi một chút trật tự của các khối CSS. Trong đó, đáng chú ý là thay vì sử dụng điều kiện max-width
thì chúng ta sử dụng min-width
.
/* For mobile phones: */
[class*="col-"] {
width: 100%;
}
@media only screen and (min-width: 768px) {
/* For desktop: */
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
}
Code language: CSS (css)
Thêm một breakpoint khác
Chúng ta có thể thêm nhiều breakpoint để đáp ứng được nhiều loại kích thước của cửa sổ trình duyệt khác nhau. Chẳng hạn, trong ví dụ trên, chúng ta đã thiết kế cho 2 trường hợp là máy tính cá nhân và máy tính bảng.
Trong ví dụ dưới đây, chúng ta sẽ thêm một trường hợp nữa cho điện thoại (thường là có kích thước nhỏ hơn 600px).
/* For mobile phones: */
[class*="col-"] {
width: 100%;
}
@media only screen and (min-width: 600px) {
/* For tablets: */
.col-m-1 {width: 8.33%;}
.col-m-2 {width: 16.66%;}
.col-m-3 {width: 25%;}
.col-m-4 {width: 33.33%;}
.col-m-5 {width: 41.66%;}
.col-m-6 {width: 50%;}
.col-m-7 {width: 58.33%;}
.col-m-8 {width: 66.66%;}
.col-m-9 {width: 75%;}
.col-m-10 {width: 83.33%;}
.col-m-11 {width: 91.66%;}
.col-m-12 {width: 100%;}
}
@media only screen and (min-width: 768px) {
/* For desktop: */
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
}
Code language: CSS (css)
Xem ví dụ ở đây (thay đổi kích thước trình duyệt để quan sát hiệu ứng): http://demo.codegym.vn/web/15/mediaqueries/responsive-3-breakpoints.html
Thích ứng với chiều xoay của màn hình
Media Query cũng có thể được sử dụng để giúp trang web hiển thị tốt với các chiều xoay khác nhau (ngang và dọc).
Ví dụ:
@media only screen and (orientation: landscape) {
body {
background-color: lightblue;
}
}
Code language: CSS (css)
Xem ví dụ ở đây (có thể mở ví dụ này trên điện thoại hoặc máy tính bảng và xoay thiết bị để xem hiệu ứng): http://demo.codegym.vn/web/15/mediaqueries/orientation.html
Kết luận
Qua đây là một số chia sẻ về CSS, mời bạn tiếp tục theo dõi các bài viết sau để hiểu rõ hơn về CSS.
Các bạn có thể tham khảo các bài viết hay về CSS tại đây.
Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.