11/08/2018, 21:24

Các thủ đoạn cơ bản để dàn bố cục trang với chỉ CSS (flexbox và grid)

Trước đây việc dàn bố cục trang ( layout ) chủ yếu dựa vào những công cụ thô sơ thời đồ đá, ví dụ để cho 2 đoạn văn ở 2 bên của trang thì người ta sẽ vẽ 1 cái bảng table gồm 1 hàng 2 ô rồi nhét chữ vào các ô. Để cho một thành phần trong trang ( element ) dạt vào góc bên trái người ta dùng ...

Trước đây việc dàn bố cục trang (layout) chủ yếu dựa vào những công cụ thô sơ thời đồ đá, ví dụ để cho 2 đoạn văn ở 2 bên của trang thì người ta sẽ vẽ 1 cái bảng table gồm 1 hàng 2 ô rồi nhét chữ vào các ô. Để cho một thành phần trong trang (element) dạt vào góc bên trái người ta dùng float:left chẳng hạn.

Những công cụ này đem đi dàn layout vốn là sai mục đích, bảng là để ....tạo bảng (thật bất ngờ), float là để chèn ảnh vào một đoạn văn sao cho chữ bao quanh ảnh.

Nhưng vì nhu cầu ngày xưa các website layout đơn giản chỉ như một cái văn bản nên cứ dùng. Ngày nay với công nghệ quá phát triển, một trang web không chỉ để truyền tải chữ nữa mà nó còn để thể hiện độ ngầu của chủ nhân,... nên nhu cầu layout linh hoạt theo thiết bị, bố cục phức tạp đã phát sinh ra CSS Flexbox và Grid.

Ngoài CSS Flexbox và Grid còn có các thư viện luôn chầu chực phục vụ tận răng như Bootstrap. Sử dụng thư viện sẽ đảm bảo cho bạn một quá trình khởi đầu css khấp khểnh.

Để cho đỡ nhức đầu trong bài này chỉ đề ra những vấn đề cơ bản và cách sử dụng cơ bản CSS Flexbox và Grid

Khi nào xài Flex khi nào xài Grid

khi mà chỉnh những thứ một ôhoặc một hướng (dọc hoặc ngang) thì dùng flex, hai hướng thì dùng grid

flex để căn dọc cho từng ô

việc căn dọc sẽ hết sức rách việc nếu không có flex như đã nói ở bài trước

Một ô là gì? ...mọi thứ. Hầu như trong trang web cái gì cũng là một ô. thậm chí ô này bọc lấy ô kia và mỗi ô này đều dùng flex chứ không phải dùng cho ô ngoài cùng hay ô trong cùng. Tưởng tượng ô giống như một div
alt text
^ ô này bọc ô kia...

flex cho một hướng

Một hướng là như này:
alt text

mỗi hàng trong ảnh đều là ví dụ cho 1 hướng

ngoài ra một cột cũng có 1 hướng

grid cho hai hướng

hai hướng thì là như này
alt text

ví dụ thường gặp và thường dùng tới grid là trình bày ảnh, như ở trên. Lưu ý hai hướng không phải là hai hàng. có thể là rất nhiều hàng :laughing:

Flex

Nguyên lí

một div cha có setting display: flex vào thì các div con tự động dàn hàng ra (thường là hàng ngang).

Nếu đứa con có thêm setting margin: auto thì ngoài việc vẫn dàn hàng thì nó đồng thời được căn giữa theo chiều dọc

chỗ nào khó

cái khó thứ nhất: xác định gia phả

Có lẽ cú pháp thì không có gì là khó, cái khó (trừu tượng xíu lúc đầu thôi) là việc xác định gia phả cho các thành phần trong trang.

