Kiểm tra xem phần tử có hiển thị trong DOM không


377

Có cách nào để tôi có thể kiểm tra xem một phần tử có thể nhìn thấy trong JS thuần (không có jQuery) không?

Vì vậy, ví dụ, trong trang này: Xe đạp hiệu suất , nếu bạn di chuột qua Ưu đãi (trên menu trên cùng), một cửa sổ giao dịch xuất hiện, nhưng lúc đầu, nó không được hiển thị. Nó có trong HTML nhưng không nhìn thấy được.

Vì vậy, được cung cấp một phần tử DOM, làm cách nào tôi có thể kiểm tra xem nó có hiển thị hay không? Tôi đã thử:

window.getComputedStyle(my_element)['display']);

nhưng nó dường như không hoạt động. Tôi tự hỏi những thuộc tính nào tôi nên kiểm tra. Nó đến với tâm trí của tôi:

display !== 'none'
visibility !== 'hidden'

Bất kỳ ai khác mà tôi có thể bị mất?


1
Điều đó không sử dụng màn hình, nó sử dụng khả năng hiển thị để kiểm tra mức độ hiển thị (ẩn hoặc hiển thị). ví dụ:document.getElementById('snDealsPanel').style.visibility
PSL

PSL. Nếu tôi muốn làm điều này chung chung hơn, tôi nên kiểm tra thuộc tính nào: khả năng hiển thị, hiển thị ...?
Hommer Smith

Bạn có thể làm cho nó chung chung theo cách của riêng bạn nhưng điều tôi đang nói là nó sử dụng khả năng hiển thị kiểm tra phần tử.
PSL

Đây là mã của tôi (không có jquery) cho câu hỏi này stackoverflow.com/a/22969337/2274995
Aleko

Liên kết bị hỏng khiến câu hỏi của bạn không dễ hiểu. Vui lòng đóng khung lại.
Yogihosting

Câu trả lời:


618

Theo tài liệu MDN này , thuộc tính của một thành phần offsetParentsẽ trả về nullbất cứ khi nào nó hoặc bất kỳ cha mẹ nào của nó được ẩn thông qua thuộc tính kiểu hiển thị. Chỉ cần đảm bảo rằng phần tử không cố định. Một tập lệnh để kiểm tra điều này, nếu bạn không có position: fixed;thành phần nào trên trang của mình, có thể trông giống như:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    return (el.offsetParent === null)
}

Mặt khác, nếu bạn làm có yếu tố vị trí cố định mà có thể bị bắt trong tìm kiếm này, bạn sẽ thật đáng buồn (và chậm) phải sử dụng window.getComputedStyle(). Hàm trong trường hợp đó có thể là:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    var style = window.getComputedStyle(el);
    return (style.display === 'none')
}

Tùy chọn # 2 có lẽ đơn giản hơn một chút vì nó chiếm nhiều trường hợp cạnh hơn, nhưng tôi cá là nó cũng chậm hơn, vì vậy nếu bạn phải lặp lại thao tác này nhiều lần, tốt nhất có thể tránh nó.


Wow không đùa đâu. Imo không nên có lý do để sử dụng phương pháp thứ hai như một giải pháp phổ quát; không có trang nào có các phần tử cố định mà trình tạo của nó không nhận thức rõ ràng và người ta chỉ có thể kiểm tra các phần tử đó bằng cách sử dụng phương thức getComputingStyle () sau khi chạy phương thức offsetParent trên tất cả các phần tử trước.
AlexZ

6
Cũng là FYI, vừa phát hiện ra rằng nó el.offsetParentkhông hoạt động trên IE9 cho các yếu tố không cố định. Hoặc có vẻ như vậy, dù sao đi nữa. (Mặc dù vậy đối với IE11.) Vì vậy, getComputedStylesau tất cả.
Nick

1
@AlexZ Tôi không chắc chắn liệu offsetParent có thực sự phản xạ lại trong các trình duyệt ngày nay hay không, nhưng vâng, một vài năm trước, họ đã từng, đó là những gì tôi hiểu từ các báo cáo. Lưu ý rằng jsPerf chỉ đề cập đến tốc độ thực hiện, trong khi chỉnh lại dòng là về màn hình. Và trào ngược làm cho UI kém. Cá nhân tôi sẽ không tăng tốc cho một thói quen có thể được gọi là 5/6 lần trên một trang.
Ethan

