JQuery: check if element is in normal flow

前端 未结 3 766
傲寒
傲寒 2021-02-07 05:05

What is the most elegant way to check whether an element is in the normal flow using jQuery?

According to the CSS3 specification,

A box belongs t

相关标签:
3条回答
  • 2021-02-07 05:14

    I doubt theres a better way, but a different way would be:

    1) Surround the element with a wrapper

    2) Compare height and width of wrapper with wrapped element

    For example:

    $('#elementToTest').clone().addClass('clone').wrap('<div></div>')
    if($('#elementToTest.clone').height()>$('#elementToTest.clone').parent().height()){
        //outside the normal flow
    }
    
    0 讨论(0)
  • 2021-02-07 05:19

    I think another "in flow" requirement is that overflow is set to visible.

    From the CSS2 spec:

    Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

    • A very detailed answer to a related question.
    • YUI blog entry about block formatting contexts.
    • A blog post I've found helpful in the past.

    Based on the requirements you quoted and the overflow requirement, this is one way to do it with jquery:

    function isInFlow(elm, ctxRoot) {
    
        ctxRoot = ctxRoot || document.body;
    
        var $elm = $(elm),
            ch = -1,
            h;
    
        if (!$elm.length) {
            return false;
        }
    
        while ($elm[0] !== document.body) {
            h = $elm.height();
            if (h < ch || !okProps($elm)) {
                return false;
            }
            ch = h;
            $elm = $elm.parent();
    
            if (!$elm.length) {
                // not attached to the DOM
                return false;
            }
            if ($elm[0] === ctxRoot) {
                // encountered the ctxRoot and has been
                // inflow the whole time
                return true;
            }
        }
        // should only get here if elm
        // is not a child of ctxRoot
        return false;
    }
    
    function okProps($elm) {
    
        if ($elm.css('float') !== 'none'){
            return false;    
        }
        if ($elm.css('overflow') !== 'visible'){
            return false;    
        }
        switch ($elm.css('position')) {
            case 'static':
            case 'relative':
                break;
            default:
                return false;
        }
        switch ($elm.css('display')) {
            case 'block':
            case 'list-item':
            case 'table':
                return true;
        }
        return false;
    }
    ​   
    

    See this jsFiddle for test cases.

    I'm not sure if it would be better to use window.getComputedStyle() or not.

    The function is checking to see if elm is in ctxRoot's flow or block formatting context (as it was previously called, I think). If ctxRoot is not supplied, it will check against the body element. This does not check to make sure ctxRoot is in flow. So, with this HTML

    <div id="b" style="overflow: hidden;">
        <div id="ba">ba
            <p id="baa">baa</p>
            <span id="bab">bab</span>
            <span id="bac" style="display:block;">bac</span>
        </div>
    </div>
    

    The test cases are:

    var b = $('#b')[0];
    console.log('no  ',isInFlow(b));
    console.log('no  ',isInFlow('#ba'));
    console.log('yes ',isInFlow('#ba', b));
    console.log('no  ',isInFlow('#baa'));
    console.log('yes ',isInFlow('#baa', b));
    console.log('no  ',isInFlow('#bab'));
    console.log('no  ',isInFlow('#bab', b));
    console.log('no  ',isInFlow('#bac'));
    console.log('yes ',isInFlow('#bac', b));
    
    0 讨论(0)
  • 2021-02-07 05:35

    Instead of looking at it retroactively, you could pre-empt the need for this by using data annotations. Any time you create or define an element, set its attribute data-flow to true or false.

    For example:

    var newDiv = document.createElement("div");
    newDiv.style.position = "absolute";
    newDiv.setAttribute("data-flow","false");
    

    Or in html

    <div style="position:absolute;" data-flow="false"></div>
    

    And then you could simply select these elements with a selector:

    $('*[data-flow=false]')
    
    0 讨论(0)
提交回复
热议问题