Khi nhìn vào một trang bạn hãy nhìn từ tổng quát đến chi tiết chứ đừng cắm đầu vào viết html từ trên xuống dưới từ trái sang phải chằm chằm một chỗ như nhìn gái vậy. Điều này áp dụng chung cho mọi thứ css chứ không chỉ css flex hay grid không, như đã đề cập ở bài trước. Chúng ta phải nhìn vào tổng quát nhìn khắp trang, nhìn như liếc nhìn bài thằng bên cạnh trong tiết kiểm tra vậy, nhìn mọi thứ chỗ nào cũng nhìn, lướt qua xem nó làm được mấy bài rồi để còn báo cho lũ bàn sau,... Thậm chí mội con mắt chúng ta nhìn bài nó và con mắt kia còn phải dòm cô giáo. Xem layout cũng vậy, một con mắt xem nội dung trang để còn viết html, mắt bên kia phải nhìn vào các bố trí để nhận dạng chỗ nào thì cần flex/grid để còn chia div, bọc div vào html để định dạng css cho tiện.

alt text

ví dụ nhìn vào cái trang youtube này
alt text

thì đừng cắm cổ vào chỗ Trang chủ, Thịnh hành, Đăng ký... luôn,
alt textkiểu

<div class="trangchuthinhhanhdangki">
    <p>Trang chủ</p>
    <p>Thịnh hành</p>
    <p>Đăng kí</p>
</div>

rồi viết tiếp phần "khoảng 770000000 kết quả"
alt text

<p class="khoang77">khoảng 77000000 kết quả</p>

rồi chưa kịp chèn mấy cái ảnh với tên video bên dưới thì chợt nhận ra là làm thế quái nào để chỗ "770000000 kết quả" nó chạy sang bên được?!? (vì theo markup bình thường nó sẽ xuống dòng và đứng bên lề trái của trang)

alt text
Lúc này mới nghĩ đến flex và làm flex cho 2 đối tượng này. Và khi cần làm flex thì điều tất yếu là phải bọc div cho chúng, loay hoay quay lại tìm tìm bọc bọc

<div class="chamẹ">
    <div class="trangchuthinhhanhdangki">các thứ các thứ</div>
    <p class="khoang77">khoảng 77000000 kết quả</p>
</div>

rồi làm cái ảnh
alt text

<img src="anhmeo.jpeg">

Rồi đến đoạn dưới không biết làm sao cho mấy cánh ảnh chạy xuống dưới cái "khoảng 7777" được? (vì bố trực tiếp của nó có display:flex nên nó cũng bị dàn ngang ra luôn, chạy sang phải của chỗ "khoảng 777")

alt text

Lại phải bọc div che chở quanh ảnh và cái đoạn văn "khoảng 77000" kia để cái div đó đứng ra làm lá chắn cho 2 đứa p và img bên trong, tránh việc bọn này phải làm con của người có display: flex để rồi phải dàn hàng ngang ra. Khi đó cái div che chở sẽ trở thành 1 đứa con của cha mẹ. Đứa con kia vẫn là "trang chủ thịnh hành đăng kí".

<div class="chamẹ">
        <div class="trangchuthinhhanhdangki">các thứ các thứ</div>
        <div class="divchechở">
                <p class="khoang77">khoảng 77000000 kết quả</p>
                <img src>
        </div>
</div>

không nói đến việc sửa lại tên class cho phản ánh đúng nội dung của div, mà bản thân việc gói đi gói lại các div nghĩ đã thấy nản rồi.

nhìn tổng quan như này

alt text

toàn trang là một div bố viền đỏ, chia làm 2 cột con có viền đỏ, chạy theo chiều ngang.

Bản thân cái cột đỏ ở bên phải lại là một div bố viền xanh, có các con là div màu xanh chạy theo chiều dọc.

Vậy ta chia div theo gia phả nhà này ngay từ đầu.

Cái khó thứ hai: thuộc tính nào vứt vào chỗ bố, thuộc tính nào vứt vào chỗ con

Không nhiều nhưng ban đầu dễ rối với nhau, bố con tranh nhau chả biết ai phần ai.

