Giải pháp
Sử dụng container flex lồng nhau.
Loại bỏ chiều cao phần trăm. Loại bỏ các thuộc tính bảng. Loại bỏ vertical-align
. Tránh định vị tuyệt đối. Chỉ cần gắn bó với flexbox tất cả các cách thông qua.
Áp dụng display: flex
cho mục flex ( .item
), làm cho nó trở thành một thùng chứa flex. Điều này tự động thiết lập align-items: stretch
, cho biết đứa trẻ ( .item-inner
) mở rộng toàn bộ chiều cao của cha mẹ.
Quan trọng: Loại bỏ độ cao đã chỉ định khỏi các mục flex để phương thức này hoạt động. Nếu một đứa trẻ có chiều cao được chỉ định (ví dụ height: 100%
), thì nó sẽ bỏ qua việc align-items: stretch
đến từ cha mẹ. Để stretch
mặc định hoạt động, chiều cao của trẻ phải tính toán auto
(giải thích đầy đủ ).
Hãy thử điều này (không thay đổi HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
bản demo jsFiddle
Giải trình
Vấn đề của tôi .item-inner { height: 100% }
là không hoạt động trong webkit (Chrome).
Nó không hoạt động vì bạn đang sử dụng chiều cao phần trăm theo cách không phù hợp với cách triển khai truyền thống của thông số kỹ thuật.
10.5 Chiều cao nội dung: height
tài sản
phần trăm
Chỉ định chiều cao phần trăm. Tỷ lệ phần trăm được tính tương ứng với chiều cao của khối chứa hộp được tạo. Nếu chiều cao của khối chứa không được chỉ định rõ ràng và phần tử này không được định vị tuyệt đối, giá trị sẽ được tính auto
.
auto
Chiều cao phụ thuộc vào giá trị của các thuộc tính khác.
Nói cách khác, để phần trăm chiều cao hoạt động trên một đứa trẻ đang chảy, cha mẹ phải có chiều cao được đặt.
Trong mã của bạn, bộ chứa cấp cao nhất có chiều cao được xác định: .container { height: 20em; }
Container cấp ba có chiều cao xác định: .item-inner { height: 100%; }
Nhưng giữa chúng, thùng chứa cấp hai - .item
- không có chiều cao xác định. Webkit xem đó là một liên kết còn thiếu.
.item-inner
đang nói với Chrome: hãy cho tôiheight: 100%
. Chrome tìm đến phụ huynh ( .item
) để tham khảo và trả lời: 100% là gì? Tôi không thấy gì cả (bỏ qua flex: 1
quy tắc đó). Kết quả là, nó được áp dụng height: auto
(chiều cao nội dung), phù hợp với thông số kỹ thuật.
Mặt khác, Firefox hiện chấp nhận chiều cao linh hoạt của cha mẹ làm tài liệu tham khảo cho chiều cao phần trăm của trẻ. IE11 và Edge cũng chấp nhận độ cao flex.
Ngoài ra, Chrome sẽ chấp nhận flex-grow
làm tài liệu tham khảo chính đầy đủ nếu được sử dụng cùng vớiflex-basis
(mọi giá trị số hoạt động ( auto
sẽ không), bao gồm flex-basis: 0
). Tuy nhiên, khi viết bài này, giải pháp này thất bại trong Safari.
#outer {
display: flex;
flex-direction: column;
height: 300px;
background-color: white;
border: 1px solid red;
}
#middle {
flex-grow: 1;
flex-basis: 1px;
background-color: yellow;
}
#inner {
height: 100%;
background-color: lightgreen;
}
<div id="outer">
<div id="middle">
<div id="inner">
INNER
</div>
</div>
</div>
Bốn giải pháp
1. Chỉ định chiều cao cho tất cả các phần tử cha
Một giải pháp đa trình duyệt đáng tin cậy là chỉ định chiều cao cho tất cả các phần tử cha. Điều này ngăn chặn các liên kết bị thiếu, mà các trình duyệt dựa trên Webkit coi là vi phạm thông số kỹ thuật.
Lưu ý rằng min-height
và max-height
không được chấp nhận. Nó phải là height
tài sản.
Thêm chi tiết tại đây: Làm việc với các height
giá trị phần trăm và thuộc tính CSS
2. Định vị tương đối và định vị CSS
Áp dụng position: relative
cho cha mẹ và position: absolute
cho trẻ.
Kích đứa trẻ với height: 100%
và width: 100%
, hoặc sử dụng các tính chất bù đắp: top: 0
, right: 0
, bottom: 0
, left: 0
.
Với định vị tuyệt đối, phần trăm chiều cao hoạt động mà không có chiều cao được chỉ định trên cha mẹ.
3. Xóa các thùng chứa HTML không cần thiết (được khuyến nghị)
Có cần hai container xung quanh button
không? Tại sao không loại bỏ .item
hoặc .item-inner
, hoặc cả hai? Mặc dù button
các yếu tố đôi khi thất bại như container flex , chúng có thể là các vật phẩm flex. Xem xét việc tạo ra button
một đứa trẻ của .container
hoặc .item
, và loại bỏ đánh dấu vô cớ.
Đây là một ví dụ:
.container {
height: 20em;
display: flex;
flex-direction: column;
border: 5px solid black
}
a {
flex: 1;
background: orange;
border-bottom: 1px solid white;
display: flex; /* nested flex container (for aligning text) */
align-items: center; /* center text vertically */
justify-content: center; /* center text horizontally */
}
<div class="container">
<a>Button</a>
<a>Button</a>
<a>Button</a>
</div>
4. Container Flex lồng nhau (khuyên dùng)
Loại bỏ chiều cao phần trăm. Loại bỏ các thuộc tính bảng. Thoát khỏivertical-align
. Tránh định vị tuyệt đối. Chỉ cần gắn bó với flexbox tất cả các cách thông qua.
Áp dụng display: flex
cho mục flex (.item
), làm cho nó trở thành một thùng chứa flex. Điều này tự động thiết lập align-items: stretch
, cho biết đứa trẻ ( .item-inner
) mở rộng toàn bộ chiều cao của cha mẹ.
Quan trọng: Loại bỏ độ cao đã chỉ định khỏi các mục flex để phương thức này hoạt động. Nếu một đứa trẻ có chiều cao được chỉ định (ví dụ height: 100%
), thì nó sẽ bỏ qua việc align-items: stretch
đến từ cha mẹ. Để stretch
mặc định hoạt động, chiều cao của trẻ phải tínhauto
(giải thích đầy đủ ).
Hãy thử điều này (không thay đổi HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>