- vừa được xem lúc

Cách sử dụng Grid và Flexbox trong CSS

0 0 221

Người đăng: Nguyen My Huyen

Theo Viblo Asia

Khi mới biết đến flex-box, mình thật sự choáng ngợp với sự tiện lợi của nó, đến mức cái gì cũng dùng flex-box, đến một ngày mình tự hỏi, ủa, vậy có cần grid nữa ko? Grid nên dùng lúc nào? Mình nghĩ chắc hẳn cũng có nhiều bạn có thắc mắc giống mình. Vậy chúng ta cùng làm sáng tỏ vấn đề ấy trong bài viết này nhé!

Trước tiên, chúng ta cần làm rõ sự khác biệt giữa Grid và Flexbox. Grid là một module bố cục đa chiều, tức là bao gồm nhiều hàng và cột. Flexbox có thể bố trí các phần tử con của nó dưới dàng hàng hoặc cột, nhưng không phải cả hai. Nếu bạn chưa hiểu về Grid và Flexbox, bạn có thể đọc thêm trong bài này https://ishadeed.com/article/learn-box-alignment/. Nếu bạn đã biết rồi, thật tuyệt, hãy đi sâu vào việc phân biệt chúng, cũng như khi nào nên sử dụng và lý do vì sao.

Điểm khác nhau giữa Grid và Flexbox

Trước tiên thì phải khẳng định rằng dù bạn dùng Grid hay Flexbox trong bất cứ trường hợp nào thì đều không sai. Bài viết này chỉ là khuyến nghị bạn nên dùng cái nào cho một trường hợp cụ thể.

/* Flexbox wrapper */
.wrapper { display: flex;
} /* Grid wrapper */
.wrapper { display: grid; grid-template-columns: 2fr 1fr; grid-gap: 16px;
}

Bạn có nhận thấy điều khác biệt không? Flexbox sắp xếp các phần tử thành 1 dòng (hoặc 1 cột, nếu muốn), trong khi Grid tạo một lưới các cột và hàng.

Làm sao để quyết định nên sử dụng cái nào

Quyết định dùng Grid hay Flexbox đôi khi có thể hơi khó, nhất là khi bạn mới làm quen với CSS. Dưới đây là một số câu hỏi mà chúng ta hay phân vân khi lựa chọn giữa chúng:

  • Hiển thị các phần tử con như thế nào? Một dòng hay dưới dạng cột và dòng?
  • Làm thế nào để các thành phần hiển thị đúng trên các kích thước màn hình khác nhau?

Hầu hết trường hợp, nếu bạn nhìn thấy một phần tử có tất cả các phần tử con hiển thị trên cùng 1 dòng, thì Flexbox là giải pháp tốt nhất. Giống như trong ví dụ này:

Tuy nhiên, nếu bạn nhìn thấy cả cột và hàng, thì Grid sẽ là giải pháp phù hợp hơn.

Giờ sau khi bạn đã hiểu sự khác biệt giữa chúng, chúng ta sẽ chuyển sang các ví dụ cụ thể hơn và tìm hiểu cách quyết định.

Các trường hợp sử dụng và ví dụ

Grid

Main và Sidebar

Đối với Sidebar và Main thì Grid là giải pháp hoàn hảo. Hãy xem bản mockup sau: Đây sẽ là cách ta CSS cho nó

/* HTML */
<div class="wrapper"> <aside>Sidebar</aside> <main>Main</main>
</div> /* CSS */
@media (min-width: 800px) { .wrapper { display: grid; grid-template-columns: 200px 1fr; grid-gap: 16px; } aside { align-self: start; }
}

Nếu align-self không được sử dụng cho <aside>, chiều cao của nó sẽ bằng với <main>, không quan trọng nội dung dài thế nào.

Cards

Bản thân cái tên Grid cũng đã giải thích ý nghĩa của nó, nên việc sử dụng nó để tạo 1 lưới card là cách sử dụng hoàn hảo.

.wrapper { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-gap: 16px;
}

Cột sẽ có độ rộng ít nhất là 200px, nếu khoảng cách không đủ, nó sẽ chuyển card sang dòng mới. Có điều có thể sẽ gây ra scroll ngang nếu độ rộng màn hình nhỏ hơn 200px. Giải pháp đơn giản là thêm độ rộng tối thiểu để áp dụng css:

@media (min-width: 800px) { .wrapper { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-gap: 16px; }
}

Section layout

Ví dụ như trong design bên dưới, chúng ta có thể sử dụng Grid 2 lần, một lần để chia thành 2 khu vực (phần contact us với phần form), lần thứ 2 để chia grid trong form.

@media (min-width: 800px) { .wrapper { display: grid; grid-template-columns: 200px 1fr; } .form-wrapper { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 16px; } .form-message, .form-button { grid-column: 1 / 3; /* để nó full độ rộng màn hình */ }
}

CSS Flexbox

Website Navigation

Website navigation nên được xây dựng bằng Flexbox. Phần lớn navigation đều theo mô típ logo ở bên trái, menu ở bên phải, rất phù hợp với flexbox.

.site-header { display: flex; flex-wrap: wrap; justify-content: space-between;
}

Dù cấu trúc navigation có thể khác biệt một chút ở các design, nhưng ta vẫn có thể set khoảng cách giữa các mục với thuộc tính justify-content.

Actions List

Khi nghe đến danh sách, thường thì ta hay nghĩ đến một danh sách dọc. Tuy nhiên, một danh sách có thể hiển thị trên 1 dòng, ví dụ như danh sách hành động trên Facebook hay Twitter. Nó bao gồm các nút hành động mà người dùng có thể thực hiện.

Như bạn thấy, các phần tử được hiển thị liên tiếp theo chiều ngang. Đó là một trong những cách sử dụng chính của Flexbox.

.actions-list { display: flex;
} .actions-list__item { flex: 1; /* mở rộng phần tử đồng thời chia đều độ rộng của phần tử cha cho mỗi phần tử */
}

Một biến thể khác là header và footer của modal

Cả header và footer của modal đều có phần tử con hiển thị trên 1 dòng. Khoảng cách giữa chúng sẽ được giải quyết đơn giản với flex.

Với modal header

.modal-header { display: flex; justify-content: space-between;
}

Còn với footer, nó sẽ khác một chút. Nút "Cancel" được thêm margin auto để đẩy nó sang bên phải.

.cancel__action { margin-left: auto;
}

Form elements

Sự kết hợp của 1 trường input cùng button bên cạnh như hình dưới đây cũng là 1 trường hợp nên sử dụng Flexbox

Trong form, trường input chiếm tất cả không gian còn lại, làm cho nó có chiều rộng động. Đó là vì ta sử dụng flex: 1 1 auto; cho thẻ input.

Bình luận cho bài viết

Một trường hợp khác cũng khá phổ biến là component bình luận cho bài viết như sau

Chúng ta có ảnh người dùng và bình luận của họ. Phần nội dung bình luận chiếm khoảng không gian còn lại của phần tử cha, tương tự ví dụ trên.

Nội dung trong card

Card thì có rất nhiều biến thể, nhưng phổ biến nhất là như sau

Ở bên trái, các phần tử con được xếp lần lượt từ trên xuống dưới, vì direction của flex đang là column. Phía bên phải thì ngược lại, direction được set là row.

.card { display: flex; flex-direction: column;
} @media (min-width: 800px) { .card { flex-direction: row; }
}

Một biến thể phổ biến khác của card là icon với text label bên dưới. Nó có thể là 1 button, link, hoặc thậm chí chỉ để trang trí.

Lưu ý là text và icon phải căn giữa theo chiều ngang hoặc chiều dọc. Nhờ có flexbox, điều đó rất đơn giản.

.card { display: flex; flex-direction: column; align-items: center;
}

Tương tự với kiểu hiển thị trên 1 dòng, ta chỉ cần bỏ dòng flex-direction: column;, vì direction row là mặc định.

Features List

Có một cái rất hay ho ở Flexbox là khả năng đảo ngược hướng phần tử.

.item { flex-direction: row-reverse;
}

Như trong mockup bên dưới, các phần tử chẵn sẽ được đảo ngược thứ tự. Flexbox rất hữu dụng.

Căn giữa nội dung của 1 component

Hãy tưởng tượng chúng ta có 1 component gồm nhiều phần tử và cần căn giữa nó, căn giữa theo chiều ngang thì khá đơn giản với text-align.

Nhưng với chiều dọc thì sao? Đơn giản!

.hero { display: flex; flex-direction: column; align-items: center; /* căn giữa theo chiều ngang */ justify-content: center; /* căn giữa theo chiều dọc */ text-align: center;
}

Kết hợp Grid và Flexbox

Trong thực tế thì layout thường bao gồm nhiều phần trong các ví dụ trên, nên ta có thể kết hợp sử dụng cả 2. Trường hợp dễ thấy nhất là một danh sách card sử dụng grid và nội dung bên trong card sử dụng Flexbox.

Đây là yêu cầu đối với layout này:

  • Độ dài của các card trong mỗi dòng phải bằng nhau
  • Link "Read more" phải ở cuối cùng của card, không quan trọng chiều cao của card.
  • Grid sử dụng minmax() .
/* HTML */
<div class="wrapper"> <article class="card"> <img src="sunrise.jpg" alt="" /> <div class="card__content"> <h2><!-- Title --></h2> <p><!-- Desc --></p> <p class="card_link"><a href="#">Read more</a></p> </div> </article>
</div> /* CSS */
@media (min-width: 500px) { .wrapper { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 16px; }
} .card { display: flex; /* [1] */ flex-direction: column; /* [2] */
} .card__content { flex-grow: 1; /* [3] */ display: flex; /* [4] */ flex-direction: column;
} .card__link { margin-top: auto; /* [5] */
}

Mình sẽ giải thích thêm về đoạn CSS trên:

  1. Áp dụng Flexbox cho card.
  2. directioncollumn, có nghĩa các phần tử sẽ xếp lần lượt theo chiều dọc.
  3. Để nội dung card mở rộng và lấp đầy khoảng trống còn lại.
  4. Áp dụng Flexbox cho card content
  5. Cuối cùng, sử dụng marrgin-top: auto để đẩy link xuống. Điều này sẽ giữ nó ở dưới cùng bất kể chiều cao của thẻ.

Bạn có thể thấy việc kết hợp Grid và Flexbox không hề khó. Đó là 2 công cụ đem đến cho chúng ta rất nhiều cách để triển khai layout. Hãy hiểu chúng đúng cách và kết hợp chúng chỉ khi bạn thực sự cần nhé.

Nguồn: https://ishadeed.com/article/grid-layout-flexbox-components/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 528

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 410

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 776

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 373

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 463

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 436