2
than ôi! getComputedStylekhông hoạt động chính xác: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Tuy nhiên, vậy offsetParent- có lẽ nên sử dụng kết hợp cả hai?
anh chàng mograbi

2
đối với eg9 + eg10, bạn có thể kiểm tra xem offsetParent = body cho các phần tử không nhìn thấy được.
SuperUberDuper 7/03/2016

99

Tất cả các giải pháp khác đã phá vỡ đối với một số tình huống đối với tôi ..

Xem câu trả lời thắng tại:

http://plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview

Cuối cùng, tôi quyết định rằng giải pháp tốt nhất là $(elem).is(':visible')- tuy nhiên, đây không phải là javascript thuần túy. đó là jquery ..

Vì vậy, tôi đã xem qua nguồn của họ và tìm thấy những gì tôi muốn

jQuery.expr.filters.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Đây là nguồn: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelITT.js


11
Điều này sẽ trở lại truecho một yếu tố vớivisibility:hidden
Yuval A.

9
@YuvalA.: Vâng vì phần tử vẫn hiển thị. Đặt một phần tử để visibility:hiddenhiển thị không có nội dung nữa, nhưng vẫn lấy chiều rộng và chiều cao của phần tử!
Jacob van Lingen

4
@Michael bạn có thể dễ dàng duyệt mã jQuery và nếu bạn đang sử dụng bất kỳ IDE hiện đại nào (hãy thử nếu không), bạn có thể chuyển sang sửa các phần mã trong khi sử dụng jQuery hoặc bất kỳ lib nào khác. Bạn có thể học được rất nhiều trong khi duyệt các cơ sở mã của các dự án nguồn mở.
Lukas Liesis

53

Nếu bạn quan tâm đến hiển thị của người dùng:

function isVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity < 0.1) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    const elemCenter   = {
        x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
        y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
    };
    if (elemCenter.x < 0) return false;
    if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
    if (elemCenter.y < 0) return false;
    if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
    let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
    do {
        if (pointContainer === elem) return true;
    } while (pointContainer = pointContainer.parentNode);
    return false;
}

Đã thử nghiệm (sử dụng thuật ngữ mocha ):

describe.only('visibility', function () {
    let div, visible, notVisible, inViewport, leftOfViewport, rightOfViewport, aboveViewport,
        belowViewport, notDisplayed, zeroOpacity, zIndex1, zIndex2;
    before(() => {
        div = document.createElement('div');
        document.querySelector('body').appendChild(div);
        div.appendChild(visible = document.createElement('div'));
        visible.style       = 'border: 1px solid black; margin: 5px; display: inline-block;';
        visible.textContent = 'visible';
        div.appendChild(inViewport = visible.cloneNode(false));
        inViewport.textContent = 'inViewport';
        div.appendChild(notDisplayed = visible.cloneNode(false));
        notDisplayed.style.display = 'none';
        notDisplayed.textContent   = 'notDisplayed';
        div.appendChild(notVisible = visible.cloneNode(false));
        notVisible.style.visibility = 'hidden';
        notVisible.textContent      = 'notVisible';
        div.appendChild(leftOfViewport = visible.cloneNode(false));
        leftOfViewport.style.position = 'absolute';
        leftOfViewport.style.right = '100000px';
        leftOfViewport.textContent = 'leftOfViewport';
        div.appendChild(rightOfViewport = leftOfViewport.cloneNode(false));
        rightOfViewport.style.right       = '0';
        rightOfViewport.style.left       = '100000px';
        rightOfViewport.textContent = 'rightOfViewport';
        div.appendChild(aboveViewport = leftOfViewport.cloneNode(false));
        aboveViewport.style.right       = '0';
        aboveViewport.style.bottom       = '100000px';
        aboveViewport.textContent = 'aboveViewport';
        div.appendChild(belowViewport = leftOfViewport.cloneNode(false));
        belowViewport.style.right       = '0';
        belowViewport.style.top       = '100000px';
        belowViewport.textContent = 'belowViewport';
        div.appendChild(zeroOpacity = visible.cloneNode(false));
        zeroOpacity.textContent   = 'zeroOpacity';
        zeroOpacity.style.opacity = '0';
        div.appendChild(zIndex1 = visible.cloneNode(false));
        zIndex1.textContent = 'zIndex1';
        zIndex1.style.position = 'absolute';
        zIndex1.style.left = zIndex1.style.top = zIndex1.style.width = zIndex1.style.height = '100px';
        zIndex1.style.zIndex = '1';
        div.appendChild(zIndex2 = zIndex1.cloneNode(false));
        zIndex2.textContent = 'zIndex2';
        zIndex2.style.left = zIndex2.style.top = '90px';
        zIndex2.style.width = zIndex2.style.height = '120px';
        zIndex2.style.backgroundColor = 'red';
        zIndex2.style.zIndex = '2';
    });
    after(() => {
        div.parentNode.removeChild(div);
    });
    it('isVisible = true', () => {
        expect(isVisible(div)).to.be.true;
        expect(isVisible(visible)).to.be.true;
        expect(isVisible(inViewport)).to.be.true;
        expect(isVisible(zIndex2)).to.be.true;
    });
    it('isVisible = false', () => {
        expect(isVisible(notDisplayed)).to.be.false;
        expect(isVisible(notVisible)).to.be.false;
        expect(isVisible(document.createElement('div'))).to.be.false;
        expect(isVisible(zIndex1)).to.be.false;
        expect(isVisible(zeroOpacity)).to.be.false;
        expect(isVisible(leftOfViewport)).to.be.false;
        expect(isVisible(rightOfViewport)).to.be.false;
        expect(isVisible(aboveViewport)).to.be.false;
        expect(isVisible(belowViewport)).to.be.false;
    });
});

