2012-11-08 30 views
13

Khi bạn áp dụng border-collapse: collapse; vào một bảng để "kết hợp" các đường viền của ô với nhau, nó bắt đầu gây ra các vấn đề trong việc xác định độ rộng của các ô bảng trong Javascript. Ví dụ: xem trang này:
http://game-point.net/misc/browserTests/scratchpads/jsTableWidth/
Có hai bảng, một bảng có đường viền bị sập và một không có. Nếu bạn bấm vào một hàng trong một không có đường viền bị sụp đổ, hàm innerWidth và outerWidth của jQuery sẽ báo cáo những gì tôi mong đợi (chiều rộng nội dung và nội dung cộng với chiều rộng đường viền tương ứng; không có đệm).Tại sao chiều rộng Javascript của một ô trong một pixel quá ngắn?

Tuy nhiên, nếu bạn nhấp vào một hàng trong bảng có đường viền bị thu hẹp, bạn sẽ nhận được hành vi không nhất quán của trình duyệt, đặc biệt là trên thuộc tính clientWidth. Trong Firefox, clientWidth giống với width(). Trong IE và Chrome, nó cao hơn 1 pixel và trong Opera, nó giống với width(), nhưng Opera width() quá nhỏ. Trên thực tế, width() là một pixel quá nhỏ trong tất cả các trình duyệt mà tôi đã thử nghiệm ngoại trừ Firefox. Vì vậy, nếu bạn chụp ảnh màn hình và nội dung thực sự là 80px, width() là 79px (jQuery lấy nó từ giá trị CSS được tính). Tại sao điều này?

Tôi muốn có chiều rộng của nội dung thực tế. Tôi dường như không thể sử dụng width() vì chỉ Firefox có quyền đó với đường viền bị sập. Tôi không thể sử dụng outerWidth() vì bao gồm các đường viền (hoặc có thể chỉ là một đường viền, vì nó chỉ lớn hơn 1px so với chiều rộng nội dung thực tế). Tôi không thể sử dụng clientWidth vì giá trị của nó không nhất quán giữa các trình duyệt. Tôi nên làm gì và tại sao width() 1px quá ngắn trong hầu hết các trình duyệt khi đường viền bị thu hẹp?

+0

sử dụng phương thức '.wrapInner()' để bao bọc nội dung của ô bằng div và nhận chiều rộng của ô. http://api.jquery.com/wrapInner/ – charlietfl

+2

Nhưng điều đó có nghĩa là bạn cần phải chèn các phần tử DOM trên khắp nơi để bọc nội dung ... không chính xác lý tưởng? – Jez

+0

bảng có thể là một nhức đầu, tại sao bạn nghĩ rằng chúng không được sử dụng để bố trí nữa? Nội dung đóng gói là giải pháp để tạo hoạt ảnh cho các hàng trong đó. Hãy thử làm động một hàng mà không có nó ... kết quả là khủng khiếp – charlietfl

Trả lời

5

Tôi nghĩ rằng vấn đề trong mọi trình duyệt nhưng Opera thực sự là một cái gì đó jQuery đang làm với chức năng width() của nó; nó có móc tùy chỉnh cho chiều rộng và chiều cao và nó không luôn luôn trả về chiều rộng tính toán thực sự. Khi tôi sử dụng window.getComputedStyle để có được chiều rộng của các ô bảng này, nó thực sự cho tôi độ rộng phù hợp được hiển thị. Tôi sẽ báo cáo đầu ra của window.getComputedStyle của Opera là một lỗi, bởi vì nó dường như không cung cấp cho bạn chiều rộng phù hợp ngay cả khi bạn bỏ qua jQuery.

7

Trong mô hình đường viền thu gọn, các ô không chỉ là "được ghép", chúng được chia sẻ bởi các ô liền kề.

Vì vậy, nói rằng bạn đã đánh dấu như thế này:

<table style="border-collapse: collapse"> 
    <tr> 
    <td style="border: 1px solid black; width: 100px"> 
    <td style="border: 1px solid black; width: 100px"> 
    </tr> 
</table> 

Trong mô hình biên giới sụp đổ, chiều rộng của bảng này là 102px. Có 0,5px đường viền thực sự là bên ngoài bảng, sau đó là 0,5px đường viền, sau đó là 100px ô, sau đó là 1px đường viền, sau đó là 100px ô, sau đó là 0,5px đường viền, sau đó là 0,5px đường viền bên ngoài bảng. Xem hình ảnh tại http://www.w3.org/TR/CSS21/tables.html#collapsing-borders

Vì vậy, cho điều đó, UA sẽ trả về các chiều rộng khác nhau của ô đầu tiên là gì? Nó có nên là 100px không? 101px? 102px? Thứ gì khác? Chỉ cần trả lại chiều rộng nội dung cộng với chiều rộng đường viền sẽ trả lại 102px, nhưng khoảng trống thực tế được di chuyển bởi ô chỉ là 101px ...

Hơn nữa, nếu jQuery tự tính chiều rộng nội dung, nó cũng có thể gặp sự cố này, nếu nó không phải là trường hợp đặc biệt bị thu hẹp biên giới.

Và không có thông số kỹ thuật thực sự cho clientWidth, ít hơn nhiều so với chiều rộng của jQuery() và như vậy, tất nhiên. Đó là loại giải thích tại sao các kết quả bạn thấy là tất cả các nơi.

Đối với những gì bạn nên làm, nếu bạn thực sự biết chính xác những gì đang xảy ra với biên giới của bạn, bạn nên có lẽ getBoundingClientRect(). Chiều rộng (giả sử trình duyệt không gây rối rằng lên) và trừ ra khỏi nửa độ rộng của biên giới. Nếu bạn cần điều này để làm việc với các chiều rộng biên giới khác nhau, tôi không chắc chắn có một giải pháp tuyệt vời.

+0

Chiều rộng của bảng bạn chỉ định là 203px (tôi vừa thử), với thêm 3px đến từ đường viền 1px ở bên trái và bên phải của bảng và một đường viền 1px khác giữa hai ô. Tôi thực sự không hiểu lời giải thích của bạn. – Jez

+1

Chiều rộng kết xuất là 203px. Chiều rộng bố cục là 202px. Các biên giới thực sự dính ra khỏi bàn. Xin vui lòng xem hình ảnh tại liên kết tôi đã cung cấp ... –

+0

@BorisZbarsky câu trả lời tuyệt vời, cảm ơn. –

Các vấn đề liên quan