JQuery: check if element is in normal flow

前端 未结 3 767
傲寒
傲寒 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: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

    ba

    baa

    bab bac

    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));
    

提交回复
热议问题