trường hợp cạnh nếu elem được đặt bên ngoài khung nhìn, có thể bị bắt bởi "if (! pointContainer) return false;" kiểm tra điểm đầu tiên Người bảo vệ
Jerry Đặng

Nếu bạn muốn kiểm tra xem người dùng có thể nhìn thấy nó hay không, bạn sẽ phải sử dụng scrollIntoViewquyền?! Cái này khá đắt. Có cách nào thông minh khác không?
Kim Kern

36

Điều này có thể giúp: Ẩn phần tử bằng cách định vị nó ở vị trí xa nhất bên trái và sau đó kiểm tra thuộc tính offsetLeft. Nếu bạn muốn sử dụng jQuery, bạn chỉ cần kiểm tra : bộ chọn hiển thị và nhận trạng thái hiển thị của phần tử.

HTML:

<div id="myDiv">Hello</div>

CSS:

<!-- for javaScript-->
#myDiv{
   position:absolute;
   left : -2000px;
}

<!-- for jQuery -->
#myDiv{
    visibility:hidden;
}

javaScript:

var myStyle = document.getElementById("myDiv").offsetLeft;

if(myStyle < 0){
     alert("Div is hidden!!");
}

jQuery:

if(  $("#MyElement").is(":visible") == true )
{  
     alert("Div is visible!!");        
}

jsFiddle


12
OP yêu cầu câu trả lời không có jQuery.
Stephen Quan

Nó đã được chỉnh sửa sau đó tôi đoán. Khi tôi trả lời nó không được đề cập trong chủ đề.
Md. Ashaduzzaman

2
@StephenQuan, tôi đã cập nhật câu trả lời với cả giải pháp jQuery và javaScript.
Md. Ashaduzzaman

6
đối với ví dụ jQuery, không nên cảnh báo nói "Div có thể nhìn thấy không?"
Andrei Bazanov

Tôi không muốn kết luận một phần tử bị ẩn hoàn toàn chỉ vì phần bù của nó nhỏ hơn 0: nếu nó chỉ có một số lượng nhỏ pixel nhỏ hơn 0 và phần bên phải của nó có thể nhìn thấy thì sao? (Tôi đồng ý rằng điều này có vẻ như là một thiết kế ngớ ngẩn, nhưng bạn không bao giờ biết với các nhà thiết kế web hiện nay.) Có lẽ tốt hơn để thêm chiều rộng cho offsetLeft và xem kết quả vẫn nhỏ hơn 0. Chỉ trong trường hợp.
Silas S. Brown

31

Sử dụng cùng mã với jQuery:

jQuery.expr.pseudos.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Vì vậy, trong một chức năng:

function isVisible(e) {
    return !!( e.offsetWidth || e.offsetHeight || e.getClientRects().length );
}

Hoạt động như một bùa mê trong Win / IE10, Linux / Firefox.45, Linux / Chrome.52 của tôi ...

