Stellen Sie sicher, dass das absolut positionierte div die übergeordnete div-Höhe erweitert


204

Wie Sie im folgenden CSS sehen können, möchte ich mich child2vorher positionieren child1. Dies liegt daran, dass die Website, die ich gerade entwickle, auch auf Mobilgeräten funktionieren child2sollte, auf der sich die Website unten befinden sollte, da sie die gewünschte Navigation unter den Inhalten auf den Mobilgeräten enthält. - Warum nicht 2 Masterseiten? Dies sind die einzigen 2, divsdie im gesamten HTML-Code neu positioniert werden. Daher sind 2 Masterseiten für diese geringfügige Änderung ein Overkill.

HTML:

<div id="parent">
    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

parent { position: relative; width: 100%; }
child1 { width: auto; margin-left: 160px; }
child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }

child2 hat eine dynamische Höhe, da verschiedene Unterwebsites mehr oder weniger Navigationselemente haben können.

Ich weiß, dass absolut positionierte Elemente aus dem Fluss entfernt und daher von anderen Elementen ignoriert werden.
Ich habe versucht, overflow:hidden;das übergeordnete Div festzulegen, aber das hat nicht geholfen, und das auch nicht clearfix.

Mein letzter Ausweg wird JavaScript sein, um die beiden divsentsprechend neu zu positionieren , aber jetzt werde ich versuchen, herauszufinden, ob es eine Nicht-JavaScript-Methode gibt, um dies zu tun.


3
Ich bin nicht 100% sicher, aber ich denke, Sie müssen sich wahrscheinlich für eine JS-Lösung entscheiden, die die Größe von child2 berechnet und child1 entsprechend bewegt.
Billy Moat

2
Dies kann erreicht werden, indem die Position des Elternteils auf relativ und des Kindes auf absolut gesetzt wird.
Pilzanthrax

1
Sehen Sie sich diese Problemumgehung an, vielleicht kann sie helfen.
Az.Youness

Antworten:


151

Sie haben die Frage selbst beantwortet: "Ich weiß, dass absolut positionierte Elemente aus dem Fluss entfernt und von anderen Elementen ignoriert werden." Sie können die Größe der Eltern also nicht nach einem absolut positionierten Element einstellen.

Sie verwenden entweder feste Höhen oder Sie müssen JS einbeziehen.


1
Ich markiere dies als technisch korrekt, obwohl ich eine andere Lösung für mein Problem gefunden habe, nämlich praktisch das erforderliche CSS auf den spezifischen Seiten zu verschachteln, die differenziert werden müssen (2 von 40 im Moment).

16

Obwohl das Strecken auf Elemente mit position: absolutenicht möglich ist, gibt es häufig Lösungen, bei denen Sie die absolute Positionierung vermeiden und gleichzeitig den gleichen Effekt erzielen können. Schauen Sie sich diese Geige an, die das Problem in Ihrem speziellen Fall löst Http://jsfiddle.net/gS9q7/

Der Trick besteht darin, die Elementreihenfolge umzukehren, indem beide Elemente schweben, das erste nach rechts und das zweite nach links, sodass das zweite zuerst angezeigt wird.

.child1 {
    width: calc(100% - 160px);
    float: right;
}
.child2 {
    width: 145px;
    float: left;
}

Fügen Sie zum Schluss dem Eltern einen Clearfix hinzu, und Sie sind fertig (siehe die die vollständige Lösung finden Geige ).

Solange sich das Element mit der absoluten Position oben im übergeordneten Element befindet, besteht im Allgemeinen eine gute Chance, dass Sie eine Problemumgehung finden, indem Sie das Element schweben lassen.


10

Feeela hat recht, aber Sie können einen Elternteil dazu bringendiv, sich zu einem untergeordneten Element zusammenzuziehen / zu erweitern, wenn Sie IhredivPosition wie folgt umkehren:

.parent{
    postion: absolute;
    /* position it in the browser using the `left`, `top` and `margin` 
       attributes */
}

.child{
    position: relative;
    height: 100%;
    width: 100%;

    overflow: hidden;
    /* to pad or move it around using `left` and `top` inside the parent */
}

Dies sollte für Sie funktionieren.


9

Es gibt einen recht einfachen Weg, dies zu lösen.

Sie müssen nur den Inhalt von child1 und child2 in relativen Divs mit Anzeige duplizieren: keine in parent div. Sagen Sie child1_1 und child2_2. Setzen Sie child2_2 oben und child1_1 unten ein.

