CSS 07/08/2023

TẠO BỐ CỤC LINH HOẠT VÀ HIỆU QUẢ VỚI FLEXBOX

Mục lục
    "CSS flexbox là một one-dimensional layout pattern, một trong những pattern giúp bạn dễ dàng thiết kế layout một cách linh hoạt và hiệu quả. Phân chia không gian giữa các items và kiểm soát căn chỉnh chúng trong container flex layout. Với flexbox, chúng ta có thể dễ dàng sắp xếp các items từ trái sang phải, từ trên xuống dưới, đồng thời kiểm soát khoảng cách và thứ tự của các items trong container."

    Flexbox là gì?

    Flexbox là một kiểu dàn trang (layout mode) mà nó sẽ tự cân đối kích thước của các phần tử bên trong để hiển thị trên mọi thiết bị. Nói theo cách khác, bạn không cần thiết lập kích thước của phần tử, không cần cho nó float, chỉ cần thiết lập nó hiển thị chiều ngang hay chiều dọc, lúc đó các phần tử bên trong có thể hiển thị theo ý muốn.

    Cấu trúc và thuật ngữ

    Image TUI-editor


    Flex container: là thành phần lớn bao quanh chứa các phần tử (Flex items) bên trong. Các item bên trong sẽ hiển thị dựa trên thiết lập của container này.

    Flex items: là phần tử con nằm trong thành phần lớn bao quanh gọi là những Flex items, các bạn có thể sắp xếp thứ tự của các Flex items này.


    Về cơ bản, những items sẽ được sắp xếp theo một trong hai trục chính (từ main-start đến main-end) hoặc trục dọc (từ cross-start đến cross-end).


    main-axis: trục chính của một flex container là nơi mà các flex items được bố trí dọc theo đó. Hãy nhớ, nó không nhất thiết phải nằm ngang hay nằm dọc, nó hoàn toàn phụ thuộc vào thuộc tính flex-direction của flex container.

    main-start | main-end: các flex items đặt bên trong flex container được sắp xếp theo chiều ngang, bắt đầu từ main-start cho đến main-end.

    main-size: Là kích thước của mỗi item dựa theo trục main axis.

    cross-axis: Nó nằm vuông góc với trục main-axis. Hướng của nó phụ thuộc vào hướng của main-axis.

    cross-start | cross-end: mang ý nghĩa tương tự với main-startmain-end, nhưng theo hướng vuông góc với chúng.

    cross-size: Là kích thước của mỗi item dựa theo trục cross axis.

    Các thuộc tính của Flex Container

    • display: Để sử dụng flex trong css thì đơn giản là chúng ta chỉ cần khai báo thuộc tính display: flex

      Image TUI-editor

    .container {
      display: flex | inline-flex;
    }
    • flex-direction: xác định hướng của main-axis để container sắp xếp các item.

      Image TUI-editor

    .container {
      display: flex | inline-flex;
      flex-direction: row | column | row-reverse | column-reverse; 
    }

    row(được thiết lập mặc định): chuyển trục main axis theo chiều ngang. Các flex items được hiển thị từ trái qua phải (ở chế độ ltr), và phải qua trái (ở chế độ rtl).

    Image TUI-editor

    row-reverse: tương tự như row, nhưng đảo ngược thứ tự các flex items.

    Image TUI-editor

    column: chuyển trục main axis theo chiều dọc. Các flex items được hiển thị từ trên xuống dưới (ở chế độ ltr), và từ dưới lên trên (ở chế độ rtl).

    Image TUI-editor

    column-reverse: tương tự như column, nhưng đảo ngược thứ tự các flex items.

    Image TUI-editor

    • flex-wrap: Theo mặc định, trình duyệt sẽ cố gắng sắp xếp tất cả flex items trên cùng một hàng. Bạn có thể thay đổi nó và cho phép các flex items xuống dòng khi cần thiết với thuộc tính này.

      Image TUI-editor

    .container {
      display: flex | inline-flex;
      flex-wrap: nowrap | wrap | wrap-reverse; 
    }

    nowrap: mặc định, tất cả các item sẽ nằm trên một dòng.

    Image TUI-editor

    wrap: khi kích thước container thay đổi và tổng chiều rộng các item cộng lại lớn hơn chiều rộng của container thì item sẽ tự động xuống dòng.

    Image TUI-editor

    wrap-reverse: tương tự như wrap, nhưng thay vì xuống dòng thì item sẽ tự động nhảy lên trên.

    Image TUI-editor

    • flex-flow: Đây là một cách viết tắt, giúp chúng ta chỉ định cả 2 thuộc tính flex-directionflex-wrap. Giá trị mặc định của flex-flowrow nowrap.

    .container {
      display: flex | inline-flex;
      flex-flow: column wrap; 
    }
    • justify-content: Thuộc tính này giúp xác định sự liên kết giữa các flex items dọc theo main axis. Nó giúp phân phối thêm không gian trống giữa các flex items trên cùng một hàng (flex line). Ngoài ra thuộc tính này còn thực hiện một số kiểm soát cho việc căn chỉnh các mục khi chúng tràn hàng (overflow).

      Image TUI-editor

    .container {
      display: flex | inline-flex;
      justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
    }

    flex-start: giá trị mặc định,item sẽ bắt đầu từ lề chính main-start của container.

    Image TUI-editor

    flex-end: item sẽ bắt đầu từ lề chính main-end của container (khác với row-reverse là đổi hướng hiển thị).

    Image TUI-editor

    center: item sẽ nằm giữa container.

    Image TUI-editor

    space-between: item sẽ có khoảng cách giữa các phần tử bằng nhau do container sẽ tự động căn khoảng cách, item đầu tiên sát lề chứa điểm main-start, item cuối cùng sát lề chứa điểm main-end.

    Image TUI-editor

    space-around: tương tự space-between, nhưng khác ở chỗ là mỗi item có khoảng cách 2 bên cạnh và những khoảng cách này bằng nhau.

    Image TUI-editor

    space-evenly: item được phân phối sao cho khoảng cách giữa hai item bất kỳ, giữa item và các lề là bằng nhau.

    Image TUI-editor

    • align-items: sử dụng để điều chỉnh vị trí bắt đầu và căn chỉnh các item bên trong container theo dọc theo trục cross axis, chiều ngang hoặc chiều dọc tùy thuộc vào flex-direction.

      Image TUI-editor

    .container {
      display: flex | inline-flex;
      align-items: stretch | flex-start | flex-end | center | baseline;
    }

    stretch: giá trị mặc định, các phần tử sẽ được kéo dài để lấp đầy container chứa nó, nhưng sẽ ưu tiên giá trị height/width nếu có, khi đó item sẽ không cao full mà chỉ lấy giá trị height/width mà bạn set.

    Image TUI-editor

    flex-start: item sẽ bắt đầu từ lề cross-start của container.

    Image TUI-editor

    flex-end: item sẽ bắt đầu từ lề cross-end của container. Trường hợp mặc định với cross axis đứng dọc, flex-direction: row thì các item sẽ dồn xuống dưới.

    Image TUI-editor

    center: item sẽ căn giữa theo chiều của cross axis.

    Image TUI-editor

    baseline: item được căn chỉnh theo đường cơ sở của chúng.

    Image TUI-editor

    • align-content: sử dụng để căn chỉnh khoảng cách các item bên trong container theo dọc theo trục cross axis, chiều ngang hoặc chiều dọc tùy thuộc vào flex-direction.

      Image TUI-editor

    .container {
      display: flex | inline-flex;
      align-content: flex-start | flex-end | center | space-between | space-around | stretch;
    }

    flex-start: item sẽ bắt đầu từ lề cross-start của container.

    flex-end: item sẽ bắt đầu từ lề cross-end của container.

    center: item sẽ nằm giữa container căn theo cross-axis.

    space-between: các item sẽ có khoảng cách giữa các phần tử bằng nhau do container tự động căn khoảng cách, item đầu tiên sát lề chứa cross-start, item cuối cùng sát lề chứa cross-end.

    space-around: tương tự space-between, nhưng khác ở chỗ là mỗi item có khoảng cách 2 bên cạnh và những khoảng cách này bằng nhau.

    stretch: giá trị mặc định, các phần tử sẽ được kéo dài, căn chỉnh sao cho lấp đầy container chứa nó (vẫn ưu tiên giá trị height/width nếu có).

    • order: Định nghĩa thứ tự xuất hiện của các item trong container. Mặc định thứ tự xuất hiện của các item con là 0. Giá trị nhỏ hơn 0 sẽ xuất hiện trước, và giá trị lớn hơn 0 sẽ xuất hiện sau.

      Image TUI-editor

    .item {
      order: <integer>; /* mặc định là 0 */
    }

    Image TUI-editor

    • flex-grow cho phép các phần tử giãn theo độ rộng của container.

      Image TUI-editor

    .item {
      flex-grow: <integer>; /* mặc định là 0 */
    }

    Ví dụ:

    Image TUI-editor

    Giá trị mặc định của thuộc tính flex-grow là 0, các item sẽ không tự động co giãn kích thước, để lại nhiều khoảng trống trong container.

    Khi tăng flex-grow = 1, item sẽ tự động giãn ra đều nhau sao cho vừa với khung container.

    Image TUI-editor

    Giá trị của flex-grow rất linh động, khi set thuộc tính này cho tất cả các item với cùng một giá trị thì các item sẽ có tỉ lệ như nhau và được dàn đều lấp đầy container. 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, mà set flex-grow là 100 thì kết qua vẫn sẽ ra tương tự với tỉ lệ 1:1.


    Nhưng điều thú vị hơn ở flex-grow là áp dụng nó cho từng item. Ta có giá trị mặc định ở tất cả phần tử là flex-grow = 0, thay đổi riêng giá trị của item2 thành 1, kết quả như sau:

    Image TUI-editor

    Vậy là ở đây, thiết lập flex-grow là 1 thì item2 sẽ lấy phần trống còn lại của container đắp vào chính nó.

    Bây giờ hãy thử cho các phần tử đều là flex-grow: 1, nhưng set riêng phần tử thứ 3 giá trị khác:

    Image TUI-editor

    Lúc này thì tất cả các item đều được giãn ra lấp đầy phần trống của container, nhưng item3 có flex-grow: 3 sẽ được thừa hưởng nhiều phần trống hơn các item còn lại chỉ có flex-grow: 1, cụ thể là hơn khoảng 3 lần. Và như đã đề cập ở 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 item đều có flex-grow: 4 và item3 có thuộc tính flex-grow: 12 thì nó cũng tương tự như là 1 với 3.

    Bạn tự thay đổi các giá trị để hiểu rõ hơn nhé.

    • flex-shrink: ngược lại 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.

    .item {
      flex-shrink: <integer>; /* mặc định là 1 */
    }

    Giá trị mặc định trong flex-shrink là 1, cho phép các phần tử co lại bằng nhau khi độ rộng container giảm xuống. Nếu flex-shrink: 0 thì item sẽ không co giãn mà lấy nguyên giá trị của thuộc tính width/height.

    • flex-basis: sử dụng để xác định độ dài ban đầu của một item.

    .item {
      flex-basis: <length> | auto; /* mặc định là auto */
    }

    Nếu bạn xác định độ dài chung của class item = 100px nhưng tùy chỉnh item3 với flex-basis: 250px thì ta sẽ được như sau:

    Image TUI-editor

    • flex: sử dụng để gộp chung ba thuộc tính flex-grow, flex-shrinkflex-basis.

    .item { 
      flex: 1; /* flex-grow = 1, flex-shrink = 1, flex-basis = 0 */ 
      flex: 1 1 0; 
    }
    Lưu ý:
    Nếu thuộc tính chỉ có một tham số thế này: flex: 1; thì ta hiểu đó là flex-grow.
    Nếu thuộc tính chỉ có một tham số có đơn vị độ dài như thế này: flex: 250px; thì ta hiểu đó là flex-basis.
    Nếu thuộc tính có hai tham số thế này: flex: 1 250px; thì ta hiểu đó là flex-grow và flex-basis.
    Nếu thuộc tính có hai tham số thế này: flex: 1 2; thì ta hiểu đó là flex-grow và flex-shrink.
    • align-self: có tác dụng tương tự như align-items của phần container nhưng sử dụng riêng cho từng item, bạn có thể dùng nó để đặt lại vị trí cho một số item mà align-items đã quy định.

    .item { 
      align-self: auto | flex-start | flex-end | center | baseline | stretch; 
    }

    Image TUI-editor

    Kết luận

    Bài viết tới đây là kết thúc rồi. Cá nhân mình cảm nhận flexbox cực kỳ hay và hiệu quả cho việc dàn trang, nhất là với các trang có hỗ trợ mobile view. Hy vọng thông qua bài viết này, các bạn sẽ nắm vững kiến thức về flexbox hơn.

    Bạn cũng có thể thích bài viết dưới đây