如何使用jQuery将一个元素相对于另一个元素定位?


354

我有一个隐藏的DIV,其中包含类似工具栏的菜单。

我有许多DIV,当鼠标悬停在它们上时,它们可以显示菜单DIV。

是否有将菜单DIV移到活动(鼠标悬停)DIV右上角的内置功能?我正在寻找类似的东西$(menu).position("topright", targetEl);


1
看看stackoverflow.com/questions/8400876/…它解决了可能发生的更多问题
Toskan

请参阅“问题是否应该在标题中包含“标签”?” ,共识是“不,他们不应该”!
Andreas Niedermair

@paul是的,样式略有不同。此问题的初始标题以jQuery:开头,不鼓励使用。通常,由于问题的附加标记,使得前缀无用。如果标题中需要该技术,则应在真实的句子中捕获它,而不仅仅是前缀-因为这是标记的用途。
Andreas Niedermair 2015年

Answers:


203

注意:这需要jQuery UI(不仅是jQuery)。

您现在可以使用:

$("#my_div").position({
    my:        "left top",
    at:        "left bottom",
    of:        this, // or $("#otherdiv")
    collision: "fit"
});

快速定位(jQuery UI / Position)。

您可以在此处下载jQuery UI


1
我一直在尝试使用positon插件,但由于某种原因,我无法使其正常工作:(
Salman 2010年

也对我不起作用。尝试使用此颜色将简单的纯色div放置在主体上方,导致其左上角偏移了17个像素。
茄子Jeff

46
请注意,此答案取决于jQueryUI,而不仅仅是jQuery。可能会解释为什么它对你们几个人无效。
btubbs 2011年

398

tl; dr :(在这里尝试)

如果您具有以下HTML:

<div id="menu" style="display: none;">
   <!-- menu stuff in here -->
   <ul><li>Menu item</li></ul>
</div>

<div class="parent">Hover over me to show the menu here</div>

那么您可以使用以下JavaScript代码:

$(".parent").mouseover(function() {
    // .position() uses position relative to the offset parent, 
    var pos = $(this).position();

    // .outerWidth() takes into account border and padding.
    var width = $(this).outerWidth();

    //show the menu directly over the placeholder
    $("#menu").css({
        position: "absolute",
        top: pos.top + "px",
        left: (pos.left + width) + "px"
    }).show();
});

但这不起作用!

只要菜单和占位符具有相同的偏移父级,这将起作用。如果没有,并且您没有嵌套的CSS规则来关心#menu元素在DOM中的位置,请使用:

$(this).append($("#menu"));

就在放置#menu元素的行之前。

但这仍然行不通!

您可能会有一些奇怪的布局,不适用于这种方法。在这种情况下,只需使用jQuery.ui的位置插件(如下面的答案中所述)即可处理所有可能发生的情况。注意,show()在调用之前,您必须先进入菜单元素position({...});插件无法定位隐藏的元素。

3年后的2012年更新说明:

(原始解决方案在此处存档以供后代使用)

因此,事实证明,我在这里使用的原始方法远非理想。特别是在以下情况下将失败:

  • 菜单的偏移父级不是占位符的偏移父级
  • 占位符带有边框/填充

幸运的是,jQuery 在1.2.6中引入了方法(position()outerWidth()),使在后一种情况下查找正确的值变得容易得多。对于前一种情况,append将menu元素添加到占位符是可行的(但会破坏基于嵌套的CSS规则)。


168
哇,这真是个怪胎:前几天我不得不这样做,不记得怎么了,用谷歌搜索并得到了……这个答案!要爱SOF。
雅各布

17
嘿-我发生了同样的事情-不记得该怎么做,并在Stack Overflow上找到了自己的答案。
赫卡迪尔

16
我认为您的菜单div样式应使用display:none而不是display:hidden。
加布

6
当菜单的容器具有position:相对(或继承以外的任何内容)时,此操作将无法正常工作,因为position:absolute将禁用该位置,而.offset将禁用该页面的左上角。
Mike Cooper

3
根据菜单的放置方式,可以将jQuery的.offset()替换为.position()。api.jquery.com/offset
Danny C

16

这最终对我有用。

var showMenu = function(el, menu) {
    //get the position of the placeholder element  
    var pos = $(el).offset();    
    var eWidth = $(el).outerWidth();
    var mWidth = $(menu).outerWidth();
    var left = (pos.left + eWidth - mWidth) + "px";
    var top = 3+pos.top + "px";
    //show the menu directly over the placeholder  
    $(menu).css( { 
        position: 'absolute',
        zIndex: 5000,
        left: left, 
        top: top
    } );

    $(menu).hide().fadeIn();
};

6

这是我编写的jQuery函数,可帮助我定位元素。

这是一个示例用法:

$(document).ready(function() {
  $('#el1').position('#el2', {
    anchor: ['br', 'tr'],
    offset: [-5, 5]
  });
});

上面的代码将#el1的右下角与#el2的右上角对齐。['cc','cc']将#el1居中#el2。确保#el1具有以下位置的css:绝对和z-index:10000(或一些非常大的数字)以保持在顶部。

偏移选项允许您将坐标微调指定数量的像素。

源代码如下:

jQuery.fn.getBox = function() {
  return {
    left: $(this).offset().left,
    top: $(this).offset().top,
    width: $(this).outerWidth(),
    height: $(this).outerHeight()
  };
}

jQuery.fn.position = function(target, options) {
  var anchorOffsets = {t: 0, l: 0, c: 0.5, b: 1, r: 1};
  var defaults = {
    anchor: ['tl', 'tl'],
    animate: false,
    offset: [0, 0]
  };
  options = $.extend(defaults, options);

  var targetBox = $(target).getBox();
  var sourceBox = $(this).getBox();

  //origin is at the top-left of the target element
  var left = targetBox.left;
  var top = targetBox.top;

  //alignment with respect to source
  top -= anchorOffsets[options.anchor[0].charAt(0)] * sourceBox.height;
  left -= anchorOffsets[options.anchor[0].charAt(1)] * sourceBox.width;

  //alignment with respect to target
  top += anchorOffsets[options.anchor[1].charAt(0)] * targetBox.height;
  left += anchorOffsets[options.anchor[1].charAt(1)] * targetBox.width;

  //add offset to final coordinates
  left += options.offset[0];
  top += options.offset[1];

  $(this).css({
    left: left + 'px',
    top: top + 'px'
  });

}

3

为什么要过于复杂?解决方法很简单

CSS:

.active-div{
position:relative;
}

.menu-div{
position:absolute;
top:0;
right:0;
display:none;
}

jQuery的:

$(function(){
    $(".active-div").hover(function(){
    $(".menu-div").prependTo(".active-div").show();
    },function(){$(".menu-div").hide();
})

即使,

  • 两个div放置在其他任何地方
  • 调整浏览器大小

如果我想为占位符模拟占位符,并在输入上方显示它,则此方法不起作用(
tibalt 2012年

当我要对齐两个兄弟姐妹甚至完全不相关的元素时,这是行不通的,这很常见。
oriadam '16

3

您可以使用jQuery插件PositionCalculator

该插件还包括碰撞处理(翻转)功能,因此可以将类似于工具栏的菜单放置在可见位置。

$(".placeholder").on('mouseover', function() {
    var $menu = $("#menu").show();// result for hidden element would be incorrect
    var pos = $.PositionCalculator( {
        target: this,
        targetAt: "top right",
        item: $menu,
        itemAt: "top left",
        flip: "both"
    }).calculate();

    $menu.css({
        top: parseInt($menu.css('top')) + pos.moveBy.y + "px",
        left: parseInt($menu.css('left')) + pos.moveBy.x + "px"
    });
});

对于该标记:

<ul class="popup" id="menu">
    <li>Menu item</li>
    <li>Menu item</li>
    <li>Menu item</li>
</ul>

<div class="placeholder">placeholder 1</div>
<div class="placeholder">placeholder 2</div>

这是小提琴:http : //jsfiddle.net/QrrpB/1657/


控制台写未定义不是行的函数:VAR POS = $ .PositionCalculator({你能帮帮解决这一问题?
亚历山大·别洛夫

@AlexandrBelov:我想,您没有加载该插件。在使用它之前,您必须加载插件PositionCalculator的js文件。
TLindig

2

像这样吗

$(menu).css("top", targetE1.y + "px"); 
$(menu).css("left", targetE1.x - widthOfMenu + "px");

2

这对我有用:

var posPersonTooltip = function(event) {
var tPosX = event.pageX - 5;
var tPosY = event.pageY + 10;
$('#personTooltipContainer').css({top: tPosY, left: tPosX});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.