Wenn Ihre Abfrage (oder was auch immer) das absolute Div aufruft, setzen Sie einfach das entsprechende relative Div (child1_1 oder child2_2) mit display: block AND sichtbarkeit: hidden. Das relative Kind ist immer noch unsichtbar, erhöht jedoch den Div der Eltern.


2
Das brachte mich dazu, in die richtige Richtung zu denken. In meinem Fall zeigt die Einstellungsanzeige: Keine im Inhalt des "Größenhalters" die Größe des Div nicht an, jedoch die Deckkraft: 0, passt das Div korrekt an und erfordert keine zusätzliche Abfrage.
Edencorbin

Die Art und Weise, wie ich es getan habe, war, zwei doppelte Divs zu erhalten. Das erste ist der sichtbare Inhalt mit absoluter Position und das zweite ist ein Div mit versteckter Sichtbarkeit, das das übergeordnete Div mit der richtigen Höhe hält. Alles funktioniert einwandfrei = D
Diogo Garcia

4

Mit reinem JavaScript müssen Sie nur die Höhe Ihres untergeordnetenstatic position Elements .child1mit der Methode getComputedStyle () abrufen und diesen Abrufwertpadding-top mithilfe der Eigenschaft HTMLElement.style als denselben Wert für dasselbe untergeordnete Element festlegen .


Überprüfen Sie das folgende Code-Snippet und führen Sie es aus, um ein praktisches Beispiel für das zu finden, was ich oben beschrieben habe:

/* JavaScript */

var child1 = document.querySelector(".child1");
var parent = document.getElementById("parent");

var childHeight = parseInt(window.getComputedStyle(child1).height) + "px";
child1.style.paddingTop = childHeight;
/* CSS */

#parent { position: relative; width: 100%; }
.child1 { width: auto; }
.child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }
html, body { width: 100%;height: 100%; margin: 0; padding: 0; }
<!-- HTML -->

<div id="parent">
    <div class="child1">STATIC</div>
    <div class="child2">ABSOLUTE</div>
</div>


2

Ich hatte ein ähnliches Problem. Um dies zu lösen (anstatt die Höhe des Iframes mithilfe des Körpers, Dokuments oder Fensters zu berechnen), habe ich ein Div erstellt, das den gesamten Seiteninhalt umschließt (z. B. ein Div mit einer ID = "Seite"), und dann seine Höhe verwendet.


2

Diese Frage wurde 2012 vor der Flexbox gestellt. Der richtige Weg, um dieses Problem mit modernem CSS zu lösen, ist eine Medienabfrage und eine Flex-Spaltenumkehr für mobile Geräte. Es ist keine absolute Positionierung erforderlich.

https://jsfiddle.net/tnhsaesop/vjftq198/3/

HTML:

<div class="parent">
  <div style="background-color:lightgrey;">
    <p>
      I stay on top on desktop and I'm on bottom on mobile
    </p>
  </div>
  <div style="background-color:grey;">
    <p>
      I stay on bottom on desktop and I'm on bottom on mobile
    </p>
  </div>
</div>

CSS:

.parent {
  display: flex;
  flex-direction: column;
}

@media (max-width: 768px) {
  .parent {
    flex-direction: column-reverse;
  }
}

1

Ich habe eine andere Lösung gefunden, die ich nicht liebe, aber die Arbeit erledige.

Duplizieren Sie die untergeordneten Elemente grundsätzlich so, dass die Duplikate nicht sichtbar sind.

<div id="parent">
    <div class="width-calc">
        <div class="child1"></div>
        <div class="child2"></div>
    </div>

    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

.width-calc {
    height: 0;
    overflow: hidden;
}

Wenn diese untergeordneten Elemente wenig Markup enthalten, ist die Auswirkung gering.


4
Dies kann einige Probleme mit Suchmaschinenranking geben
mschadegg

1

"Sie verwenden entweder feste Höhen oder Sie müssen JS einbeziehen."

Hier ist das JS-Beispiel:

