Cách chỉnh 2 cột cao bằng nhau (same height) trong HTML + Boostrap

Link demo:


Đoạn code demo
<div class="container py-4">
    <div class="row g-4">
      <!-- Cột 1 -->
      <div class="col-lg-6 col-md-6 mb-24 d-flex">
        <div class="featured-card flex-fill d-flex flex-column">
          <div class="blog-post-thumb chbl-image-wraper">
            <img src="https://via.placeholder.com/800x450?text=Image+1"
                 alt="Tiêu đề bài viết 1" loading="lazy" />
          </div>

          <h4 class="mt-20">Tiêu đề bài viết 1</h4>

          <div class="flex-grow-1">
            <p>
              Đây là phần mô tả ngắn. Nội dung dài ngắn khác nhau nhưng nhờ flex nên
              card vẫn căn đều và nút “Đọc thêm” luôn ở dưới cùng.
            </p>
          </div>

          <div class="mt-15">
            <a class="fs-14" href="/bai-viet-1">Đọc thêm</a>
          </div>
        </div>
      </div>

      <!-- Cột 2 (cố tình dài hơn để bạn thấy 2 cột vẫn bằng chiều cao) -->
      <div class="col-lg-6 col-md-6 mb-24 d-flex">
        <div class="featured-card flex-fill d-flex flex-column">
          <div class="blog-post-thumb chbl-image-wraper">
            <img src="https://via.placeholder.com/800x450?text=Image+2"
                 alt="Tiêu đề bài viết 2" loading="lazy" />
          </div>

          <h4 class="mt-20">Tiêu đề bài viết 2</h4>

          <div class="flex-grow-1">
            <p>
              Mô tả ngắn phần 2. Đoạn này dài hơn để mô phỏng thực tế:
              thêm vài câu nữa để nội dung cao hơn, giúp bạn thấy rõ việc
              các cột vẫn có chiều cao bằng nhau khi hiển thị cạnh nhau.
            </p>
            <p>
              Khi nội dung cột này cao hơn, cột bên trái vẫn “kéo” lên
              bằng nhờ hệ thống flex được thiết lập đúng cách.
            </p>
          </div>

          <div class="mt-15">
            <a class="fs-14" href="/bai-viet-2">Đọc thêm</a>
          </div>
        </div>
      </div>
    </div>
  </div>


Giải thích chi tiết (tại sao các cột bằng nhau)

1) Cấu trúc tổng thể

  • Mỗi cột là một .col-lg-6 .col-md-6 (hai cột trên một hàng).

  • Bên trong mỗi cột có một “card” thực chất là <div class="featured-card ...">.

2) Các class mấu chốt để bằng chiều cao

  • d-flex ở phần tử cột (<div class="col-lg-6 ... d-flex">):
    Biến cột thành một flex container theo chiều ngang (mặc định). Nhờ vậy, phần tử con trực tiếp của cột (tức .featured-card) có thể “giãn” ra theo chiều cao của cột.

  • flex-fill.featured-card:
    Khi cha (cột) là d-flex, flex-fill khiến .featured-card chiếm toàn bộ không gian còn lại theo cả chiều rộng/chiều cao do flex cung cấp.
    Kết quả: tất cả card trong các cột sẽ cao bằng nhau, căn theo cột có nội dung cao nhất.

  • d-flex flex-column.featured-card:
    Chuyển card thành flex container theo trục dọc. Đây là tiền đề để dùng flex-grow-1 cho phần nội dung, giúp:

    • Nội dung có thể “co giãn” lấp đầy khoảng trống.

    • Kéo phần “Đọc thêm” xuống cuối card để các nút thẳng hàng.

  • flex-grow-1 ở khối nội dung:
    Phần nội dung sẽ giãn nở lấp đầy chiều cao còn lại bên trong card.
    Nhờ thế, bất kể nội dung ngắn/dài khác nhau, block “Đọc thêm” luôn dạt xuống dưới cùng, tạo cảm giác cân đối & chuyên nghiệp.

3) Các class phụ trợ khác

  • .fs-14: Bootstrap không có sẵn cỡ chữ 14px (nhỏ nhất fs-6 ~ 16px), nên mình thêm class tùy biến .fs-14 { font-size:14px } để link “Đọc thêm” đúng cỡ bạn dùng.

  • .mb-24: Bootstrap spacing theo bậc (mb-3, mb-4…), không có mb-24px nên mình thêm nhanh để giữ nguyên ý đồ của bạn (có thể thay bằng mb-3/mb-4 tùy design).

  • .blog-post-thumb img { width:100% }: Đảm bảo ảnh full bề ngang card, tránh “co cụm” gây lệch layout.

4) Khi nào cần chỉnh khác?

  • Nếu bạn không muốn đặt d-flex ở từng cột, một lựa chọn khác là đặt align-items-stretch.row rồi đảm bảo phần tử bên trong cột có h-100:

    <div class="row align-items-stretch"> <div class="col-md-6"> <div class="featured-card d-flex flex-column h-100">...</div> </div> <div class="col-md-6"> <div class="featured-card d-flex flex-column h-100">...</div> </div> </div>

    Cả hai cách đều đúng; cách trong snippet của bạn (đặt d-flex ở cột + flex-fill ở card) rất thực dụng và dễ hiểu.



Nhận xét