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
^ ô này bọc ô kia...
flex cho một hướng
Một hướng là như này:
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
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
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.
ví dụ nhìn vào cái trang youtube này
thì đừng cắm cổ vào chỗ Trang chủ, Thịnh hành, Đăng ký... luôn,
kiể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ả"
<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)
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
<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")
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
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ố
Sau khi display: flex cho bố
Sau khi margin: auto cho con
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; } }
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; } }
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)
Hay tất cả chui vào giữa khít nhau như này. Set justify-content: center
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
Hay bay hết sang phải justify-content: right
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 ô
Nếu có 5 ảnh thì như này
### 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
Ở 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!