Làm cách nào để định vị một phần tử so với phần tử khác bằng jQuery?


354

Tôi có một DIV ẩn chứa menu giống như thanh công cụ.

Tôi có một số DIV được kích hoạt để hiển thị menu DIV khi chuột di chuyển qua chúng.

Có chức năng tích hợp nào sẽ di chuyển menu DIV sang phía trên bên phải của DIV đang hoạt động (chuột di chuột) không? Tôi đang tìm kiếm một cái gì đó như$(menu).position("topright", targetEl);


1
hãy xem stackoverflow.com/questions/8400876/ mà giải quyết rất nhiều vấn đề khác có thể xảy ra
Toskan

Vui lòng xem "Có nên đặt câu hỏi bao gồm các thẻ trên mạng trong tiêu đề của họ không?" , trong đó sự đồng thuận là "không, họ không nên"!
Andreas Niedermair

@paul Vâng, có một chút khác biệt trong phong cách. Tiêu đề ban đầu của câu hỏi này có tiền tố với jQuery : , không được khuyến khích. Thông thường, do việc gắn thẻ bổ sung của câu hỏi, làm cho tiền tố trở nên vô dụng. Nếu công nghệ là cần thiết trong tiêu đề, thì nó nên được ghi lại trong một câu thực sự , không chỉ là một tiền tố - bởi vì đó là những gì các thẻ dành cho.
Andreas Niedermair

Câu trả lời:


203

LƯU Ý: Điều này yêu cầu UI UI (không chỉ jQuery).

Bây giờ bạn có thể sử dụng:

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

Để định vị nhanh ( Giao diện người dùng / Vị trí jQuery ).

Bạn có thể tải xuống jQuery UI tại đây .


1
Tôi đã cố gắng sử dụng plugin positon nhưng vì một số lý do tôi không thể làm cho nó hoạt động được :(
Salman A

Cũng không làm việc cho tôi. Việc cố gắng sử dụng điều này để đặt một div màu đơn giản phía trên cơ thể dẫn đến việc nó bị tắt 17 pixel ở phía trên bên trái.
Cà tím Jeff

46
Lưu ý rằng câu trả lời này phụ thuộc vào jQueryUI, không chỉ jQuery. Có thể giải thích tại sao nó không làm việc cho một vài bạn.
btubbs

398

tl; dr: (thử ở đây )

Nếu bạn có HTML sau:

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

sau đó bạn có thể sử dụng mã JavaScript sau:

$(".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();
});

Nhưng nó không hoạt động!

Điều này sẽ hoạt động miễn là menu và trình giữ chỗ có cùng cha mẹ bù. Nếu họ không và bạn không có các quy tắc CSS lồng nhau, quan tâm đến #menuphần tử trong DOM , hãy sử dụng:

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

ngay trước dòng định vị #menuphần tử.

Nhưng nó vẫn không hoạt động!

Bạn có thể có một số bố cục kỳ lạ không hoạt động với phương pháp này. Trong trường hợp đó, chỉ cần sử dụng plugin vị trí của jQuery.ui (như được đề cập trong câu trả lời bên dưới), xử lý mọi tình huống có thể hiểu được. Lưu ý rằng bạn sẽ phải vào show()phần tử menu trước khi gọi position({...}); các plugin không thể định vị các yếu tố ẩn.

Cập nhật ghi chú 3 năm sau vào năm 2012:

(Giải pháp ban đầu được lưu trữ ở đây cho hậu thế)

Vì vậy, nó chỉ ra rằng phương pháp ban đầu tôi có ở đây là xa lý tưởng. Cụ thể, nó sẽ thất bại nếu:

  • cha mẹ bù của menu không phải là cha mẹ bù của giữ chỗ
  • trình giữ chỗ có đường viền / phần đệm

May mắn thay, jQuery đã giới thiệu các phương thức ( position()outerWidth()) trở lại trong 1.2.6, giúp cho việc tìm kiếm các giá trị phù hợp trong trường hợp sau ở đây dễ dàng hơn rất nhiều. Đối với trường hợp trước, appending phần tử menu để giữ chỗ hoạt động (nhưng sẽ phá vỡ các quy tắc CSS dựa trên lồng nhau).


168
Whoa điều này thật quái đản: tôi đã phải làm điều này vào ngày khác, không thể nhớ làm thế nào, googled nó và có ... câu trả lời này! Phải yêu SOF.
Jacob

17
Heh - Tôi đã có điều tương tự xảy ra với tôi - không thể nhớ cách làm điều gì đó và tìm thấy câu trả lời của riêng tôi trên Stack Overflow.
Herb Caudill

16
Tôi nghĩ rằng phong cách div menu của bạn nên sử dụng display: none thay vì display: hidden.
Gabe

6
Điều này sẽ không hoạt động đúng khi vùng chứa của menu có vị trí: tương đối (hoặc bất cứ thứ gì ngoài kế thừa), vì vị trí: tuyệt đối sẽ tắt khóa đó và .offset sẽ tắt ở phía trên bên trái của trang.
Mike Cooper

3
Tùy thuộc vào cách trình đơn của bạn được định vị .offset () của jQuery có thể được sử dụng như là một thay thế thả xuống cho .poseition (). api.jquery.com/offset
Daniel C

16

Đây là những gì làm việc cho tôi cuối cùng.

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

Đây là một hàm jQuery tôi đã viết giúp tôi định vị các phần tử.

Dưới đây là một ví dụ sử dụng:

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

Mã ở trên sắp xếp phía dưới bên phải của # el1 với phía trên bên phải của # el2. ['cc', 'cc'] sẽ căn giữa # el1 trong # el2. Đảm bảo rằng # el1 có css vị trí: tuyệt đối và chỉ số z: 10000 (hoặc một số thực sự lớn) để giữ nó ở đầu.

Tùy chọn offset cho phép bạn chỉnh các tọa độ theo một số pixel được chỉ định.

Mã nguồn dưới đây:

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

Tại sao phức tạp quá nhiều? Giải pháp rất đơn giản

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

Nó hoạt động ngay cả khi,

  • Hai div đặt ở bất cứ nơi nào khác
  • Trình duyệt kích thước lại

phương pháp này không hoạt động nếu tôi muốn mô phỏng giữ chỗ cho tức là và hiển thị nó ở trên đầu vào (
tibalt

Điều này không hoạt động khi tôi muốn sắp xếp hai yếu tố là anh em ruột hoặc thậm chí hoàn toàn không liên quan, điều này rất phổ biến.
oriadam

3

Bạn có thể sử dụng plugin jQuery PositionCalculator

Plugin đó cũng bao gồm xử lý va chạm (lật), vì vậy menu giống như thanh công cụ có thể được đặt ở vị trí có thể nhìn thấy.

$(".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"
    });
});

cho đánh dấu đó:

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

Đây là câu đố: http://jsfiddle.net/QrrpB/1657/


Bảng điều khiển ghi Không xác định không phải là một chức năng cho dòng: var pos = $ .PocationCalculator ({Bạn có thể giúp giải quyết vấn đề không?
Alexandr Belov

@AlexandrBelov: Tôi đoán, bạn đã không tải plugin. Trước khi bạn có thể sử dụng nó, bạn phải tải tập tin js của plugin PositionCalculator.
TLindig 27/2/2015

2

Một cái gì đó như thế này?

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

2

Điều này làm việc cho tôi:

var posPersonTooltip = function(event) {
var tPosX = event.pageX - 5;
var tPosY = event.pageY + 10;
$('#personTooltipContainer').css({top: tPosY, left: tPosX});
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.