CSS: Wie positioniere ich zwei Elemente übereinander, ohne eine Höhe anzugeben?

96

Ich habe zwei DIVs, die ich genau übereinander positionieren muss. Wenn ich das mache, wird die Formatierung jedoch völlig durcheinander gebracht, da der enthaltende DIV so wirkt, als gäbe es keine Höhe. Ich denke, dies ist das erwartete Verhalten, position:absoluteaber ich muss einen Weg finden, diese beiden Elemente übereinander zu positionieren und den Container zu dehnen, wenn sich der Inhalt erstreckt:

Die obere linke Kante von .layer2sollte genau an der oberen linken Kante von ausgerichtet seinlayer1

<!-- HTML -->
<div class="container_row">
    <div class="layer1">
        Lorem ipsum...
    </div>
    <div class="layer2">
        More lorem ipsum...
    </div>
</div>
<div class="container_row">
    ...same HTML as above. This one should never overlap the .container_row above.
</div>

/* CSS */
.container_row {}

.layer1 {
    position:absolute;
    z-index: 1;
}

.layer2 {
    position:absolute;
    z-index: 2;
}
Andrew
quelle
1
position: absoluteist dann nicht ganz der richtige Stil.
BoltClock
Ja, position:absolutefühlt sich nicht richtig an. Was wäre der richtige Stil?
Andrew
Das tun die .layer1und .layer2Elemente haben eine bekannte Größe?
Mu ist zu kurz
Nein, sie haben auch eine unbekannte Größe.
Andrew

Antworten:

81

Zuallererst sollten Sie wirklich die Position auf absolut positionierten Elementen angeben, sonst werden Sie auf merkwürdiges und verwirrendes Verhalten stoßen. Sie möchten wahrscheinlich top: 0; left: 0das CSS für beide absolut positionierten Elemente erweitern. Sie werden auch haben wollen position: relativeauf , .container_rowwenn Sie die absolut positionierten Elemente wollen positioniert werden in Bezug auf ihre Eltern , anstatt das Dokument des Körpers :

Wenn das Element 'position: absolute' hat, wird der enthaltende Block vom nächsten Vorfahren mit einer 'Position' von 'absolut', 'relativ' oder 'fest' festgelegt ...

Ihr Problem ist, dass position: absoluteElemente aus dem normalen Fluss entfernt werden :

Es wird vollständig aus dem normalen Fluss entfernt (es hat keine Auswirkungen auf spätere Geschwister). Eine absolut positionierte Box erstellt einen neuen Block für normal fließende Kinder und absolut (aber nicht fest) positionierte Nachkommen. Der Inhalt eines absolut positionierten Elements fließt jedoch nicht um andere Boxen.

Dies bedeutet, dass absolut positionierte Elemente keinerlei Einfluss auf die Größe des übergeordneten Elements haben und Ihr erstes Element <div class="container_row">eine Höhe von Null hat.

Sie können also nicht das tun, was Sie mit absolut positionierten Elementen versuchen, es sei denn, Sie wissen, wie hoch sie sein werden (oder Sie können entsprechend deren Höhe angeben). Wenn Sie die Höhen angeben können, können Sie die gleichen Höhen auf die setzen, .container_rowund alles wird ausgerichtet. Sie können auch eine margin-topzweite setzen .container_row, um Platz für die absolut positionierten Elemente zu lassen. Beispielsweise:

http://jsfiddle.net/ambiguous/zVBDc/

mu ist zu kurz
quelle
Tolle Antwort, danke! Ich denke, ich muss möglicherweise die Höhe dynamisch mit Javascript herausfinden. Ich hatte nur gehofft, dass es nicht dazu kommen musste. = [
Andrew
@ Andrew: Ja, willkommen beim vertikalen Größen- / Positions- / Ausrichtungssystem von CSS: Wenn Sie die spezifischen Größen der Dinge nicht kennen, haben Sie normalerweise kein Glück. Das horizontale Material ist einfacher zu handhaben, aber das meiste riecht immer noch so, als ob es von "Druckern mit festem Layout" und nicht von "Personen mit dynamischem Layout" entworfen wurde.
Mu ist zu kurz
1
Nicht position: absolutebenötigt. Bitte überprüfen Sie: stackoverflow.com/a/51949049/1736186
stattdessen
62

Tatsächlich ist dies ohne Position absoluteund Angabe einer Höhe möglich. Alles was Sie tun müssen, ist zu verwendendisplay: grid übergeordnete Element zu verwenden und Nachkommen in dieselbe Zeile und Spalte zu setzen.

Bitte überprüfen Sie das folgende Beispiel basierend auf Ihrem HTML. Ich habe nur hinzugefügt<span> einige Farben , damit Sie das Ergebnis sehen können.

Sie können auch einfach z-indexjedes der untergeordneten Elemente ändern , um seine Sichtbarkeit zu ändern (welches sollte oben sein).

.container_row{
  display: grid;
}

.layer1, .layer2{
  grid-column: 1;
  grid-row: 1;
}

.layer1 span{
  color: #fff;
  background: #000cf6;
}

.layer2{
  background: rgba(255, 0, 0, 0.4);
}
<div class="container_row">
    <div class="layer1">
        <span>Lorem ipsum...<br>Test test</span>
    </div>
    <div class="layer2">
        More lorem ipsum...
    </div>
</div>
<div class="container_row">
    ...same HTML as above. This one should never overlap the .container_row above.
</div>

stattdessen
quelle
11
Nett. Aber um fair zu sein, display: gridgab es vor sieben Jahren noch nicht :)
mu ist zu kurz
Es gibt unten eine andere Antwort, geschrieben von @Cornelius. Er verwendet flex, was heutzutage eine viel bessere Browserunterstützung hat.
Oleg Cherr
20

