Menu

Cách căn giữa div trong CSS: mọi phương pháp, có đo kiểm

Mọi cách căn giữa một div theo chiều ngang, chiều dọc hoặc cả hai: flexbox, grid, margin auto, position absolute kết hợp transform, inset với margin auto và align-content. Mỗi cách đều chạy trực tiếp và tự đo độ căn giữa của mình, kèm bảng cho biết khi nào nên dùng cách nào.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Câu trả lời ngắn

Để căn giữa một div theo cả chiều ngang và chiều dọc bên trong phần tử cha, biến phần tử cha thành grid và căn giữa nội dung của nó:

.parent {
  display: grid;
  place-items: center;
  min-height: 200px; /* the parent needs room to center in */
}

Cách này hợp với phần tử con có kích thước bất kỳ và không cần đặt gì trên chính phần tử con. Dưới đây là sáu phương pháp đặt cạnh nhau. Mỗi hộp tự đo sau khi hiển thị và in ra khoảng cách từ tâm của nó đến tâm phần tử cha:

Cả sáu đều báo 0px trên cả hai trục (viền 1px của khung bằng nhau ở mọi cạnh, nên không làm lệch tâm). Thử đổi chiều rộng hoặc chữ trong một hộp rồi chạy lại: những phương pháp không phụ thuộc vào kích thước cố định vẫn giữ ở 0.

Nên dùng phương pháp nào

Phương phápCăn giữaPhần tử con cần kích thước cố định?Phù hợp nhất cho
Grid place-items: centerCả hai trụcKhôngLựa chọn mặc định: một phần tử con trong một hộp
Flexbox justify-content + align-itemsCả hai trụcKhôngMột hàng hoặc cột các mục, căn giữa như một nhóm
margin: auto trong phần tử cha flex hoặc gridCả hai trụcKhôngCăn giữa một mục trong khi các mục cùng cấp được sắp xếp khác
margin: 0 autoChỉ chiều ngangMột width hoặc max-widthKhung trang, bài viết, form trong luồng bình thường
Absolute + translate(-50%, -50%)Cả hai trụcKhôngLớp phủ, nhãn và hộp thoại nằm trên nội dung khác
Absolute + inset: 0; margin: autoCả hai trụcCó, chiều rộng và chiều caoHộp thoại có kích thước cố định
align-content: center trên một khốiChiều dọcKhôngCăn giữa theo chiều dọc mà không đổi display của phần tử cha

Cách 1: flexbox

Flexbox căn giữa theo hai trục bằng hai thuộc tính. justify-content lo trục chính (chiều ngang khi xếp thành hàng), còn align-items lo trục phụ:

Khi có nhiều phần tử con, flexbox căn giữa chúng như một nhóm và giữ chúng trên một hàng. Đây là chỗ flexbox hơn grid, vì grid sẽ xếp ba mục thành một cột ở giữa. Trang justify-content trình bày mọi giá trị căn chỉnh.

Cách 2: grid

place-items: center là cách viết tắt của align-items: center cộng justify-items: center. Trên một grid container chỉ có một phần tử con, nó căn giữa phần tử đó theo cả hai hướng:

Dùng min-height thay vì height để phần tử cha cao thêm khi thẻ cao hơn 180px, thay vì để thẻ tràn ra ngoài.

Cách 3: margin: 0 auto (chiều ngang)

Một phần tử khối có chiều rộng nhỏ hơn phần tử chứa nó có thể được căn giữa theo chiều ngang bằng margin hai bên tự động. Trình duyệt chia đều khoảng trống cho hai bên:

Hộp thứ hai chiếm hết chiều rộng, nên không có khoảng trống và không có gì dịch chuyển. Đó là lý do thường gặp khiến margin: 0 auto "không chạy". Cách này cũng chỉ căn giữa theo chiều ngang trong luồng bình thường; margin auto theo chiều dọc ở đó bằng 0. Tuy vậy, bên trong phần tử cha flex hoặc grid, margin: auto căn giữa theo cả hai hướng, chính là hộp thứ ba trong phần so sánh ở trên.

Cách 4: position absolute và transform

Khi phần tử phải nằm đè lên nội dung khác (nhãn trên ảnh, hộp thoại trên trang), đặt nó ở vị trí absolute tại 50% rồi kéo lùi lại một nửa kích thước của chính nó:

top: 50%; left: 50% đặt góc trên bên trái của phần tử vào tâm. Phần trăm trong translate() tính theo kích thước của chính phần tử, nên -50% kéo nó lùi lại một nửa chiều rộng và chiều cao, dù chúng là bao nhiêu. Phần tử cha phải được định vị (position: relative), nếu không phần tử sẽ căn giữa theo trang. Định vị được trình bày ở trang position.