Rất cám ơn jQuery mà không có jQuery!


Đẹp nhưng không bao gồm các yếu tố bị che giấu bởi tràn.
Alph.Dev

tốt đẹp nhưng tại sao !! (phủ định kép)?
Sunil Garg

3
Để buộc kết quả là boolean. Là e.offsetWidthmột số nguyên, !e.offsetWidthsẽ trả về falsenếu e.offsetWidthcao hơn 0 (phần tử hiển thị). Vì vậy, thêm một cái khác !như trong !!e.offsetWidthsẽ trở lạitrue nếu e.offsetWidthcao hơn không. Đó là một tốc ký cho return e.offsetWidth > 0 ? true : falsehoặc rõ ràng return e.offsetWidth > 0.
Yvan

16

Kết hợp một vài câu trả lời ở trên:

function isVisible (ele) {
    var style = window.getComputedStyle(ele);
    return  style.width !== "0" &&
    style.height !== "0" &&
    style.opacity !== "0" &&
    style.display!=='none' &&
    style.visibility!== 'hidden';
}

Giống như AlexZ đã nói, điều này có thể chậm hơn một số tùy chọn khác của bạn nếu bạn biết cụ thể hơn những gì bạn đang tìm kiếm, nhưng điều này sẽ nắm bắt tất cả các cách chính yếu tố được ẩn.

Nhưng, nó cũng phụ thuộc vào những gì được xem là hiển thị cho bạn. Ví dụ: chiều cao của div có thể được đặt thành 0px nhưng nội dung vẫn hiển thị tùy thuộc vào thuộc tính tràn. Hoặc nội dung của div có thể được tạo cùng màu với nền để người dùng không nhìn thấy nhưng vẫn hiển thị trên trang. Hoặc một div có thể được di chuyển khỏi màn hình hoặc ẩn đằng sau các div khác, hoặc nội dung của nó có thể không nhìn thấy nhưng đường viền vẫn hiển thị. Ở một mức độ nhất định "hữu hình" là một thuật ngữ chủ quan.


1
Đẹp, nhưng style.opacity, style.height và style. Thong trả về một chuỗi để nó không hoạt động với! ==
Maslow

Một cách khác mà một yếu tố có thể bị ẩn thông qua kiểu là màu của nó có thể khớp với màu nền hoặc chỉ số z của nó có thể thấp hơn các yếu tố khác.
nu everest

thêm display:nonevào điều này sẽ là tuyệt vời. Một giải pháp làm việc thích hợp!
Gijo Varghese

7

Tôi đã có một giải pháp hiệu quả hơn so với giải pháp getComputingStyle () của AlexZ khi một người có các yếu tố vị trí 'cố định', nếu một người sẵn sàng bỏ qua một số trường hợp cạnh (kiểm tra nhận xét):

function isVisible(el) {
    /* offsetParent would be null if display 'none' is set.
       However Chrome, IE and MS Edge returns offsetParent as null for elements
       with CSS position 'fixed'. So check whether the dimensions are zero.

       This check would be inaccurate if position is 'fixed' AND dimensions were
       intentionally set to zero. But..it is good enough for most cases.*/
    if (!el.offsetParent && el.offsetWidth === 0 && el.offsetHeight === 0) {
        return false;
    }
    return true;
}

Lưu ý bên lề: Nói đúng ra, "tầm nhìn" cần được xác định trước. Trong trường hợp của tôi, tôi đang xem xét một phần tử hiển thị miễn là tôi có thể chạy tất cả các phương thức / thuộc tính DOM trên nó mà không gặp vấn đề gì (ngay cả khi độ mờ là 0 hoặc thuộc tính hiển thị CSS bị 'ẩn', v.v.).


6

Nếu phần tử hiển thị thường xuyên (display: block và visibillity: thấy được), nhưng một số container cha bị ẩn, thì chúng ta có thể sử dụng clientWidthclientHeight để kiểm tra xem.

function isVisible (ele) {
  return  ele.clientWidth !== 0 &&
    ele.clientHeight !== 0 &&
    ele.style.opacity !== 0 &&
    ele.style.visibility !== 'hidden';
}

Plunker (bấm vào đây)


ele.style.visibility !== 'hidden'là dư thừa ở đây. Trong trường hợp đó, clientWidth và clientHeight sẽ là 0.
subavis

