12

更新我想避免遍历所有元素的父元素,依次测试每个元素,但这是迄今为止我设法找到的最佳解决方案,就像在这个答案中一样。


在事件处理程序中,我想检测目标元素的位置是相对于视口(固定)还是文档(静态、相对或绝对)。

鉴于一个元素的位置可能是固定的,因为它具有“位置:固定”,或者因为它的父元素之一是“位置:固定”,那么检测元素固定位置的有效方法是什么?

例如:

CSS

#one {position:relative; height:10px; width:10px}

#two-wrapper {position:fixed; bottom:0; height:10px; width:10px}
#two {height:10px; width:10px}

HTML

<div id="one" class="trigger-event">element one</div>

<div id="two-wrapper">
    <div id="two" class="trigger-event">element two</div>
</div>

JS

$(document).ready(function(){
    $('.trigger-event').on('mouseenter', function(event){
        var isFixed = .... ????

        if (isFixed) {
            $(event.target).css('background','red'); 
        } else {
            $(event.target).css('background','green'); 
        }
    });
});
4

6 回答 6

14

这是一个基于遍历元素父级的解决方案,依次检查每个父级的 CSS 位置值。

这是最有效的方法,还是有办法仅通过检查元素本身来检测有效定位?

http://jsfiddle.net/Q4mSJ/

CSS

.trigger-event {background:#ccc}

#one {position:relative; height:50px; width:50px}

#two-wrapper {position:fixed; bottom:0; height:50px; width:50px}
#two {height:50px; width:50px}

HTML

<div id="one" class="trigger-event">element one</div>

<div id="two-wrapper">
    <div id="two" class="trigger-event">element two</div>
</div>

JS

function elementOrParentIsFixed(element) {
    var $element = $(element);
    var $checkElements = $element.add($element.parents());
    var isFixed = false;
    $checkElements.each(function(){
        if ($(this).css("position") === "fixed") {
            isFixed = true;
            return false;
        }
    });
    return isFixed;
}

$(document).ready(function(){
    $('.trigger-event').on('mouseenter', function(event){
        var isFixed = elementOrParentIsFixed(event.target);

        if (isFixed) {
            $(event.target).css('background','red'); 
        } else {
            $(event.target).css('background','green'); 
        }
    });
});
于 2013-10-20T07:28:24.260 回答
9

使用$(selector).offsetParent()您可以搜索选择器的祖先,而无需加载所有元素的父元素。它仍然需要遍历父元素,但一旦找到具有所选位置(相对、绝对或固定)的最近元素,它将停止。

http://jsfiddle.net/89y1buz9/11/

CSS:

div {
border: 1px solid #ccc;
}
#outer {
    height: 200px;
    width: 120px;
    position: fixed;
    padding-top: 20px;
}
#inner {
        width: 95px;
    height: 150px;
    margin: 0px auto;
    position: relative;
}
#clickme {
    width: 70px;
    height: 50px;
    cursor: pointer;
    text-align: center;
    line-height: 40px;
    margin: 20px auto;
}

HTML:

<div id="outer">
    <div id="inner">
        <div id="clickme">ClickMe</div>
    </div>
</div>

Javascript:

function isFixed(ele, posType) {
    var eleCheck = ele.offsetParent(),
        returnVal;
    posType = posType || "fixed";
    if (eleCheck.prop("tagName") === 'HTML') {
        return false;
    }
    returnVal = (eleCheck.css("position") !== posType) ? isFixed(eleCheck): posType;
    return returnVal;
}

用法: 使用或不使用第二个参数调用它默认搜索固定元素

$(function () {
    $("#clickme").on("click", function () {
        if (isFixed($(this), "fixed") === "fixed") {
            $(this).css("background", "red");
        } else {
            $(this).css("background", "green");
        }
    });
});
于 2014-10-10T18:05:55.953 回答
3

已更新,见下文...

我在为此搜索纯 javascript 解决方案时来到这里......但我希望有人会喜欢我的 jquery 版本。

这里有两个函数,它们的工作方式略有不同,但性能差异很小。我没有测量它,但是根据对jsperf“每个 vs 过滤器”的测试,.each()版本稍微快一些。

尽管如此,我还是喜欢这个.filter()版本,因为它是如此简短和清晰。

$.fn.isfixed = function(){
    var el = $(this);
    var all = el.add(el.parents());
    return all.filter(function(){
        return $(this).css("position") === "fixed";
    }).length > 0;
};

$.fn.isfixed = function(){
    var el = $(this);
    var all = el.add(el.parents());
    var ret = false;
    all.each(function(){
        if ($(this).css("position") === "fixed") {
            ret = true;
            return false;
        }
    });
    return ret;
};

用法是$('path > to > your > element').isfixed()和返回truefalse

更新

这是纯javascript版本。事实证明,检测el.style.position(固定/绝对/相对)不起作用,不知道为什么,但window.getComputedStyle(el)...确实如此。

var isfixed = function(elm) {
    var el;
    if (typeof elm === 'object') el = elm[0] || elm;
    else if (typeof elm === 'string') el = document.querySelector(elm);
    while (typeof el === 'object' && el.nodeName.toLowerCase() !== 'body') {
        if (window.getComputedStyle(el).getPropertyValue('position').toLowerCase() === 'fixed') return true;
        el = el.parentElement;
    }
    return false;
};

它接受三种元素参数:
作为 javascript 对象:
var obj = document.querySelector('div#myID > span');

var obj = document.getElementById('span#someID');

作为 jquery 对象:
var obj = $('div#myID > span');

或仅作为选择器:
var obj = 'div#myID > span';

用法很简单isfixed(obj);,并提供布尔值truefalse

最后是混合解决方案(纯 javascript 作为 jquery 插件)

$.fn.isfixed = function(){
    var el = this[0];
    while (typeof el === 'object' && el.nodeName.toLowerCase() !== 'body') {
        if (window.getComputedStyle(el).getPropertyValue('position').toLowerCase() === 'fixed') return true;
        el = el.parentElement;
    }
    return false;
};

用法:$('div#myID > span').isfixed()如上例所示。
希望你会喜欢它。

于 2017-05-07T17:36:03.197 回答
3

这是我现在用来检测可能嵌套在position:fixed父对象中的元素的方法。(基于另一个null存在价值观问题的答案。)

// Returns true if `node` uses css position:fixed or has a parent that does so.
function isFixedPosition(node) {
    while (node && node.nodeName.toLowerCase() !== 'body') {
        if (window.getComputedStyle(node).getPropertyValue('position').toLowerCase() === 'fixed')
            { return true; }
        node = node.parentNode;
    }
    return false; // if got this far
}
于 2020-01-11T04:15:39.677 回答
1

我采用了上面的一些示例并制作了简单的 js vanilla 代码来获取元素的位置,因此您可以在 jQuery 中使用它,也可以在没有 jQuery 的情况下使用它。

function getStylePosition(element){
  return window.getComputedStyle(element).getPropertyValue('position');
}

// use it like this
var element = document.getElementsByTagName('div')[0];
// js only
alert(getStylePosition(element));

// jQuery
alert(getStylePosition($('div')[0]));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="position:fixed;"></div>

于 2018-06-28T09:33:34.823 回答
0
$(document).ready(function(){
    $('.trigger-element').on('mouseenter', function(event){
        var position= $(this).css("position");

        if (position=="fixed") {
            $(event.target).css('background','red'); 
        } else {
            $(event.target).css('background','green'); 
        }
    });
});

jsFiddle

于 2013-10-20T05:47:08.240 回答