bố:

  • display: flex
  • justify-content: nhiều thứ lắm xem ở phần sau

con:

  • margin: auto

Cú pháp flex

Set cho div bố

.bố{
    display: flex;
    flex-direction: row hoặc column
 }  

  • row nếu muốn con dàn theo chiều ngang
  • column nếu muốn con dàn theo chiều dọc

không nói gì thì css mặc định là row nhé, vì hầu như lôi flex ra là vì muốn dàn ngang mà, còn trên xuống:laugh:

Set cho div con

Như đã đề cập ở phần nguyên lí, chỉ cần set cho div bố là div con cũng đã dàn ra.

Trước khi display: flex cho bố
alt text

Sau khi display: flex cho bố
alt text

Sau khi margin: auto cho con
alt text

Phiên bản di động không có đất cho dàn ngang

nên ta dùng media queries để đổi hướng của flex

@media screen and (max-awidth: 400px){
    .cha{
        flex-direction: column;
    }
}

alt text

Hoặc đơn giản là gỡ luôn flex ra (tuy như vậy mất cả căn dọc đẹp)

@media screen and (max-awidth: 400px){
    .cha{
        display: block;
    }
}

alt text

Chức năng phân chia khoảng cách giữa các con

Khi các con đã có margin: auto thì chúng sẽ tự đứng cách ra một khoảng đều nhau (xem lại ảnh trước nhé)

Lưu ý phần này nói về khoảng cách giữa chúng chứ không phải kích thước của chúng.

Nhưng giả dụ mình không thích cách đều, ví dụ tên trang thì đứng sang trái, các link đứng sang phải như này. Set justify-content: space-between (cho bố hay con? xem lại mục trước)
alt text

Hay tất cả chui vào giữa khít nhau như này. Set justify-content: center

alt text

Hay chia đều ra nhưng vẫn có khoảng cách 2 bên ngoài cùng như này. justify-content: space-around
alt text

Hay bay hết sang phải justify-content: right
alt text

Grid

một ví dụ điển hình là làm layout album ảnh

cú pháp

 .cha{
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
 }

bao nhiêu cột thì bấy nhiêu chữ 1fr. Điều này giúp tạo ra 4 cột bằng nhau. Các ảnh sẽ lần lượt nhảy vào 4 ô trên hàng đầu tiên, từ trái qua phải, hết slot thì xuống hàng 2, rồi hàng 3,... cứ thế đến hết

Setting cho con thì không phải phạm trù của Grid nhưng đi kèm hay sử dụng nên mình ghi luôn ở đây

.con{
    awidth: 100%;
    height: chiều cao mong muốn;
    object-fit: cover;
    }

Vậy nếu mình có 3 thẻ img

<div class="cha">
    <img>
    <img>
    <img>
</div> 

thì nó sẽ tự nhảy vào các ô
alt text

Nếu có 5 ảnh thì như này
alt text

### Chia khoảng giữa các con
Lợi thế của grid đó là việc chia khoảng nếu làm thủ công sẽ rất rách việc nhưng giờ đây chỉ cần một dòng

 .cha{
    grid-column-gap: khoảng giữa các cột;
    grid-row-gap: khoảng giữa các hàng;
 }

ví dụ mình đặt cả 2 là 10px thì được như sau
alt text

Ở phiên bản cho di động ta chỉ việc dùng media query set lại cho div cha để chia thành 1 cột còn bản tablet chia thành 2 cột là xong

@media screen and (max-awidth: 400px){
    .cha{
            grid-template-columns: 1fr;
     }
 }


@media screen and (max-awidth: 800px){
    .cha{
        grid-template-columns: 1fr 1fr ;
    }
}

Vậy là đã xong các tính năng cơ bản của flex và grid, với những tính năng sơ sơ này đã có thể áp dụng vào rất nhiều tình huống rồi! :heart:

0