Bagaimana cara memposisikan satu elemen relatif terhadap yang lain dengan jQuery?

354

Saya memiliki DIV tersembunyi yang berisi menu seperti toolbar.

Saya memiliki sejumlah DIV yang diaktifkan untuk menampilkan menu DIV ketika mouse berada di atasnya.

Apakah ada fungsi bawaan yang akan memindahkan menu DIV ke kanan atas DIV aktif (mouse hover)? Saya mencari sesuatu seperti$(menu).position("topright", targetEl);

paul
sumber
1
lihat stackoverflow.com/questions/8400876/… yang membahas lebih banyak masalah yang dapat terjadi
Toskan
Silakan lihat "Haruskah pertanyaan menyertakan" tag "dalam judul mereka?" , di mana konsensus adalah "tidak, mereka seharusnya tidak"!
Andreas Niedermair 3-15
@ paul Ya, ada sedikit perbedaan gaya. Judul awal pertanyaan ini diawali dengan jQuery:, yang tidak dianjurkan. Biasanya, karena penandaan tambahan pertanyaan, yang membuat awalan tidak berguna. Jika teknologi diperlukan dalam judul, itu harus ditangkap dalam kalimat nyata , bukan hanya awalan - karena itulah gunanya tag.
Andreas Niedermair 3-15

Jawaban:

203

CATATAN: Ini membutuhkan jQuery UI (bukan hanya jQuery).

Anda sekarang dapat menggunakan:

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

Untuk penentuan posisi cepat ( UI jQuery / Posisi ).

Anda dapat mengunduh jQuery UI di sini .

Uriel
sumber
1
Saya sudah mencoba menggunakan plugin positon tetapi untuk beberapa alasan saya tidak bisa membuatnya bekerja :(
Salman A
Juga tidak bekerja untuk saya. Mencoba menggunakan ini untuk memposisikan div warna solid sederhana di atas bodi yang mengakibatkannya mati sebanyak 17 piksel di kiri atas.
Terong Jeff
46
Perhatikan bahwa jawaban ini tergantung pada jQueryUI, bukan hanya jQuery. Mungkin jelaskan mengapa itu tidak berhasil untuk Anda berdua.
btubbs
398

tl; dr: (coba di sini )

Jika Anda memiliki HTML berikut:

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

maka Anda dapat menggunakan kode JavaScript berikut:

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

Tapi itu tidak berhasil!

Ini akan berfungsi selama menu dan placeholder memiliki orangtua offset yang sama. Jika tidak, dan Anda tidak memiliki aturan CSS bersarang yang peduli dengan #menuelemen DOM , gunakan:

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

tepat sebelum garis yang memposisikan #menuelemen.

Tapi tetap saja tidak berhasil!

Anda mungkin memiliki beberapa tata letak aneh yang tidak berfungsi dengan pendekatan ini. Dalam hal ini, cukup gunakan plugin posisi jQuery.ui (sebagaimana disebutkan dalam jawaban di bawah), yang menangani setiap kemungkinan kejadian . Perhatikan bahwa Anda harus ke show()elemen menu sebelum memanggil position({...}); plugin tidak dapat memposisikan elemen tersembunyi.

Perbarui catatan 3 tahun kemudian pada tahun 2012:

(Solusi asli diarsipkan di sini untuk anak cucu)

Jadi, ternyata metode asli yang saya miliki di sini jauh dari ideal. Secara khusus, itu akan gagal jika:

  • orang tua offset menu bukan orang tua pengganti placeholder
  • placeholder memiliki perbatasan / padding

Untungnya, jQuery memperkenalkan metode ( position()dan outerWidth()) jalan kembali ke 1.2.6 yang membuat menemukan nilai yang tepat dalam kasus terakhir di sini jauh lebih mudah. Untuk kasus sebelumnya, appendmemasukkan elemen menu ke placeholder works (tetapi akan melanggar aturan CSS berdasarkan nesting).

Yakub
sumber
168
Whoa ini aneh: Saya harus melakukan ini beberapa hari yang lalu, tidak bisa mengingat bagaimana, mencari di Google dan mendapatkan ... jawaban ini! Harus cinta SOF.
Jacob
17
Heh - saya pernah mengalami hal yang sama pada saya - tidak ingat bagaimana melakukan sesuatu, dan menemukan jawaban saya sendiri di Stack Overflow.
Herb Caudill
16
Saya pikir gaya menu div Anda harus menggunakan tampilan: tidak ada alih-alih tampilan: disembunyikan.
Gabe
6
Ini tidak akan berfungsi dengan baik ketika wadah menu memiliki posisi: relatif (atau apa pun selain mewarisi), karena posisi: absolut akan mematikan itu, dan .offset akan mematikan dari kiri atas halaman.
Mike Cooper
3
Bergantung pada bagaimana posisi menu Anda .offset () jQuery dapat digunakan sebagai pengganti drop-in untuk .position (). api.jquery.com/offset
Danny C
16

Inilah yang pada akhirnya berhasil bagi saya.

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

Berikut adalah fungsi jQuery yang saya tulis yang membantu saya memposisikan elemen.

Berikut adalah contoh penggunaannya:

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

Kode di atas menyejajarkan kanan-bawah # el1 dengan kanan-atas # el2. ['cc', 'cc'] akan memusatkan # el1 di # el2. Pastikan # el1 memiliki css posisi: absolut dan indeks-z: 10000 (atau angka yang sangat besar) untuk tetap di atasnya.

Opsi offset memungkinkan Anda untuk mendorong koordinat dengan jumlah piksel tertentu.

Kode sumber di bawah ini:

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

}
Venkat D.
sumber
3

Mengapa terlalu rumit? Solusinya sangat sederhana

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

Itu bekerja bahkan jika,

  • Dua div ditempatkan di tempat lain
  • Ukuran browser kembali
gtamil
sumber
metode ini tidak berfungsi jika saya ingin meniru placeholder yaitu dan menunjukkan input di atas (
tibalt
Ini tidak berfungsi ketika saya ingin menyelaraskan dua elemen yang bersaudara atau bahkan sama sekali tidak terkait, yang sangat umum.
oriadam
3

Anda dapat menggunakan plugin jQuery PositionCalculator

Plugin itu juga termasuk penanganan tabrakan (flip), sehingga menu seperti toolbar dapat ditempatkan pada posisi yang terlihat.

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

untuk markup itu:

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

Ini biola: http://jsfiddle.net/QrrpB/1657/

TLindig
sumber
Console menulis Undefined bukan fungsi untuk baris: var pos = $ .PositionCalculator ({Bisakah Anda membantu menyelesaikan masalah ini?
Alexandr Belov
@AlexandrBelov: Saya kira, Anda tidak memuat plugin. Sebelum Anda dapat menggunakannya, Anda harus memuat file js dari plugin PositionCalculator.
TLindig
2

Sesuatu seperti ini?

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

Ini bekerja untuk saya:

var posPersonTooltip = function(event) {
var tPosX = event.pageX - 5;
var tPosY = event.pageY + 10;
$('#personTooltipContainer').css({top: tPosY, left: tPosX});
devXen
sumber