5

Nếu chúng ta chỉ thu thập những cách cơ bản để phát hiện khả năng hiển thị, hãy để tôi không quên:

opacity > 0.01; // probably more like .1 to actually be visible, but YMMV

Và làm thế nào để có được các thuộc tính:

element.getAttribute(attributename);

Vì vậy, trong ví dụ của bạn:

document.getElementById('snDealsPanel').getAttribute('visibility');

Nhưng còn ai? Nó không hoạt động ở đây. Nhìn kỹ hơn và bạn sẽ thấy rằng khả năng hiển thị đang được cập nhật không phải là một thuộc tính trên thành phần, mà là sử dụng thuộc styletính. Đây là một trong nhiều vấn đề với việc cố gắng làm những gì bạn đang làm. Trong số những người khác: bạn không thể đảm bảo rằng thực sự có thứ gì đó để xem trong một yếu tố, chỉ vì khả năng hiển thị, hiển thị và độ mờ của nó đều có các giá trị chính xác. Nó vẫn có thể thiếu nội dung hoặc có thể thiếu chiều cao và chiều rộng. Một đối tượng khác có thể che khuất nó. Để biết thêm chi tiết, một tìm kiếm nhanh của Google cho thấy điều này và thậm chí bao gồm một thư viện để thử giải quyết vấn đề. (YMMV)

Kiểm tra những điều sau đây, đó là những bản sao có thể có của câu hỏi này, với những câu trả lời xuất sắc, bao gồm một số hiểu biết sâu sắc từ John Resig hùng mạnh. Tuy nhiên, trường hợp sử dụng cụ thể của bạn hơi khác so với tiêu chuẩn, vì vậy tôi sẽ không gắn cờ:

(CHỈNH SỬA: OP SAYS PAGES PAGES, KHÔNG TẠO RA CHÚNG TÔI, VÌ SAO KHÔNG ĐƯỢC ÁP DỤNG) Một lựa chọn tốt hơn? Liên kết khả năng hiển thị của các yếu tố với các thuộc tính mô hình và luôn tạo khả năng hiển thị phụ thuộc vào mô hình đó, giống như Angular làm với ng-show. Bạn có thể làm điều đó bằng cách sử dụng bất kỳ công cụ nào bạn muốn: Angular, JS đơn giản, bất cứ điều gì. Tốt hơn hết, bạn có thể thay đổi triển khai DOM theo thời gian, nhưng bạn sẽ luôn có thể đọc trạng thái từ mô hình, thay vì DOM. Đọc sự thật của bạn từ DOM là xấu. Và chậm. Tốt hơn nhiều để kiểm tra mô hình và tin tưởng vào việc triển khai của bạn để đảm bảo rằng trạng thái DOM phản ánh mô hình. (Và sử dụng thử nghiệm tự động để xác nhận giả định đó.)


Tôi đang phân tích trang web, đây không phải là trang web của riêng tôi ... :)
Hommer Smith

4

Câu trả lời được chấp nhận không làm việc cho tôi. Năm 2020 trả lời :

1) Phương thức (elem.offsetParent! == null) hoạt động tốt trong Firefox nhưng không hoạt động trong Chrome. Đối với Chrome "vị trí: đã sửa;" cũng sẽ làm cho offsetParent trả về "null" ngay cả phần tử nếu hiển thị trong trang.

Bản giới thiệu:

//different results in Chrome and Firefox
console.log(document.querySelector('#hidden1').offsetParent); //null Chrome & Firefox
console.log(document.querySelector('#fixed1').offsetParent); //null in Chrome, not null in Firefox
    <div id="hidden1" style="display:none;"></div>
    <div id="fixed1" style="position:fixed;"></div>

bạn có thể thấy anh chàng này megatest https://stackoverflow.com/a/11639664/4481831 (chạy nó với nhiều trình duyệt để thấy sự khác biệt).

2) (getComputingStyle (elem) .display! == 'none') không hoạt động vì phần tử có thể ẩn vì một trong các thuộc tính hiển thị của cha mẹ được đặt thành không, getComputingStyle sẽ không bắt được.

Bản giới thiệu:

var child1 = document.querySelector('#child1');
console.log(getComputedStyle(child1).display);
//child will show "block" instead of "none"
<div id="parent1" style="display:none;">
  <div id="child1" style="display:block"></div>
</div>

3) (elem.clientHeight! == 0) . Phương pháp này không bị ảnh hưởng bởi vị trí cố định và nó cũng kiểm tra xem phần tử cha mẹ không nhìn thấy được. Nhưng nó có vấn đề với các yếu tố đơn giản không có bố cục css, xem thêm tại đây

Bản giới thiệu:

console.log(document.querySelector('#div1').clientHeight); //not zero
console.log(document.querySelector('#span1').clientHeight); //zero
<div id="div1">test1 div</div>
<span id="span1">test2 span</span>

4) (elem.getClientRects (). Length! == 0) dường như vượt qua các vấn đề của 3 phương thức trước. Tuy nhiên, nó có vấn đề với các phần tử sử dụng các thủ thuật CSS (khác với "display: none") để ẩn trong trang.

console.log(document.querySelector('#notvisible1').getClientRects().length);
console.log(document.querySelector('#notvisible1').clientHeight);
console.log(document.querySelector('#notvisible2').getClientRects().length);
console.log(document.querySelector('#notvisible2').clientHeight);
console.log(document.querySelector('#notvisible3').getClientRects().length);
console.log(document.querySelector('#notvisible3').clientHeight);
<div id="notvisible1" style="height:0; overflow:hidden; background-color:red;">not visible 1</div>

<div id="notvisible2" style="visibility:hidden; background-color:yellow;">not visible 2</div>

<div id="notvisible3" style="opacity:0; background-color:blue;">not visible 3</div>

KẾT LUẬN: Vì vậy, những gì tôi đã chỉ cho bạn là không có phương pháp nào là hoàn hảo. Để kiểm tra khả năng hiển thị phù hợp, bạn phải sử dụng kết hợp 3 phương pháp cuối cùng.


3

Chỉ cần tham khảo nó cần lưu ý rằng getBoundingClientRect()có thể làm việc trong một số trường hợp nhất định.

Ví dụ, một kiểm tra đơn giản rằng phần tử bị ẩn sử dụng display: nonecó thể trông giống như thế này:

var box = element.getBoundingClientRect();
var visible = box.width && box.height;

Điều này cũng tiện dụng vì nó cũng bao gồm chiều rộng bằng không, chiều cao bằng không và position: fixedvỏ. Tuy nhiên, nó sẽ không báo cáo các yếu tố ẩn với opacity: 0hoặc visibility: hidden(nhưng cũng không offsetParent).


Câu trả lời tốt nhất cho tôi ... đơn giản và hiệu quả. Và không có upvote duy nhất sau 3 năm! Đi vào để thể hiện giá trị của sự khôn ngoan của đám đông. Phiên bản của tôi : var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Sau đó, tôi có thể lọc các mảng của các phần tử theo cách sau:$$(sel).filter(isVisible) .
7vujy0f0hy

Tôi thấy đó là giải pháp đơn giản nhất developer.mozilla.org/en-US/docs/Web/API/Euity/
mẹo

Điều này không hoạt động khi người dùng hiển thị .... nếu bạn cuộn đi thì nó vẫn đúng
Ray Foss

3

Vì vậy, những gì tôi tìm thấy là phương pháp khả thi nhất:

function visible(elm) {
  if(!elm.offsetHeight && !elm.offsetWidth) { return false; }
  if(getComputedStyle(elm).visibility === 'hidden') { return false; }
  return true;
}

Điều này được xây dựng trên những sự thật này:

  • Một display: nonephần tử (thậm chí là một phần tử lồng nhau) không có chiều rộng cũng như chiều cao.
  • visiblityhiddenthậm chí là cho các yếu tố lồng nhau.

Vì vậy, không cần kiểm tra offsetParenthoặc lặp lại trong cây DOM để kiểm tra cha mẹ nào có visibility: hidden. Điều này sẽ hoạt động ngay cả trong IE 9.

Bạn có thể tranh luận nếu opacity: 0và các yếu tố sụp đổ (có chiều rộng nhưng không có chiều cao - hoặc ngược lại thị thực) cũng không thực sự hiển thị. Nhưng sau đó một lần nữa họ không nói ẩn.


3

Một bổ sung nhỏ cho câu trả lời của ohad navon.

Nếu trung tâm của phần tử thuộc về phần tử khác, chúng ta sẽ không tìm thấy nó.