Một biến thể cho phần tử có kích thước biết trước: position: absolute; inset: 0; margin: auto; cùng với width và height. Các margin tự động chia đều khoảng trống ở cả bốn cạnh.

Cách 5: align-content trên một khối bình thường

align-content: center giờ cũng chạy trên các khối chứa thông thường, không chỉ flex và grid. Nó căn giữa nội dung theo chiều dọc mà không thay đổi cách sắp xếp các phần tử con:

.parent {
  min-height: 200px;
  align-content: center;   /* vertical centering, still display: block */
}
.child {
  max-width: 300px;
  margin-inline: auto;     /* horizontal centering */
}

Thuộc tính này được hỗ trợ trên Chrome, Firefox và Safari hiện tại. Trình duyệt cũ bỏ qua nó, nên hãy dùng grid nếu bạn phải hỗ trợ các trình duyệt đó.

Căn giữa trên toàn màn hình

Để căn giữa một hộp thoại trong viewport bất kể cuộn trang, kết hợp một lớp cố định phủ toàn màn hình với grid:

.overlay {
  position: fixed;
  inset: 0;                     /* covers the viewport */
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / 50%);
}

Để căn giữa nội dung cả trang theo chiều dọc, dùng min-height: 100dvh trên phần tử cha thay vì 100vh: trên điện thoại, 100vh tính cả vùng nằm sau thanh công cụ của trình duyệt, nên "tâm" bị lệch xuống thấp.

Căn giữa chữ là một việc khác

Mọi cách ở trên đều căn giữa một hộp. Để căn giữa chữ bên trong hộp, dùng text-align: center trên hộp đó, như ở trang căn giữa chữ trong HTML. Bạn thường cần cả hai: grid để căn giữa thẻ, và text-align để căn giữa các dòng chữ bên trong.

Lỗi thường gặp

  • Phần tử cha không có chiều cao. Căn giữa theo chiều dọc cần khoảng trống; phần tử cha co lại vừa nội dung thì không có khoảng trống nào.
  • margin: 0 auto trên một khối chiếm hết chiều rộng. Đặt width hoặc max-width trước.
  • margin: auto để căn giữa theo chiều dọc trong luồng bình thường. Margin tự động theo chiều dọc ở đó bằng 0; hãy dùng flex hoặc grid.
  • Căn giữa absolute mà phần tử cha không được định vị. Phần tử sẽ căn giữa theo trang, không phải theo hộp.
  • align-items: center trên phần tử con. Các thuộc tính căn chỉnh đặt trên phần tử cha (flex hoặc grid container), trừ margin: auto và align-self.
  • text-align: center để căn giữa một khối. Nó căn giữa nội dung inline (chữ, ảnh, phần tử con inline-block), không căn giữa phần tử con dạng khối.

Câu hỏi thường gặp

Làm sao căn giữa một div theo cả chiều ngang và chiều dọc?

Biến phần tử cha thành grid rồi căn giữa nội dung của nó: .parent { display: grid; place-items: center; }. Phiên bản flexbox là display: flex; justify-content: center; align-items: center;. Dù dùng cách nào, phần tử cha cũng cần chiều cao lớn hơn div.

Làm sao chỉ căn giữa div theo chiều ngang?

Đặt cho div một chiều rộng và margin hai bên tự động: .box { width: 300px; margin: 0 auto; } (hoặc max-width cho khối responsive). margin-inline: auto là cách viết tương đương bằng thuộc tính logic.

Vì sao margin: 0 auto không căn giữa được div?

Div không có chiều rộng nhỏ hơn phần tử chứa nó, nên không còn khoảng trống nào để chia (mặc định một khối chiếm hết chiều rộng). Hãy đặt width hoặc max-width. Cách này cũng không có tác dụng với phần tử inline và không bao giờ căn giữa theo chiều dọc trong luồng bình thường.

Vì sao div không căn giữa theo chiều dọc?

Phần tử cha chỉ cao bằng nội dung của nó, nên không có khoảng trống thừa để căn giữa. Đặt cho phần tử cha một chiều cao (hoặc min-height), rồi căn giữa bằng grid hoặc flexbox.

Cách dễ nhất để căn giữa một div là gì?

Đặt display: grid; place-items: center; cho phần tử cha: hai khai báo, cả hai trục, phần tử con kích thước nào cũng được. Dùng flexbox khi phần tử cha còn sắp xếp các mục khác thành một hàng.

Làm sao căn giữa chữ bên trong một div?

Dùng text-align: center trên div cho chữ và nội dung inline. Căn giữa chính div và căn giữa chữ bên trong nó là hai việc khác nhau.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu