Margin trong CSS có vẻ đơn giản ngay từ thời điểm đầu tiên bạn biết nó. Margin áp dụng cho một phần tử, nó tạo thành một khoảng trống xung quanh phần tử đấy, đẩy xa các phần tử khác.
-
Bạn có thể hiểu Margin là Lề
Tuy nhiên, Margin có nhiều thứ có thể bạn chưa biết.
Một trong những điều đầu tiên mà hầu hết chúng ta học được khi học CSS, là chi tiết về các phần khác nhau của một hộp trong CSS, được mô tả là CSS Box Model.
Một trong những yếu tố trong Box Model là Margin, đó một vùng trong suốt xung quanh box, nó sẽ đẩy các phần tử khác ra khỏi nó.
Các thuộc tính margin-top, margin-right, margin-bottom và margin-left được mô tả lại ngay trong CSS1, cùng với kiểu viết tắt margin để thiết lập cả bốn thuộc tính cùng một lúc.
-
Cú pháp: marign: top right bottom left;
-
margin: 10px; tương đương margin: 10px 10px 10px 10px;
-
margin: 10px 20px; tương đương margin: 10px 20px 10px 20px;
Margin mặc dù khá đơn giản nhưng có một số thứ xảy ra có thể khiến bạn khó nắm bắt. Trong bài này chúng ta sẽ cùng tìm hiểu và xử lý chúng khi viết CSS.
Tất tần tật về Margin trong CSS
Cụ thể, chúng ta sẽ xem xét cách các margin tương tác với nhau và cách margin collapsing thực sự hoạt động như thế nào.
CSS Box Model là gì?
Box Model đề cập đến cách các phần khác nhau của hộp như:
-
content (nội dung)
-
padding (phần đệm giữa nội dung và đường viền)
-
border (đường viền)
-
margin (lề)
được trình bày và tương tác với nhau.
Trong CSS1, Box Model được trình bày chi tiết như hình bên dưới:
Mô tả CSS Box Model trong CSS1
Bốn thuộc tính lề cho mỗi bên của box và cách viết tắt của margin đều được xác định trong CSS1.
Trong đặc tả CSS2.1 có hình minh họa để thể hiện Box Model và cũng xác định các thuật ngữ chúng ta vẫn sử dụng để mô tả các box khác nhau.
Thông số kỹ thuật mô tả content box, padding box, border box và margin box, mỗi box được xác định bởi các cạnh của nội dung, phần đệm, đường viền và lề tương ứng.
Mô tả CSS Box Model trong phiên bản CSS2.1
Hiện tại đã có đặc tả CSS Box Model 3 nhưng đang là bản nháp.
Do đó, chúng ta sẽ sử dụng định nghĩa trong CSS2 cho phần lớn bài viết này.
Margin Collapsing là gì?
Đặc tả CSS1, đã xác định margin, cũng xác định Margin Collapsing.
Margin Collapsing là vấn đề tự động thu gọn lề trong một số trường hợp:
-
Phần tử cha mẹ với phần tử con đầu tiên hoặc phần tử con cuối cùng
Chúng ta hãy xem xét từng trường hợp xảy ra Margin collapsing.
Tình huống #1: Tự động thu gọn margin của phần tử anh chị em liền kề
Nếu bạn có hai phần tử hiển thị lần lượt từng phần tử trong luồng bình thường, lề dưới của phần tử bên trên chồng với lề trên của phần tử phía dưới.
Trong ví dụ CodePen dưới đây, chúng ta có ba phần tử div.
-
Div đầu tiên có lề trên (margin-top) và lề dưới (margin-bottom) là 50 pixel.
-
Div thứ hai có lề trên (margin-top) và lề dưới (margin-bottom) là 20px.
-
Div thứ ba có lề trên (margin-top) và lề dưới (margin-bottom) là 3em.
Lề giữa div 1 và div 2 là 50 pixel (chứ không phải 70px). Vì lề trên của div thứ hai nhỏ hơn nên nó được kết hợp với lề dưới của div đầu tiên.
Lề giữa div thứ 2 và div thứ 3 là 3em, vì 3em lớn hơn 20px (margin-bottom của div thứ hai)
See the Pen VD1: Margin Collapsing by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Tình huống #2: Tự động thu gọn Margin của hộp trống hoàn toàn
Nếu một hộp trống, thì lề trên và lề dưới của nó có thể bị thu gọn.
Trong ví dụ CodePen sau đây, phần tử có class empty có lề trên và lề dưới là 50 pixel. Còn 2 phần tử có class là box thì không thiết lập margin.
Tuy nhiên, khoảng cách thực tế giữa các 2 phần tử thứ nhất và thứ ba không phải là 100px, mà là 50px.
Điều này là do hai lề bị thu gọn lại.
Nếu bạn thêm bất cứ thứ gì vào box đó (thậm chí là thêm padding) sẽ khiến cho lề trên và lề dưới được sử dụng và không bị thu gọn.
See the Pen VD2: Lề chồng lấn trong phần tử trống by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Tình huống #3: Margin thu gọn giữa phần tử cha mẹ và phần tử con đầu tiên hoặc phần tử con cuối cùng
Đây là tình huống lề bị thu gọn thường xuyên gặp phải nhất, là nó không dễ thấy bằng mắt thường.
Trong ví dụ CodePen sau, mình có một div với một class wrapper, và mình đã cho rằng div đó một outline màu đỏ để bạn có thể thấy nó ở đâu.
Mình thiết lập cho ba phần tử con của wrapper đều có một margin: 50px;
Tuy nhiên, phần tử con đầu tiên (first child) và phần tử con cuối cùng (last child) thực tế lại không có lề cách 50px với phần tử wrapper.
See the Pen VD3: Lề chồng lấn với phần tử cha và phần tử con đầu tiên, cuối cùng by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Điều này là do lề của phần tử con bị thu gọn với bất kỳ lề nào trên phần tử cha.
Do đó lề nằm ở bên ngoài của phần tử cha (Lề này sẽ đẩy ra khoảng cách với phần tử nằm trên / dưới phần tử cha wrapper)
Bạn có thể thấy rõ nếu bạn kiểm tra phần tử đầu tiên bằng DevTools. Vùng màu vàng nổi bật chính là lề.
Kiểm tra lề (margin) bằng DevTools
Tình huống thứ 3 này cũng nêu bật ý nghĩa của Margin Collapsing.
Trong CSS2, chỉ các lề dọc được chỉ định để thu gọn - đó là lề trên và dưới trên một phần tử nếu bạn ở chế độ viết ngang.
Vì vậy, lề trái và phải của cả 3 phần tử ở trên không bị thu gọn và cách wrapper đúng bằng 50px.
Những thứ ngăn chặn Margin Collapsing
Margin không bao giờ thu gọn nếu một phần tử có vị trí tuyệt đối (position: absolute;), hoặc được float.
Tuy nhiên, giả sử bạn không muốn việc thu gọn xảy ra. Vậy làm cách nào để ngăn chặn nó?
Điều đầu tiên ngăn chặn margin collapsing là có một cái gì đó giữa chúng.
Ví dụ: Một hộp hoàn toàn trống sẽ không thu bị thu gọn lề trên và lề dưới của nó nếu nó được thiết lập đường viền (border) hoặc phần đệm (padding).
Trong ví dụ dưới đây, mình đã thêm padding: 1px; vào phần tử trống có class là empty. Hiện tại nó có một lề 50 pixel ở trên và 50px ở dưới.
See the Pen VD1: Ngăn chặn Margin collapsing by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Điều này có logic phía sau nó, nếu hộp là hoàn toàn trống rỗng không có đường viền (border) hay phần đệm (padding) thì bản chất của nó là vô hình.
Đây là một phần tử không có tác dụng gì.
Nếu bạn không muốn đều này xảy ra. Hãy thêm bất cứ cái gì vào phần tử trống này.
Hành vi tương tự có thể xảy ra trong tình huống thứ #3.
Nếu chúng ta thêm một đường viền (border) cho phần tử cha, margin của phần tử con sẽ nằm ở bên trong, như ví dụ codepen dưới đây:
See the Pen VD2: Ngăn chặn Margin Collapsing by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Một lần nữa, đây là một hành vi logic.
Nếu bạn có phần tử wrapper nhưng thiết lập nó trống, có thể bạn không muốn có thêm khoảng trống trên màn hình hiển thị.
Điều này rất có ý nghĩa khi trang web của bạn chủ yếu là văn bản.
Nó ít hữu ích như hành vi khi chúng ta đang sử dụng các phần tử để bố trí một thiết kế.
Định nghĩa bối cảnh cho một khối để ngăn chặn Margin Collapsing
Định nghĩa bối cảnh cho một khối (Block Formatting Context (BFC)) cũng sẽ ngăn chặn lề tự động thu gọn.
Nếu chúng ta nhìn lại tình huống thứ #3:
Phần tử con đầu tiên và phần tử con cuối cùng kết thúc với lề của chúng nằm ở bên ngoài phần tử cha.
Nếu chúng ta thiết lập cho phần tử cha display: flow-root; để tạo ra bối cảnh cho khối này, các lề sẽ nằm ở bên trong.
See the Pen Định nghĩa bối cảnh cho block để ngăn chặn Margin collapsing by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Thiết lập overflow: auto; thì cũng nhận được hiệu quả tương tự, mặc dù nó cũng có thể tạo ra scrollbars mà có thể bạn không muốn.
FLEX và GRID containers
Flex và Grid containers thiết lập định dạng ngữ cảnh Flex và Grid cho phần tử con của chúng, vì thế, chúng có hành vi khác nhau để bố trí khối.
Một trong những sự khác biệt là vấn đề lề thu gọn sẽ không xảy ra.
Một flex container thiết lập một bối cảnh định dạng flex mới cho nội dung của nó. Điều này giống như việc thiết lập bối cảnh định dạng block, ngoại trừ việc bố trí flex được sử dụng thay vì bố trí block.
Ví dụ, float không xâm nhập vào flex container và lề của flex container không bị thu gọn với lề nội dung của nó.
Flexbox Level1
Nếu chúng ta lấy ví dụ ở trên và thiết lập wrapper thành một flex container (display: flex;), hiển thị các item với kiểu flex-direction: column; bạn có thể thấy rằng các lề hiện được chứa bởi wrapper.
Ngoài ra, lề giữa các flex item liền kề không bị thu gọn với nhau, vì vậy giữa các item chúng cách nhau 100px.
Đó là tổng 50px ở top và 50px bottom của các item.
See the Pen Lề của Flex item không bị thu gọn by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Chiến lược thiết lập Margin cho website của bạn
Do lề bị thu gọn, nên cần có một ý tưởng tốt để đưa ra một cách xử lý nhất quán với lề trong trang web của bạn.
Điều đơn giản nhất để làm là chỉ xác định lề trên (margin-top) hoặc lề dưới (margin-bottom) của các phần tử.
Theo cách đó, bạn không nên chạy vào các vấn đề sụp đổ lề quá thường xuyên vì bên có lề sẽ luôn liền kề với một bên mà không có lề.
Giải pháp này không giải quyết được các vấn đề mà bạn có thể gặp phải với vấn đề thu gọn lề của phần tử con trong phần tử cha.
Vấn đề cụ thể đó có xu hướng ít phổ biến hơn, và hiểu tại sao vấn đề này xảy ra giúp bạn đưa ra giải pháp cụ thể.
Một giải pháp lý tưởng cho điều đó là thiết lập cho phần tử đó display: flow-root;
Trong các trình duyệt cũ hơn thì bạn có thể dùng overflow: auto;
Hoặc biến phần tử cha của nó thành một flex hoặc grid container.
Thậm chí có thể thêm padding để ngăn chặn vấn đề tự động thu gọn lề này.
Đừng quên rằng bạn có thể sử dụng caniuse để biết rõ display: flow-root; được hỗ trợ chính xác trên các phiên bản trình duyệt nào.
Hầu hết thời gian, hãy hiểu tại sao Margin Collapsing quan trọng và không quan trọng.
Sau đó, bạn có thể tìm ra từng trường hợp và làm thế nào để đối phó với nó.
Dù bạn lựa chọn phương pháp gì, hãy luôn chia sẻ thông tin với team của mình.
Vì vấn đề Margin collapsing thường không rõ ràng, vì thế, phương pháp bạn sử dụng để ngăn chặn nó cũng không rõ ràng.
Lúc này, nên có một comment tại đó để giúp team của bạn hiểu bạn đang làm gì.
Và thêm một điều nữa đề làm bài viết này trọn vẹn hơn.
Sử dụng Tỷ lệ phần trăm cho Margin
Khi bạn sử dụng tỷ lệ phần trăm trong CSS, nó phải là tỷ lệ phần trăm của một cái gì đó.
Các margin (và padding) được đặt bằng tỷ lệ phần trăm sẽ luôn là tỷ lệ phần trăm của kích thước nội tuyến (chiều rộng ở chế độ viết ngang) của phần tử cha mẹ.
Hãy xem ví dụ bên dưới đây:
See the Pen Sử dụng tỷ lệ phần trăm cho Margin by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Trong ví dụ CodePen ở trên, mình có một wrapper rộng 200px, bên trong là một box có margin: 10%;, có nghĩa là lề bằng 20px ở tất cả các mặt, nó chiếm 10% của 200px.
Xem xét Margin theo dòng chảy thực tế
Chúng ta đã nói về lề dọc (vertical margin) trong suốt bài viết này, tuy nhiên, CSS hiện đại có xu hướng suy nghĩ về mọi thứ theo một dòng chảy hơn là một theo cách vật lý.
Do đó, khi chúng ta nói về lề dọc, chúng ta thực sự đang nói về lề trong kích thước khối.
Các lề đó sẽ ở trên và dưới nếu chúng ta ở chế độ viết ngang (horizontal writing mode), nhưng sẽ ở bên phải và bên trái trong chế độ viết dọc (vertical writing mode) được viết từ trái sang phải.
Khi làm việc với logic, hãy đi theo dòng chảy tương đối, bất kể việc chế độ viết là gì, việc nói về block start và block end sẽ dễ dàng hơn, thay vì top và bottom.
Đối với chúng ta hay đọc từ trái qua phải thì chế độ viết ngang như là mặc định.
Nhưng đối với các nền văn hóa khác nhau họ đọc từ phải qua trái và viết từ trên xuống dưới...
Chính vì thế, xem xét trong dòng chảy sẽ mang tính tổng quát hơn là trên / dưới / trái / phải.
Để hiểu rõ điều này hơn CSS đã giới thiệu đặc tả logic và các giá trị logic. Nó sẽ giúp bạn hiểu hơn về dòng chảy trong CSS.
Đối với margin, điều này giúp chúng ta ánh xạ thuộc tính như sau:
-
margin-top = margin-block-start
-
margin-right = margin-inline-end
-
margin-bottom = margin-block-end
-
margin-left = margin-inline-start
Chúng ta cũng có 2 cách viết tắt sau:
Trong ví dụ CodePen tiếp theo, mình đã sử dụng các thay đổi chế độ viết, bạn có thể thấy cách các lề chạy theo hướng văn bản thay vì được gắn hướng vật lý top / right / bottom / left
See the Pen Margin theo dòng chảy thực tế by NIIT -ICT Hà Nội (@niiticthanoi) on CodePen.
Bạn có thể đọc thêm về CSS Logical Properties and Value trên MDN
Bạn đã hiểu hơn về Margin trong CSS chưa?
Như vậy chúng ta đã cùng nhau đi tìm hiểu tất cả về Margin trong CSS:
-
Bạn đã hiểu Margin Collapsing là gì. Hiểu tại sao nó xảy ra, tại sao nó không xảy ra sẽ giúp bạn bố trí layout tốt hơn.
-
Thiết lập margin theo một cách duy nhất giúp bạn đỡ đau đầu hơn.
-
Với bất cứ những gì bạn xử lý margin, hãy để lại comment cho đồng đội của mình (hoặc cho chính mình).
-
Suy nghĩ về dòng chảy thực tế chứ không phải là kích thước vật lý (top / right / bottom / left) giúp bạn viết web logic hơn.
CSS chỉ là một phần của trang web. Nếu bạn muốn nắm rõ hơn về CSS cũng như lập trình web. KHÓA HỌC PHP FULL STACK này sẽ giúp bạn hoàn thiện cả Front end và Back end.
Hãy hành động ngay!
---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #php