# Làm layout với Flexbox

Có nhiều cách để làm layout, tuy nhiên chúng ta sẽ chú trọng vào học layout thông qua Flexbox.

Tham khảo qua [CSS display ở đây](https://www.w3schools.com/cssref/pr_class_display.php)

Một số các loại display phổ biến:

* **inline**: mặc định của `<span>` và `<img>`, các tag inline sẽ xếp trên cùng 1 hàng theo mặc định. inline không có margin top margin bottom
    
* **block**: mặc định của `<p>`, `<div>` chiếm 100% width theo mặc định
    
* **inline-block**: coi như 1 kiểu dung hợp giữa inline và block, xếp trên cùng 1 hàng, không mặc định 100%, có thể margin top, bottom, set width height. là mặc định của `<button>`
    
* **none**: là ẩn luôn thẻ đó đi. Cái này có ứng dụng nhiều, giúp chúng ta làm các loại giao diện có tính tương tác VD làm giao diện tab, giao diện popup, giao diện có 2 trạng thái bật tắt,...
    
* **flex** và **inline-flex**: là 1 dạng mới cải tiến hơn so với block, mặc định của flex cũng chiếm 100% width, nhưng nó có thể kết hợp giữa thẻ cha và thẻ con để có nhiều kiểu giao diện/layout khác nhau. flex không phải là thuộc tính mặc định của thẻ html nên chúng ta cần phải thiết lập thủ công.
    

Đọc thêm [bài này](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) để hiểu thêm về flex

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1702886013091/f9785053-77cd-40ac-829b-3ff36acfccf8.png align="center")

UI Builder Elementor sử dụng các thuộc tính của flex nên cần nắm đc bản chất của CSS Flex để dùng thành thạo UI Builder.

**Bài tập**: hoàn thành 24 bài tập của [Flexbox Foggy](https://flexboxfroggy.com/)

### Một số layout cơ bản

#### Layout căn giữa theo 2 chiều:

Đây là mẫu layout khá phổ biến, để hiện nhanh 1 trang thông tin, hoặc dùng làm popup,...

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1702888886034/e078b0f3-efde-4494-a826-e984b193e7a8.png align="center")

| Mấu chốt | CSS | UI Builder |
| --- | --- | --- |
| **justify-content** và **align-items** đều để **center** | [click xem](https://www.youtube.com/watch?v=SFh3z02iVFc) | [click xem](https://www.youtube.com/watch?v=DkwgTnOzhAQ) |

#### Layout chia 2 cột khác chiều dài:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703001665949/fc129840-04f5-4287-8952-ca1fedfe020e.png align="center")

Thường dùng 1 cột để hiển thị ảnh, cột còn lại hiển thị thông tin chi tiết.

| Mấu chốt | CSS | UI Builder |
| --- | --- | --- |
| container dùng **row** |  |  |
| cột 1 set **width cố định** |  |  |
| cột 2 set **flex: 1** để chiếm hết không gian còn lại |  |  |
| về chiều cao thì tùy ý xử lý, có thể thêm overflow-y nếu muốn thêm scroll cho cột 2 |  |  |
| **lưu ý**: với UI Builder bản free bạn sẽ k add được Custom CSS. Workaround ở đây sẽ là tạo 1 block HTML và đặt id hoặc class cho các block và viết css ở trong block HTML. Ngoài ra, UI Builder sẽ thường có nhiều thẻ Div bao ngoài nên cần dùng kèm với Inspect của Chrome để check và style chính xác hơn. | [click xem](https://www.youtube.com/watch?v=ajhk9aaIVbU) | [click xem](https://www.youtube.com/watch?v=yOm1sEPFXRY) |

Tương tự với layout chia 2 cột chiều dài khác nhau chính là việc thay vì cột mà chia thành 2 hàng với chiều cao khác nhau.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703015645776/a477a60d-f510-4597-9b01-fd503fa35fae.png align="center")

**Bài tập**: Code bằng CSS hoặc UI Builder, tạo layout như trên, điền content (ảnh + text ) vào.

**Bài tập nâng cao**: Tìm hiểu về media query và để làm sao biến giao diện dạng 2 cột bên trên thành dạng 2 hàng này khi ở trên thiết bị di động. (đây chính là responsive)

#### Layout 2 bên trái phải

Thường dùng để bố trí các nút bấm, icon chức năng. Ngoài ra hầu hết các header của website đều theo dạng layout này (Logo và list các trang ở 2 bên trái phải)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703016104639/6e99cfdc-95e2-4d90-a638-1e14ef0a5ed4.png align="center")

| Mấu chốt | CSS | UI Builder |
| --- | --- | --- |
| sử dụng **justify-content: space-between** để tạo khoảng không giữa 2 cột. Một số trường hợp cũng có thể sử dụng 1 div không có nội dung và đặt **flex: 1** để chiếm nội dung ở giữa | [Click xem](https://youtu.be/opyVzQFoZFQ) | [Click xem](https://youtu.be/TWFTZN8Q_cA) |

#### Layout 1 cột nội dung chính ở giữa:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703044081006/badf5fd1-5f69-44a3-a8f4-2378c0e4e0a7.png align="center")

Khi bạn sử dụng 1 chiếc màn hình to (tính theo [viewport](https://whatismyviewport.com/), không phải resolution), thì thường các website sẽ k dàn hết toàn bộ màn hình của bạn, mà chỉ tập trung phân bố ở 1 cột ở giữa. Đây chính là layout mặc định của UI Builder, khi ở Container có 1 ô **Content Width** chọn **Boxed.** Các block con sẽ được đặt trong 1 div con có set **max-width**, và sau đó căn giữa div cha.

Bạn hãy xem lại video UI Builder làm layout trái phải.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703044677336/399e1143-4a71-43b2-9782-174e9cb09770.png align="center")

Để làm cho div con căn giữa div cha thì có [rất nhiều cách](https://css-tricks.com/centering-css-complete-guide/), VD như hình trên là 1 cách chỉ cần CSS **margin** **auto** ở div con. (Lưu ý khi không thấy display được thiết lập, nó sẽ mặc định là **block** như đã giới thiệu ở đầu bài.)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703044963339/e419f74d-5092-4cd1-bab4-83dd2e86fe6b.png align="center")

Và khi sử dụng **flex**, thay vì margin auto thì ta có thể sử dụng **align-self: center**

Để làm responsive cho điện thoại, thì sẽ thêm thiết lập width là đủ, không cần sử dụng media query. Dù width có set là bao nhiêu thì nó cũng sẽ k vượt quá giá trị max-width. Như trong ảnh dưới đây sử dụng [calc](https://developer.mozilla.org/en-US/docs/Web/CSS/calc) để không bị sát lề ở mobile (cách mỗi lề 15px);

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703045768444/2ba28e51-865e-40b7-9990-07698d0ae5cd.png align="center")

#### Layout list X item trên 1 hàng (grid item)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703045378081/7541e950-6002-48ca-81fb-bf195b8cbb48.png align="center")

Layout dạng này dùng để hiển thị nhiều nội dung dạng danh sách. VD: danh sách sản phẩm, danh sách bài viết,... và số lượng item trên 1 hàng sẽ phụ thuộc vào chiều dài màn hình, nếu màn hình nhiều diện tích, thì tăng số lượng item trên 1 hàng, giảm dần về 1-2 item nếu trên màn hình điện thoại.

Để làm được điều đó, ta không thể set width thủ công từng item được, chúng ta sẽ tạo CSS Variables và chỉ điều chỉnh giá trị này.

| Mấu chốt | CSS | UI Builder |
| --- | --- | --- |
| Cha: **flex-direction: row; flex-wrap: wrap** |  |  |
| Con: set width theo công thức và thay đổi theo **media query** | [Click xem](https://youtu.be/WvdT8HlFGnI) | [Click xem](https://youtu.be/66w449NZN-w) |

#### Layout floating

Là dạng layout bay nhảy tự do, khi mà giao diện có thể đè lên 1 giao diện khác. VD như popup, back to top button, chat support, notification, sticky header

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1703679409901/1a42e8a4-52f3-41a6-b5c8-32d1925b019a.png align="center")

Nếu muốn giao diện nổi toàn trang, dùng CSS `position: fixed`; kèm `top`, `left`, `right`, `bottom` .Nếu muốn giao diện nổi trong phạm vi của parent, thì đặt parent `position: relative;` và sau đó bản thân giao diện đặt `position: absolute`, kèm `top`, `left`, `right`, `bottom`. Nhiều trường hợp b chỉ cần dùng 2 trong số 4 thuộc tính (VD: `top`, `left`) và kèm `width`, `height` là đã có thể định vị được giao diện.

| Mấu chốt | CSS | UI Builder |
| --- | --- | --- |
| position: **fixed**/**absolute** | [Xem clip](https://youtu.be/T6ZCHdyzDVU) | [Xem clip](https://youtu.be/aot2cY7xq9Y) |