---------- jQuery JS Beispiel --------------------

    function findEnvelopSizeOfAbsolutelyPositionedChildren(containerSelector){
        var maxX = $(containerSelector).width(), maxY = $(containerSelector).height();

        $(containerSelector).children().each(function (i){
            if (maxX < parseInt($(this).css('left')) + $(this).width()){
                maxX = parseInt($(this).css('left')) + $(this).width();
            }
            if (maxY < parseInt($(this).css('top')) + $(this).height()){
                maxY = parseInt($(this).css('top')) + $(this).height();
            }
        });
        return {
            'width': maxX,
            'height': maxY
        }
    }

    var specBodySize = findEnvelopSizeOfAbsolutelyPositionedSubDivs("#SpecBody");
    $("#SpecBody").width(specBodySize.width);
    $("#SpecBody").height(specBodySize.height);

Diese Antwort könnte von einer besseren Erklärung und Ausrichtung der vorgeschlagenen Lösung profitieren.
DaniDev

1

Es gibt einen sehr einfachen Hack, der dieses Problem behebt

Hier ist eine Codesandbox, die die Lösung veranschaulicht: https://codesandbox.io/s/00w06z1n5l

HTML

<div id="parent">
  <div class="hack">
   <div class="child">
   </div>
  </div>
</div>

CSS

.parent { position: relative; width: 100%; }
.hack { position: absolute; left:0; right:0; top:0;}
.child { position: absolute; left: 0; right: 0; bottom:0; }

Sie können mit der Positionierung des Hack-Divs spielen, um zu beeinflussen, wo sich das Kind selbst positioniert.

Hier ist ein Ausschnitt:

html {
  font-family: sans-serif;
  text-align: center;
}

.container {
  border: 2px solid gray;
  height: 400px;
  display: flex;
  flex-direction: column;
}

.stuff-the-middle {
  background: papayawhip
    url("https://camo.githubusercontent.com/6609e7239d46222bbcbd846155351a8ce06eb11f/687474703a2f2f692e696d6775722e636f6d2f4e577a764a6d6d2e706e67");
  flex: 1;
}

.parent {
  background: palevioletred;
  position: relative;
}

.hack {
  position: absolute;
  left: 0;
  top:0;
  right: 0;
}
.child {
  height: 40px;
  background: rgba(0, 0, 0, 0.5);
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}
    <div class="container">
      <div class="stuff-the-middle">
        I have stuff annoyingly in th emiddle
      </div>
      <div class="parent">
        <div class="hack">
          <div class="child">
            I'm inside of my parent but absolutely on top
          </div>
        </div>
        I'm the parent
        <br /> You can modify my height
        <br /> and my child is always on top
        <br /> absolutely on top
        <br /> try removing this text
      </div>
    </div>


0

Es gibt jetzt einen besseren Weg, dies zu tun. Sie können die Eigenschaft bottom verwenden.

    .my-element {
      position: absolute;
      bottom: 30px;
    }

5
Dies funktioniert nur, wenn Sie die endgültige Größe des Elternteils kennen, die Sie nicht kennen
machineaddict

0

Dies ist sehr ähnlich zu dem, was @ChrisC vorgeschlagen hat. Es wird kein absolut positioniertes Element verwendet, sondern ein relatives. Vielleicht könnte für Sie arbeiten

<div class="container">
  <div class="my-child"></div>
</div>

Und dein CSS gefällt so:

.container{
    background-color: red;
    position: relative;
    border: 1px solid black;
    width: 100%;
}

.my-child{
    position: relative;
    top: 0;
    left: 100%;
    height: 100px;
    width: 100px;
    margin-left: -100px;
    background-color: blue;
}

https://jsfiddle.net/royriojas/dndjwa6t/


0

Betrachten Sie auch den nächsten Ansatz:

CSS:

.parent {
  height: 100%;
}
.parent:after {
  content: '';
  display: block;
}

Auch da Sie versuchen, Divs neu zu positionieren, sollten Sie das CSS-Raster berücksichtigen


-2

Absolute Ansichten positionieren sich gegen den nächsten Vorfahren, der nicht statisch positioniert ist ( position: static). Wenn Sie also eine absolute Ansicht gegen einen bestimmten Elternteil positionieren möchten, setzen Sie den Elternteil positionauf relativeund das Kind positionaufabsolute


-4

Versuchen Sie dies, es wurde für mich gearbeitet

.child {
    width: 100%;
    position: absolute;
    top: 0px;
    bottom: 0px;
    z-index: 1;
}

Die untergeordnete Größe wird auf die übergeordnete Größe eingestellt


tolle Lösung!
Alexander Cherednichenko

3
@AlexanderCherednichenko Nicht wirklich, es verfehlt den Punkt der Frage.
Wickywills
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.