Wie positioniere ich ein Element mit jQuery relativ zu einem anderen?


354

Ich habe einen versteckten DIV, der ein Symbolleisten-ähnliches Menü enthält.

Ich habe eine Reihe von DIVs, die aktiviert sind, um das Menü DIV anzuzeigen, wenn die Maus darüber bewegt wird.

Gibt es eine eingebaute Funktion, mit der das Menü DIV oben rechts neben dem aktiven DIV (Mauszeiger) verschoben wird? Ich suche so etwas wie$(menu).position("topright", targetEl);


1
Werfen Sie einen Blick auf stackoverflow.com/questions/8400876/…, der so viele weitere Probleme behebt, die auftreten können
Toskan

Siehe "Sollten Fragen" Tags "in ihren Titeln enthalten?" , wo der Konsens lautet "nein, sollten sie nicht"!
Andreas Niedermair

@ Paul Ja, es gibt einen kleinen Unterschied im Stil. Dem ursprünglichen Titel dieser Frage wurde jQuery: vorangestellt , was nicht empfohlen wird. In der Regel aufgrund der zusätzlichen Kennzeichnung der Frage, wodurch das Präfix unbrauchbar wird. Wenn die Technologie im Titel benötigt wird, sollte sie in einem echten Satz erfasst werden , nicht nur in einem Präfix - denn dafür sind Tags gedacht.
Andreas Niedermair

Antworten:


203

HINWEIS: Dies erfordert eine jQuery-Benutzeroberfläche (nicht nur jQuery).

Sie können jetzt verwenden:

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

Zur schnellen Positionierung ( jQuery UI / Position ).

Sie können die jQuery-Benutzeroberfläche hier herunterladen .


1
Ich habe versucht, das Positon-Plugin zu verwenden, aber aus irgendeinem Grund kann ich es einfach nicht zum Laufen bringen :(
Salman A

Funktioniert auch nicht bei mir. Der Versuch, damit ein einfaches einfarbiges Div über dem Körper zu positionieren, führte dazu, dass es um 17 Pixel nach links oben verschoben war.
Aubergine Jeff

46
Beachten Sie, dass diese Antwort von jQueryUI abhängt, nicht nur von jQuery. Könnte erklären, warum es für ein paar von Ihnen nicht funktioniert.
Btubbs

398

tl; dr: (versuche es hier )

Wenn Sie folgenden HTML-Code haben:

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

Dann können Sie den folgenden JavaScript-Code verwenden:

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

Aber es funktioniert nicht!

Dies funktioniert so lange, wie das Menü und der Platzhalter denselben übergeordneten Versatz haben. Wenn dies nicht der Fall #menuist und Sie keine verschachtelten CSS-Regeln haben, die sich darum kümmern, wo sich das Element im DOM befindet, verwenden Sie:

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

kurz vor der Linie, die das #menuElement positioniert .

Aber es funktioniert immer noch nicht!

Möglicherweise haben Sie ein seltsames Layout, das mit diesem Ansatz nicht funktioniert. Verwenden Sie in diesem Fall einfach das Positions-Plugin von jQuery.ui (wie in einer Antwort unten erwähnt), das alle denkbaren Eventualitäten behandelt. Beachten Sie, dass Sie show()vor dem Aufruf das Menüelement aufrufen müssen position({...}). Das Plugin kann keine versteckten Elemente positionieren.

Update Notizen 3 Jahre später im Jahr 2012:

(Die ursprüngliche Lösung ist hier für die Nachwelt archiviert )

Es stellt sich also heraus, dass die ursprüngliche Methode, die ich hier hatte, alles andere als ideal war. Insbesondere würde es scheitern, wenn:

  • Das übergeordnete Element des Menüs ist nicht das übergeordnete Element des Platzhalters
  • Der Platzhalter hat einen Rand / Abstand

Glücklicherweise hat jQuery bereits in 1.2.6 Methoden ( position()und outerWidth()) eingeführt, die es im letzteren Fall viel einfacher machen, die richtigen Werte zu finden. Im ersteren Fall appendfunktioniert das Einfügen des Menüelements in den Platzhalter (verstößt jedoch gegen CSS-Regeln, die auf der Verschachtelung basieren).


168
Whoa das ist verrückt: Ich musste das neulich machen, konnte mich nicht erinnern wie, googelte es und bekam ... diese Antwort! Muss SOF lieben.
Jacob

17
Heh - mir ist das Gleiche passiert - konnte mich nicht erinnern, wie man etwas macht, und fand meine eigene Antwort auf Stack Overflow.
Herb Caudill

16
Ich denke, Ihr Menü-Div-Stil sollte display: none anstelle von display: hidden verwenden.
Gabe

6
Dies funktioniert nicht richtig, wenn der Container des Menüs die Position: relativ (oder etwas anderes als erben) hat, da position: absolute das abtastet und .offset oben links auf der Seite abschaltet.
Mike Cooper

3
Abhängig von der Position Ihres Menüs kann jQuerys .offset () als Drop-In-Ersatz für .position () verwendet werden. api.jquery.com/offset
Danny C

16

Das hat am Ende für mich funktioniert.

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

Hier ist eine von mir geschriebene jQuery-Funktion, mit der ich Elemente positionieren kann.

Hier ist ein Anwendungsbeispiel:

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

Der obige Code richtet die untere rechte Seite von # el1 an der oberen rechten Seite von # el2 aus. ['cc', 'cc'] würde # el1 in # el2 zentrieren. Stellen Sie sicher, dass # el1 das CSS der Position: Absolut und Z-Index: 10000 (oder eine wirklich große Zahl) hat, um es oben zu halten.

Mit der Versatzoption können Sie die Koordinaten um eine bestimmte Anzahl von Pixeln verschieben.

Der Quellcode ist unten:

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

Warum zu viel komplizieren? Die Lösung ist sehr einfach

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

Es funktioniert auch wenn,

  • Zwei Divs, die irgendwo anders platziert sind
  • Browser in der Größe geändert

Diese Methode funktioniert nicht, wenn ich Platzhalter für dh emulieren und über der Eingabe zeigen möchte (
Tibalt

Dies funktioniert nicht, wenn ich zwei Elemente ausrichten möchte, die Geschwister sind oder gar nichts miteinander zu tun haben, was sehr häufig vorkommt.
Oriadam

3

Sie können das jQuery-Plugin PositionCalculator verwenden

Dieses Plugin enthält auch eine Kollisionsbehandlung (Flip), sodass das Symbolleisten-ähnliche Menü an einer sichtbaren Position platziert werden kann.

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

für diesen Aufschlag:

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

Hier ist die Geige: http://jsfiddle.net/QrrpB/1657/


Konsole schreibt Undefiniert ist keine Funktion für die Zeile: var pos = $ .PositionCalculator ({Können Sie bitte helfen, das Problem zu lösen?
Alexandr Belov

@AlexandrBelov: Ich denke, du hast das Plugin nicht geladen. Bevor Sie es verwenden können, müssen Sie die js-Datei des Plugins PositionCalculator laden.
TLindig

2

Etwas wie das?

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

2

Das funktioniert bei mir:

var posPersonTooltip = function(event) {
var tPosX = event.pageX - 5;
var tPosY = event.pageY + 10;
$('#personTooltipContainer').css({top: tPosY, left: tPosX});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.