Vì vậy, để đảm bảo rằng một trong những điểm của phần tử được tìm thấy

function isElementVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity === 0) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    var elementPoints = {
        'center': {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
        },
        'top-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top
        },
        'top-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top
        },
        'bottom-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom
        },
        'bottom-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom
        }
    }

    for(index in elementPoints) {
        var point = elementPoints[index];
        if (point.x < 0) return false;
        if (point.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
        if (point.y < 0) return false;
        if (point.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}

3

Cải thiện câu trả lời của @Guy Messika ở trên , phá vỡ và trả về sai nếu điểm trung tâm 'X là <0 là sai vì phần tử bên phải có thể đi vào chế độ xem. Đây là một sửa chữa:

private isVisible(elem) {
    const style = getComputedStyle(elem);

    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if ((style.opacity as any) === 0) return false;

    if (
        elem.offsetWidth +
        elem.offsetHeight +
        elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0
    ) return false;

    const elementPoints = {
        center: {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2,
        },
        topLeft: {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top,
        },
        topRight: {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top,
        },
        bottomLeft: {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom,
        },
        bottomRight: {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom,
        },
    };

    const docWidth = document.documentElement.clientWidth || window.innerWidth;
    const docHeight = document.documentElement.clientHeight || window.innerHeight;

    if (elementPoints.topLeft.x > docWidth) return false;
    if (elementPoints.topLeft.y > docHeight) return false;
    if (elementPoints.bottomRight.x < 0) return false;
    if (elementPoints.bottomRight.y < 0) return false;

    for (let index in elementPoints) {
        const point = elementPoints[index];
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}

2

Mã jQuery từ http://code.jquery.com/jquery-1.11.1.js có tham số isHidden

var isHidden = function( elem, el ) {
    // isHidden might be called from jQuery#filter function;
    // in that case, element will be second argument
    elem = el || elem;
    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
};

Vì vậy, có vẻ như có một kiểm tra thêm liên quan đến tài liệu chủ sở hữu

Tôi tự hỏi nếu điều này thực sự bắt các trường hợp sau đây:

  1. Các yếu tố ẩn đằng sau các yếu tố khác dựa trên z Index
  2. Các yếu tố với tính minh bạch đầy đủ làm cho chúng vô hình
  3. Các thành phần được định vị ngoài màn hình (tức là bên trái: -1000px)
  4. Các yếu tố với khả năng hiển thị: ẩn
  5. Các yếu tố có màn hình: không có
  6. Các yếu tố không có văn bản hiển thị hoặc các yếu tố phụ
  7. Các phần tử có chiều cao hoặc chiều rộng được đặt thành 0

0

Đây là mã tôi đã viết để tìm thấy chỉ có thể nhìn thấy trong số một vài thành phần tương tự và trả về giá trị của thuộc tính "class" của nó mà không có jQuery:

  // Build a NodeList:
  var nl = document.querySelectorAll('.myCssSelector');

  // convert it to array:
  var myArray = [];for(var i = nl.length; i--; myArray.unshift(nl[i]));

  // now find the visible (= with offsetWidth more than 0) item:
  for (i =0; i < myArray.length; i++){
    var curEl = myArray[i];
    if (curEl.offsetWidth !== 0){
      return curEl.getAttribute("class");
    }
  }

0

Đây là những gì tôi đã làm:

HTML & CSS: Làm cho phần tử bị ẩn theo mặc định

<html>
<body>

<button onclick="myFunction()">Click Me</button>

<p id="demo" style ="visibility: hidden;">Hello World</p> 

</body>
</html> 

JavaScript: Đã thêm mã để kiểm tra xem khả năng hiển thị có bị ẩn hay không:

<script>
function myFunction() {
   if ( document.getElementById("demo").style.visibility === "hidden"){
   document.getElementById("demo").style.visibility = "visible";
   }
   else document.getElementById("demo").style.visibility = "hidden";
}
</script>

-1

Đây là một cách để xác định nó cho tất cả các thuộc tính css bao gồm khả năng hiển thị:

html:

<div id="element">div content</div>

css:

#element
{
visibility:hidden;
}

javascript:

var element = document.getElementById('element');
 if(element.style.visibility == 'hidden'){
alert('hidden');
}
else
{
alert('visible');
}

Nó hoạt động cho bất kỳ tài sản css và rất linh hoạt và đáng tin cậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.