Vì vậy, đây có phải là câu trả lời?
"Nếu bạn cần tính toán một cái gì đó nhưng không hiển thị nó, hãy đặt phần tử thành visibility:hidden
và position:absolute
, thêm nó vào cây DOM, lấy offsetHeight và xóa nó. (Đó là những gì mà thư viện nguyên mẫu thực hiện sau các dòng tôi đã kiểm tra lần trước)."
Tôi có cùng một vấn đề về một số yếu tố. Không có jQuery hoặc Prototype được sử dụng trên trang web nhưng tôi hoàn toàn ủng hộ việc mượn kỹ thuật này nếu nó hoạt động. Như một ví dụ về một số điều không hoạt động, tiếp theo là những gì đã làm, tôi có đoạn mã sau:
// Layout Height Get
function fnElementHeightMaxGet(DoScroll, DoBase, elementPassed, elementHeightDefault)
{
var DoOffset = true;
if (!elementPassed) { return 0; }
if (!elementPassed.style) { return 0; }
var thisHeight = 0;
var heightBase = parseInt(elementPassed.style.height);
var heightOffset = parseInt(elementPassed.offsetHeight);
var heightScroll = parseInt(elementPassed.scrollHeight);
var heightClient = parseInt(elementPassed.clientHeight);
var heightNode = 0;
var heightRects = 0;
//
if (DoBase) {
if (heightBase > thisHeight) { thisHeight = heightBase; }
}
if (DoOffset) {
if (heightOffset > thisHeight) { thisHeight = heightOffset; }
}
if (DoScroll) {
if (heightScroll > thisHeight) { thisHeight = heightScroll; }
}
//
if (thisHeight == 0) { thisHeight = heightClient; }
//
if (thisHeight == 0) {
// Dom Add:
// all else failed so use the protype approach...
var elBodyTempContainer = document.getElementById('BodyTempContainer');
elBodyTempContainer.appendChild(elementPassed);
heightNode = elBodyTempContainer.childNodes[0].offsetHeight;
elBodyTempContainer.removeChild(elementPassed);
if (heightNode > thisHeight) { thisHeight = heightNode; }
//
// Bounding Rect:
// Or this approach...
var clientRects = elementPassed.getClientRects();
heightRects = clientRects.height;
if (heightRects > thisHeight) { thisHeight = heightRects; }
}
//
// Default height not appropriate here
// if (thisHeight == 0) { thisHeight = elementHeightDefault; }
if (thisHeight > 3000) {
// ERROR
thisHeight = 3000;
}
return thisHeight;
}
mà về cơ bản là thử mọi thứ và mọi thứ chỉ để có kết quả bằng không. ClientHeight không ảnh hưởng. Với các yếu tố vấn đề, tôi thường nhận được NaN trong Base và 0 ở độ cao Offset và Scroll. Sau đó tôi đã thử giải pháp Thêm DOM và clientRects để xem nó có hoạt động ở đây không.
Ngày 29 tháng 6 năm 2011, tôi thực sự đã cập nhật mã để thử cả thêm vào DOM và clientHeight với kết quả tốt hơn tôi mong đợi.
1) clientHeight cũng là 0.
2) Dom thực sự đã cho tôi một chiều cao tuyệt vời.
3) ClientRects trả về một kết quả gần giống với kỹ thuật DOM.
Bởi vì các phần tử được thêm vào có tính chất lỏng, khi chúng được thêm vào phần tử DOM Temp trống khác, chúng được hiển thị theo chiều rộng của vùng chứa đó. Điều này trở nên kỳ lạ, bởi vì nó ngắn hơn 30px so với cuối cùng.
Tôi đã thêm một vài ảnh chụp nhanh để minh họa cách tính chiều cao khác nhau.
Sự khác biệt chiều cao là rõ ràng. Tôi chắc chắn có thể thêm định vị tuyệt đối và ẩn nhưng tôi chắc chắn rằng nó sẽ không có hiệu lực. Tôi tiếp tục bị thuyết phục rằng điều này sẽ không hoạt động!
(Tôi lạc đề thêm) Chiều cao đi ra (ám) thấp hơn chiều cao được hiển thị thực. Điều này có thể được giải quyết bằng cách đặt độ rộng của phần tử DOM Temp phù hợp với cha mẹ hiện có và có thể được thực hiện khá chính xác trên lý thuyết. Tôi cũng không biết điều gì sẽ dẫn đến việc loại bỏ chúng và thêm chúng trở lại vị trí hiện tại của chúng. Khi họ đến thông qua một kỹ thuật InternalHTML, tôi sẽ tìm cách sử dụng phương pháp khác này.
* TUY NHIÊN * Không ai trong số đó là cần thiết. Trong thực tế, nó hoạt động như quảng cáo và trả lại chiều cao chính xác !!!
Khi tôi có thể làm cho các menu hiển thị trở lại một cách đáng kinh ngạc, DOM đã trả lại chiều cao chính xác cho mỗi bố cục chất lỏng ở đầu trang (279px). Đoạn mã trên cũng sử dụng getClientRects trả về 280px.
Điều này được minh họa trong ảnh chụp nhanh sau đây (được lấy từ Chrome sau khi làm việc.)
Bây giờ tôi có ý tưởng không rõ tại sao thủ thuật nguyên mẫu đó hoạt động, nhưng có vẻ như vậy. Ngoài ra, getClientRects cũng hoạt động.
Tôi nghi ngờ nguyên nhân của tất cả những rắc rối này với các yếu tố đặc biệt này là việc sử dụng InternalHTML thay vì appendChild, nhưng đó chỉ là suy đoán thuần túy vào thời điểm này.