Nội dung bài viết
Bài viết được tham khảo và viết lại dựa trên bài gốc của tác giả ishadeed
Khi các bạn code giao diện cho một dự án nào đó chẳng hạn, các bạn sẽ thấy rằng để làm khoảng cách giữa các phần tử thì sẽ có nhiều cách như margin hoặc padding hay gọi chung là spacing. Tuy nhiên mình thấy nhiều bạn mới học thì hay bị rối giữa việc dùng 2 thứ này, hôm nay mình lại tiếp tục research tìm nội dung về nó để viết cho các bạn, hi vọng sẽ giúp ích được cho các bạn phần nào trong việc cải thiện kiến thức hơn, thông suốt hơn về spacing để có thể làm chủ việc code tốt hơn.
# Các loại spacing
Như mình đã nói ở trên thì trong CSS có 2 loại spacing đó chính là outer-space và inner-space mà chúng ta hay gặp. Trong bài viết này mình gọi tạm là outer và inner cho dễ hiểu nhé. Ví dụ như hình dưới đây khoảng trống bên ngoài là outer và bên trong là inner.
Ví dụ ở trên có class là element
đi thì chúng ta có thể có CSS đơn giản như này với inner là padding
và outer là margin
. Đơn giản đúng không nào ?
.element { padding: 20px; margin-bottom: 20px; }
Tuy nhiên không chỉ đơn giản như vậy đâu, nó còn nhiều trường hợp khác thú vị lắm, chúng ta sẽ cùng nhau tìm hiểu tiếp dưới đây nhé.
# Margin
Margin thường được sử dụng khi các bạn muốn tạo khoảng cách giữa phần tử này so với các phần tử khác. Như ví dụ ở trên thì mình có dùng margin-bottom: 20px
để tạo ra khoảng cách so với phần tử ở dưới.
Chắc các bạn cũng đã biết là margin có thể sử dụng ở 4 hướng (top right bottom left), và chúng ta nên nắm rõ những thứ cơ bản này để có thể áp dụng chúng tốt vào trong dự án thực tế được.
Vấn đề margin collapse
Hiểu đơn giản là margin collapse xảy ra khi chúng ta có 2 phần tử nằm hàng dọc và có margin và một trong số chúng có margin lớn hơn cái còn lại. Trong trường hợp này thằng nào có margin lớn hơn sẽ được sử dụng và thằng còn lại sẽ bị bỏ qua. Các bạn xem hình nhé.
Các bạn thấy phần tử ở trên có margin-bottom: 50px
và thằng ở dưới có margin-top: 30px
thì khoảng cách lúc này không phải là 80px như các bạn nghĩ đâu mà là 50px do thằng ở trên có margin lớn hơn, và điều đó tạo nên một thứ chính là margin collapse.
Và để giải quyết vấn đề này thì người ta khuyến khích chỉ sử dụng một một hướng mà thôi ví dụ các bạn muốn khoảng cách giữa chúng là 80px thì chỉ cần dùng margin-bottom: 80px
là đủ, tuy nhiên nếu code .element {margin-bottom: 80px}
thì cái cuối cùng sẽ có khoảng trống dư thừa cho nên để fix cái này chúng ta sẽ dùng :not(:last-child)
.element:not(:last-child) { margin-bottom: 80px; }
Một ví dụ khác nữa cũng khá thú vị đó là mối quan hệ giữa phần tử cha và con bên trong. Giả sử ta có HTML và CSS như sau
<div class="parent"> <div class="child">I'm the child element</div> </div>
.parent { margin: 50px auto 0 auto; width: 400px; height: 120px; } .child { margin: 50px 0; }
Các bạn thấy rằng phần tử con có margin: 50px 0
nhưng lại không cách ra phía trên so với phần tử cha bao ngoài, đó là vì margin collapse của thằng cha gây ảnh hưởng lên thằng con. Để giải quyết trường hợp này thì chúng ta có thể CSS cho thằng con thành display: inline-block
hoặc hay hơn là thiết lập cho thằng cha padding-top: 50px
chẳng hạn là ok.
Negative Margin
Tức là sử dụng số âm trong giá trị của margin. Nó thật sự hữu ích trong nhiều trường hợp giả sử mình có cấu trúc giao diện như hình với padding bao quanh, làm cho phần tử con bị thu vào.
Nhưng cái chúng ta muốn là phần tử con rộng 100% của phần tử cha nhưng không được bỏ padding của phần tử cha đi thì phải làm sao. Lúc này negative margin sẽ là cứu tinh cho chuyện này, do phần tử cha có padding: 1rem
nó đẩy phần tử con vào, cho nên lúc này ở phần tử con mình cho margin số âm top left và right giá trị ngược lại 1rem là -1rem để nó giãn ra 100% của phần tử cha và dính trên cùng.
.parent { padding: 1rem } .child { margin-left: -1rem; margin-right: -1rem; margin-top: -1rem; }
# Padding – Inner Spacing
Như mình đã nói từ lúc đầu thì padding
hay còn gọi là inner bên trong phần tử. Nó thì được sử dụng ở nhiều trường hợp lắm. Ví dụ như hình dưới đây minh hoạ khi chúng ta dùng padding cho thẻ a
để phạm vi click của thẻ a
được mở rộng hơn
Padding không hoạt động
Có một điều quan trọng là padding top
và padding-bottom
sẽ không hoạt động nếu phần tử các bạn đang làm có display: inline
như là thẻ <span>
hay là thẻ <a>
. Nếu padding được thêm vào nó sẽ không ảnh hưởng tới phần tử. Để giải quyết vấn đề này thì các bạn có thể dùng thuộc tính display với giá trị khác như là inline-block
hoặc block
là oke thôi.
.element span { display: inline-block; padding-top: 1rem; padding-bottom: 1rem; }
# Một vài ví dụ thực tế
Xử lý với margin bottom
Giả sử chúng ta có một layout như thế này, và mỗi phần tử đều có margin-bottom: 20px
và các bạn thấy rằng phần tử cuối cũng có như vậy là sai vì ở đây mình chỉ muốn khoảng cách giữa các phần tử mà thôi chứ cái cuối cùng không có.
Vậy làm sao để giải quyết trường hợp này ? Chúng ta sẽ dùng :not(:last-child)
như sau
.element:not(:last-child) { margin-bottom: 20px; }
Tuy nhiên cách này chỉ chạy đúng khi hiển thị một cột, nhưng nếu giao diện là 2 cột thì lúc này nó không hề đúng, ở đây là cái số 4 vẫn có margin bottom
Và một cách tốt nhất để giải quyết nó là ở thằng cha bọc ngoài cho margin-bottom
số âm bằng chính margin bottom của thằng con như sau
.wrapper { margin-bottom: -20px; }
Card Component
Ví dụ chúng ta có hình như thế này, làm sao nhìn vào một một giao diện đơn giản như này thì chúng ta phân biệt được ở đâu xài margin, ở đâu xài padding.
Và hình dưới đây sẽ cho bạn thấy, bạn có nghĩ giống mình không nào?
<article class="card"> <a href="#"> <div class="card__thumb"><img src="food.jpg" alt=""></div> <div class="card__content"> <h3 class="card__title">Cinnamon Rolls</h3> <p class="card__author">Chef Ahmad</p> <div class="card__rating"><span>4.9</span></div> <div class="card__meta"><!-- --></div> </div> </a> </article>
.card__content { padding: 10px; } .card__title, .card__author, .card__rating { margin-bottom: 10px; }
Với code như này ta có kết quả như trên, tuy nhiên chỗ card__meta
có border phía trên lúc này ta có thể code như sau
.card__meta { padding-top: 10px; border-top: 1px solid #e9e9e9; }
Tuy nhiên kết qủa lại ra không như mong đợi, vì do padding của content bao ngoài làm cái border bị thụt vào bên trong như hình
Lúc này ta nhanh trí nghĩ ra cách dùng margin số âm cho nó kéo ra lại như mình đã trình bày trước đó như sau
.card__meta { padding-top: 10px; border-top: 1px solid #e9e9e9; margin: 0 -10px; }
Nhưng được cái border nhưng content lại dính sát lề, hết lỗi này đến lỗi khác
Để giải quyết vấn đề này, các bạn chỉ cần thêm padding left và right vào card__meta là sẽ được kết quả tuyệt vời thôi.
.card__meta { padding: 10px 10px 0 10px; border-top: 1px solid #e9e9e9; margin: 0 -10px; }
# Tạm kết
Hi vọng với những kiến thức cơ bản nhưng bổ ích này sẽ giúp ích cho các bạn phần nào cải thiện kiến thức nhé. Đừng quên xem demo ở đây nhé..
Cảm ơn anh vì bài viết hữu ích ạ.
Cám ơn em nà <3
cảm ơn vì bài viết hữu ích
Bài viết rất thú vị và bổ sung cho em nhiều kiến thức. Cảm ơn a Tuấn Anh
Bài viết rất chi tiết. Cám ơn bạn nhiều