Tolle Antwort, "mu ist zu kurz". Ich habe genau das Gleiche gesucht und nach dem Lesen Ihres Beitrags eine Lösung gefunden, die zu meinem Problem passt.

Ich hatte zwei Elemente mit genau der gleichen Größe und wollte sie stapeln. Da jeder die gleiche Größe hat, konnte ich nur machen

position: absolute;
top: 0px;
left: 0px;

nur auf das letzte Element. Auf diese Weise wird das erste Element korrekt eingefügt, wodurch die Höhe der Eltern "gedrückt" wird, und das zweite Element wird oben platziert.

Hoffentlich hilft dies anderen Menschen, die versuchen, 2+ Elemente mit derselben (unbekannten) Höhe zu stapeln.

Kraenhansen
quelle
1
NB: Bei diesem Ansatz müssen Sie immer noch wissen, welches Element das größere ist, damit Sie position: aboslutedas andere können .
Alec
9

Hier ist eine andere Lösung, bei der display: flex anstelle von position: absolute oder display: grid verwendet wird.

.container_row{
  display: flex;
}

.layer1 {
  width: 100%;
  background-color: rgba(255,0,0,0.5);  // red
}

.layer2{
  width: 100%;
  margin-left: -100%;
  background-color: rgba(0,0,255,0.5);  // blue
}
<div class="container_row">
    <div class="layer1">
        <span>Lorem ipsum...</span>
    </div>
    <div class="layer2">
        More lorem ipsum...
    </div>
</div>
<div class="container_row">
    ...same HTML as above. This one should never overlap the .container_row above.
</div>

Cornelius
quelle
Tolle Lösung. Vielen Dank!
Oleg Cherr
5

Ich musste setzen

Container_Höhe = Element1_Höhe = Element2_Höhe

.Container {
    position: relative;
}

.ElementOne, .Container ,.ElementTwo{
    width: 283px;
    height: 71px;
}

.ElementOne {
    position:absolute;
}

.ElementTwo{
    position:absolute;
}

Use kann den Z-Index verwenden, um festzulegen, welcher oben sein soll.

Arun Prasad ES
quelle
4

Hier ist ein wiederverwendbares CSS, das die Höhe jedes Elements ohne Verwendung beibehält position: absolute:

.stack {
    display: grid;
}
.stack > * {
    grid-row: 1;
    grid-column: 1;
}

Das erste Element in Ihrem stackist der Hintergrund und das zweite ist der Vordergrund.

Ken Mueller
quelle
2

Aufgrund der absoluten Positionierung werden die Elemente aus der Dokumentenflussposition entfernt: Absolut ist nicht das richtige Werkzeug für den Job. Abhängig von dem genauen Layout, das Sie erstellen möchten, werden Sie mit negativen Rändern, Position: relativ oder vielleicht sogar transformieren: übersetzen erfolgreich sein. Zeigen Sie uns ein Beispiel, was Sie tun möchten. Wir können Ihnen besser helfen.

Luiz Sócrate
quelle
1

Natürlich geht es nur darum, die Größe wieder herzustellen. Aber wie können Sie das tun, wenn Sie die Höhe nicht im Voraus kennen? Wenn Sie wissen, welches Seitenverhältnis Sie dem Container geben möchten (und darauf reagieren möchten), können Sie Ihre Körpergröße zurückerhalten, indem Sie einem anderen untergeordneten Element des Containers eine Polsterung hinzufügen, ausgedrückt als Prozentsatz.

Sie können divdem Container sogar einen Dummy hinzufügen und so etwas wie einstellenpadding-top: 56.25% , dass das Dummy-Element eine Höhe erhält, die einem Anteil der Breite des Containers entspricht. Dadurch wird der Behälter herausgedrückt und erhält ein Seitenverhältnis, in diesem Fall 16: 9 (56,25%).

Polsterung und Rand verwenden den Prozentsatz der Breite, das ist hier wirklich der Trick.

Luke Puplett
quelle
0

Nach vielen Tests habe ich überprüft, dass die ursprüngliche Frage bereits richtig ist. Es fehlen nur ein paar Einstellungen:

  • das container_rowmuss habenposition: relative;
  • Die Kinder (...) müssen haben position: absolute; left:0;
  • Um sicherzustellen, dass die Kinder (...) genau übereinander ausgerichtet sind, container_rowsollte das zusätzliche Styling vorhanden sein:
    • height:x; line-height:x; vertical-align:middle;
    • text-align:center; könnte auch helfen.
gerade vorbei
quelle