Học CSS Flexbox toàn tập phần 3

sử dụng css flexbox

Sau khi hoàn thành bài trước về các thuộc tính align, justify-content và order. Hôm nay mình sẽ giới thiệu nốt cho các bạn các thuộc tính còn lại của flexbox. Là những thuộc tính quan trọng và khó hiểu cho nên bài này khá dài nhưng mình khuyến khích các bạn nên đọc hết để hiểu rõ và áp dụng chúng 1 cách hiệu quả nha.

# Flex-basis

Set chiều rộng hoặc chiều cao của phần tử dựa vào flex-direction row hay column. Mặc định là flex-direction: row cho nên lúc này flex-basis sẽ tương ứng với thuộc tính width của phần tử và khi flex-direction: column thì lúc này flex-basis sẽ là height của phần tử.

Thuộc tính flex-basis sẽ đè lên thuộc tính width hoặc height của phần tử tùy thuộc vào giá trị của flex-direction. Các bạn có thể thay giá trị cho flex-direction vào Codepen dưới đây để hiểu hơn nha.

See the Pen CSS Flexbox basis by EvonDev (@blackzero) on CodePen.

# Flex-grow

Thuộc tính này khá là phức tạp nè, nó cho các phần tử giãn theo độ rộng của container, để mình giải thích cho các bạn qua từng hình ảnh nha. Đầu tiên mình cho các phần tử có độ rộng là 120px.

Mặc định giá trị trong thuộc tính flex-grow là 0. Nghĩa là các phần tử sẽ không tự động co giãn kích thước khi chiều rộng của container bao ngoài thay đổi. Hơi khó hiểu nhỉ ? Để mình tăng flex-grow lên 1 cho các phần tử coi sao.

Wow. Các phần tử tự động giãn ra đều nhau sao cho vừa với khung container luôn, hay thật. Ủa vậy flex-grow: 1 là gì nhỉ, mình tăng lên 999 có sao không ? Không có bị gì luôn.

Giá trị của flex-grow rất là linh động chứ không tuyệt đối nghĩa là khi set giá trị flex-grow cho các phần tử thì các phần tử đều có tỉ lệ với nhau. Ví dụ set tất cả các phần tử flex-grow là 1 thì tất cả đều như nhau tỉ lệ 1:1, nếu set 999 cho toàn bộ thì cũng vậy vì bằng nhau hết mà đơn giản về hết cũng là 1:1.

See the Pen CSS Flexbox grow – row by EvonDev (@blackzero) on CodePen.

Nhưng mà giả sử set các phần tử đều là flex-grow: 1, nhưng set riêng phần tử thứ 3 giá trị khác thì sẽ như thế nào nhỉ ?

Chỗ này có áp dụng toán học nên mình sẽ giải thích cho các bạn hiểu. Bây giờ mình có 6 phần tử, ta set flex-grow: 1 cho các phần tử thì các phần tử sẽ bằng nhau vì container sẽ chia đều cho 6. Mỗi phần tử sẽ chiếm 1/6 đúng không nào ?

Nhưng khi mình tăng ô số 3 lên flex-grow: 2. Thì lúc này giá trị của flex-grow của các phần tử cộng lại sẽ là 7 cho nên container sẽ chia đều cho 7 vì 1 + 1 + 2 + 1 + 1 + 1. Ô số 3 có flex-grow: 2 nên sẽ chiếm 2/7 của container còn các phần tử còn lại chiếm 1/7.

See the Pen CSS Flexbox grow – row2 by EvonDev (@blackzero) on CodePen.

Khi tăng ô số 3 lên flex-grow:3. Thì giá trị flex-grow của các phần tử cộng lại sẽ là 8 và container sẽ chia đều cho 8(1+1+3+1+1+1). Ô số 3 sẽ chiếm 3/8 và các ô còn lại chiếm 1/8. Và cứ thế tiếp tục nếu các bạn tăng.

Như đã nói ở trên thuộc tính flex-grow làm cho các phần tử tỉ lệ với nhau. Giả sử các phần tử đều có flex-grow: 4 và ô số 3 có thuộc tính flex-grow: 12 thì nó cũng tương tự như là 1 với 3.

Tips của mình hay dùng cho dễ hiểu đó là cứ lấy cái giá trị flex-grow của cái ô có số to nhất chia cho ô có số nhỏ nhất thì sẽ ra được tỉ lệ các phần tử so với nhau. Như ở trên 12/4 được 3 suy ra các ô còn lại sẽ bằng 1/3 ô lớn nhất.

Một điều nữa là khi dùng với flex-direction: column thì flex-grow sẽ giãn theo chiều dọc và lúc này nó sẽ là height(chiều cao) chớ không phải chiều rộng(width) nha. Cái này các bạn áp dụng tương tự để tự luyện tự hiểu cho mau lên trình nha.

# Flex-shrink

Thuộc tính này thì nó ngược lại so với thuộc tính flex-grow ở trên, nó không giãn ra mà lại co lại khi chúng ta thay đổi độ rộng của container xuống. Mặc định giá trị trong flex-shrink là 1 nghĩa là cho phép các phần tử co lại khi độ rộng container giảm xuống.

Các bạn thấy chứ các phần tử nó sẽ co lại khi chúng ta resize trình duyệt nhỏ xuống. Nhưng nếu các bạn set cho nó flex-shrink: 0 thì nó sẽ không co giãn và lúc này nó sẽ lấy giá trị của thuộc tính width.

See the Pen CSS Flexbox shrink by EvonDev (@blackzero) on CodePen.

Ở đây các bạn thấy phần tử số 3 có flex-shrink: 0. Thì khi co giãn lại tới ngưỡng độ rộng 120px(thuộc tính width) của nó thì nó vẫn sẽ giữ độ rộng đó chứ không co lại hơn nữa như các phần tử có flex-shrink: 1. Mình có note trong Codepen ở trên. Các bạn vào test xem đúng không nhá.

Cũng như flex-grow thì trong flex-shrink các phần tử cũng tỷ lệ với nhau nha. Phần tử A có flex-shrink: 6 và các phần tử còn lại có flex-shrink: 2. Thì cũng tương tự là 3:1. Ủa nếu ô có flex-shrink: 3 còn các ô khác flex-shrink: 1 thì khi co lại nó sẽ có độ rộng bằng 1/3 so với những cái còn lại à ?

Trước khi đi sâu vào giải thích thì mình xin giới thiệu thêm 1 thuộc tính khác nữa trước đã nhé. Đó là flex(thuộc tính nhá)

# Flex

Flex là viết tắt của 3 thuộc tính flex-grow flex-shrink và flex-basis. Nó như thế này. flex: flex-grow flex-shrink flex-basis. Mặc định grow(0) shrink(1) và basis(auto).

Các bạn xem ví dụ dưới đây cả hai đều có flex-basis như nhau. Nhưng mà ở box1 thì lại có flex-grow:2 nghĩa là box1 sẽ dài gấp đôi box2 khi độ rộng container giãn ra. Nhưng box2 thì lại có flex-shrink:2 nghĩa là khi container nhỏ xuống thì box2 sẽ co lại và có chiều dài bằng 1/2 box1 đúng không nhỉ ?

Chỗ này sao mà rối loạn quá ? Sao trong hình GIF lúc container giãn ra mình thấy box1 có gấp đôi box2 đâu hay khi co container lại box2 có bằng 1/2 box1 đâu. Đây chính là điểm luôn làm mình cũng như các bạn rối não khi làm việc với flexbox

Khi kết hợp 2 giá trị flex-shrink và flex-grow lại với nhau thì phức tạp lắm, không chỉ là tỉ lệ về các con số đâu mà là về tốc độ grow(giãn ra) hay shrink(co lại) nữa đó. Nào cùng vào phần hại não phía dưới nha.

# Giải thích grow và shrink khi kết hợp

Giả sử ban đầu ta có container có độ rộng tối đa là 640px sau khi tính toán bao gồm padding 2 bên của container. Lúc này có 2 phần tử như ở trên có flex-basis là 300px(bằng nhau về chiều rộng).

See the Pen CSS Flexbox shrink+grow by EvonDev (@blackzero) on CodePen.

Khi các bạn resize trình duyệt lại sao cho container còn 430px thì lúc này chúng ta sẽ mất là 640 – 430 =  210px. Ô số 1 do có flex-shrink: 1 nên nó mất 70px(chiều rộng của nó bây giờ sẽ là 300 – 70 = 230px), còn ô số 2 có flex-shrink: 2 nên sẽ mất đi 140px(chiều rộng sẽ còn 300 – 140x = 160px).

Các bạn lại resize trình duyệt tiếp cho đến khi độ rộng container xuống 340px thì chúng ta mất 640 – 340  = 300px. Ô số 1 có flex-shrink: 1 nên sẽ mất 100px(còn 200px) còn ô số 2 sẽ mất 200px(còn 100px) do có flex-shrink: 2.

Tương tự với flex-grow. Khi tăng độ rộng container lên 940px. Thì container được tăng thêm 300px(640 + 300 = 940). Ô số 1 có flex-grow: 2 nên sẽ tăng lên thêm 200px(tổng sẽ là 500px) còn ô số 2 có flex-grow: 1 nên sẽ chiếm 1/3 là 100px nên nó sẽ tăng thêm độ rộng 100px(tổng sẽ là 400px).

Các bạn nên inspect các phần tử trong Codepen để xem sự thay đổi. Khi độ rộng container giảm xuống so với ban đầu thì chúng ta tính theo flex-shrink và ngược lại khi độ rộng container tăng lên so với ban đầu thì tính theo flex-grow. Phần tăng lên hay giảm xuống của container sẽ chia tỉ lệ cho flex-shrink hay flex-grow tương ứng của các phần tử

Các bạn xem hình GIF và Codepen từ từ mới thông được. Nếu khó thông quá thì bình luận hoặc inbox cho mình. Mình sẽ giải đáp cho nha.

See the Pen CSS Flexbox shrink+grow2 by EvonDev (@blackzero) on CodePen.

# Lời kết

Phù!!! Bài viết về css flexbox đến đây là hết. Các bạn ráng học nhé. Có gì không hiểu cứ bình luận hoặc thấy mình viết sai hay giải thích sai thì góp ý giúp mình để mình cải thiện lại cách viết cũng như kiến thức. Cám ơn các bạn đã đọc bài và chúc các bạn một ngày tốt lành.

Bài viết có tham khảo và hình ảnh lấy từ medium.freecodecamp.org

avatar
Nguyen Phuong
Guest
Nguyen Phuong

Bài viết hay lắm anh!

Kiên Nguyễn
Guest
Kiên Nguyễn

Em cảm ơn anh, nhờ những bài viết của anh em ngộ ra được nhiều điều lắm anh ạ :)))

Hoàng Nguyễn
Guest
Hoàng Nguyễn

bài viết chi tiết quá, nhưng mình chưa hiểu cách viết tắt Flex:1; nghĩa là thế nào ạ