Come posizionare un elemento rispetto ad un altro con jQuery?


354

Ho un DIV nascosto che contiene un menu simile a una barra degli strumenti.

Ho un numero di DIV che sono abilitati a mostrare il menu DIV quando il mouse passa sopra di essi.

Esiste una funzione integrata che sposta il menu DIV nella parte superiore destra del DIV attivo (passaggio del mouse)? Sto cercando qualcosa di simile$(menu).position("topright", targetEl);


1
dai un'occhiata a stackoverflow.com/questions/8400876/… che risolve molti altri problemi che possono verificarsi
Toskan,

Si prega di consultare "Le domande dovrebbero includere" tag "nei loro titoli?" , dove il consenso è "no, non dovrebbero"!
Andreas Niedermair,

@paul Sì, c'è una leggera differenza nello stile. Il titolo iniziale di questa domanda era preceduto da jQuery: che non è incoraggiato. Di solito, a causa della codifica aggiuntiva della domanda, ciò rende inutile il prefisso. Se la tecnologia è necessaria nel titolo, dovrebbe essere catturata in una frase reale , non solo in un prefisso, perché è a questo che servono i tag.
Andreas Niedermair,

Risposte:


203

NOTA: ciò richiede l'interfaccia utente di jQuery (non solo jQuery).

Ora puoi usare:

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

Per un posizionamento rapido ( interfaccia utente / posizione jQuery ).

Puoi scaricare l'interfaccia utente di jQuery qui .


1
Ho provato a usare il plugin Positon ma per qualche ragione non riesco proprio a farlo funzionare :(
Salman A

Inoltre non funziona per me. Il tentativo di utilizzare questo per posizionare un semplice div a tinta unita sopra il corpo ha provocato lo spegnimento di 17 pixel in alto a sinistra.
Melanzana Jeff,

46
Nota che questa risposta dipende da jQueryUI, non solo da jQuery. Potrebbe spiegare perché non funziona per un paio di voi.
btubbs,

398

tl; dr: (provalo qui )

Se hai il seguente 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>

quindi è possibile utilizzare il seguente codice 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();
});

Ma non funziona!

Funzionerà finché il menu e il segnaposto avranno lo stesso genitore offset. In caso contrario, e non hai regole CSS nidificate che si preoccupano della posizione nel DOM #menudell'elemento, usa:

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

appena prima della linea che posiziona l' #menuelemento.

Ma non funziona ancora!

Potresti avere un layout strano che non funziona con questo approccio. In tal caso, basta usare il plug-in di posizione di jQuery.ui (come menzionato in una risposta di seguito), che gestisce ogni possibile eventualità. Nota che show()prima di chiamare dovrai accedere all'elemento del menu position({...}); il plugin non può posizionare elementi nascosti.

Note di aggiornamento 3 anni dopo nel 2012:

(La soluzione originale è archiviata qui per i posteri)

Quindi, risulta che il metodo originale che avevo qui era tutt'altro che ideale. In particolare, fallirebbe se:

  • il genitore offset del menu non è il genitore offset del segnaposto
  • il segnaposto ha un bordo / imbottitura

Fortunatamente, jQuery ha introdotto metodi ( position()e outerWidth()) nella versione 1.2.6 che rendono molto più facile trovare i valori giusti in quest'ultimo caso. Nel primo caso, appendil passaggio al segnaposto dall'elemento di menu funziona (ma infrange le regole CSS in base all'annidamento).


168
Whoa questo è strano: ho dovuto farlo l'altro giorno, non riuscivo a ricordare come, ho cercato su Google e ho ottenuto ... questa risposta! Devo amare SOF.
Jacob,

17
Heh - mi è successa la stessa cosa - non riuscivo a ricordare come fare qualcosa e ho trovato la mia risposta su Stack Overflow.
Herb Caudill

16
Penso che il tuo stile div menu dovrebbe usare display: none invece di display: nascosto.
Gabe,

6
Questo non funzionerà correttamente quando il contenitore del menu ha posizione: relativo (o qualsiasi cosa oltre a ereditare), poiché position: absolute lo disattiverà e .offset si staccherà dalla parte superiore sinistra della pagina.
Mike Cooper,

3
A seconda di come viene posizionato il menu .offset () di jQuery può essere utilizzato come sostituto drop-in per .position (). api.jquery.com/offset
Danny C

16

Questo è ciò che ha funzionato per me alla fine.

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

Ecco una funzione jQuery che ho scritto che mi aiuta a posizionare gli elementi.

Ecco un esempio di utilizzo:

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

Il codice sopra allinea la parte in basso a destra di # el1 con la parte in alto a destra di # el2. ['cc', 'cc'] dovrebbe centrare # el1 in # el2. Assicurati che # el1 abbia il css di position: absolute e z-index: 10000 (o qualche numero davvero grande) per tenerlo in cima.

L'opzione offset consente di spostare le coordinate di un numero specificato di pixel.

Il codice sorgente è di seguito:

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

Perché complicare troppo? La soluzione è molto semplice

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

Funziona anche se,

  • Due div posizionati altrove
  • Browser ridimensionato

questo metodo non funziona se voglio emulare il segnaposto per ie e mostrarlo sopra l'input (
tibalt

Questo non funziona quando voglio allineare due elementi che sono fratelli o addirittura completamente non correlati, il che è molto comune.
Oriadam,

3

È possibile utilizzare il plug-in PositionCalculator di jQuery

Quel plugin ha anche incluso la gestione delle collisioni (flip), quindi il menu simile a una barra degli strumenti può essere posizionato in una posizione visibile.

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

per quel markup:

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

Ecco il violino: http://jsfiddle.net/QrrpB/1657/


La console scrive Undefined non è una funzione per la riga: var pos = $ .PositionCalculator ({Per favore, puoi aiutare a risolvere il problema?
Alexandr Belov,

@AlexandrBelov: suppongo che non hai caricato il plugin. Prima di poterlo utilizzare, devi caricare il file js del plug-in PositionCalculator.
TLindig,

2

Qualcosa come questo?

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

2

Questo funziona per me:

var posPersonTooltip = function(event) {
var tPosX = event.pageX - 5;
var tPosY = event.pageY + 10;
$('#personTooltipContainer').css({top: tPosY, left: tPosX});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.