Zrób absolutnie pozycjonowany div, rozwiń macierzystą wysokość div

204

Jak widać poniżej w CSS, chcę child2się wcześniej ustawić child1. Wynika to z faktu, że witryna, którą aktualnie opracowuję, powinna również działać na urządzeniach mobilnych, na których child2powinna znajdować się na dole, ponieważ zawiera nawigację, którą chcę poniżej treści na urządzeniach mobilnych. - Dlaczego nie 2 strony główne? To są jedyne 2, divsktóre zostały przesunięte w całym HTML, więc 2 strony główne dla tej drobnej zmiany to przesada.

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 ma wysokość dynamiczną, ponieważ różne podwitryny mogą zawierać mniej lub więcej elementów nawigacyjnych.

Wiem, że elementy pozycjonowane absolutnie są usuwane z przepływu, a zatem są ignorowane przez inne elementy.
Próbowałem ustawić overflow:hidden;div rodzica, ale to nie pomogło, podobnie jak clearfix.

Moim ostatecznym rozwiązaniem będzie JavaScript, aby odpowiednio zmienić ich położenie divs, ale na razie postaram się sprawdzić, czy istnieje sposób inny niż JavaScript.

Micha Wiedenmann
źródło
3
Nie jestem w 100% pewien, ale myślę, że prawdopodobnie będziesz musiał wybrać rozwiązanie JS, które obliczy wysokość child2 i odpowiednio przeniesie child1.
Billy Fosa
2
Można to zrobić, ustawiając pozycję rodzica na krewną, a dziecko na absolutną.
fungusanthrax
1
Zobacz to obejście, może to może pomóc.
Az.Youness

Odpowiedzi:

152

Sam odpowiedziałeś na pytanie: „Wiem, że elementy pozycjonowane absolutnie są usuwane z przepływu, a zatem są ignorowane przez inne elementy”. Nie można więc ustawić wysokości rodziców zgodnie z absolutnie pozycjonowanym elementem.

Albo używasz ustalonych wysokości, albo musisz zaangażować JS.

feeela
źródło
1
Zaznaczam to, ponieważ technicznie jest to właściwy sposób, chociaż znalazłem inne rozwiązanie mojego problemu, którym jest praktycznie zagnieżdżenie wymaganego css na konkretnych stronach, które muszą się różnić (obecnie 2 z 40).
16

Chociaż rozciąganie do elementów za pomocą position: absolutenie jest możliwe, często istnieją rozwiązania, w których można uniknąć absolutnego pozycjonowania, uzyskując ten sam efekt. Spójrz na to skrzypce, które rozwiązują problem w twoim konkretnym przypadku http://jsfiddle.net/gS9q7/

Sztuczka polega na odwróceniu kolejności elementów poprzez przesunięcie obu elementów, pierwszego w prawo, drugiego w lewo, aby drugi pojawił się pierwszy.

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

Na koniec dodaj poprawkę do obiektu nadrzędnego i gotowe (zobacz skrzynkę dla kompletnego rozwiązania).

Zasadniczo, dopóki element z pozycją bezwzględną jest umieszczony na górze elementu nadrzędnego, istnieje spora szansa na obejście tego problemu przez przesunięcie elementu.

lex82
źródło
10

Feeela ma rację, ale możesz uzyskać od rodzicadivkurczenie się / rozwijanie do elementu potomnego, jeśli odwrócisz swojedivpozycjonowanie w następujący sposób:

.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 */
}

To powinno ci pomóc.

ChrisC
źródło
9

Istnieje dość prosty sposób na rozwiązanie tego problemu.

Musisz tylko zduplikować zawartość child1 i child2 we względnych div z display: none w parent div. Powiedz child1_1 i child2_2. Umieść child2_2 na górze, a child1_1 na dole.

Kiedy twoja jquery (lub cokolwiek) wywołuje div bezwzględny, po prostu ustaw odpowiedni względny div (child1_1 lub child2_2) z display: block AND visibility: hidden. Względne dziecko nadal będzie niewidoczne, ale zwiększy div rodzica.

MMB
źródło
2
To skłoniło mnie do myślenia we właściwym kierunku. W moim przypadku ustawienie wyświetlania: brak w treści „posiadacza rozmiaru” powoduje, że div nie ma rozmiaru, jednak krycie: 0, poprawnie dostosowuje div i nie wymaga żadnej dodatkowej jquery.
edencorbin,
Zrobiłem tak, aby uzyskać dwa duplikaty div. Pierwszy z nich to widoczna zawartość z pozycją absolutną, a drugi to div z widocznością ukrytą, który utrzymuje div div z odpowiednią wysokością, wszystko działa dobrze = D
Diogo Garcia
4

W przypadku czystego JavaScript wystarczy pobrać wysokość static positionelementu potomnego .child1za pomocą metody getComputedStyle () , a następnie ustawić tę wartość pobierania jako padding-topdla tego samego dziecka za pomocą właściwości HTMLElement.style .


Sprawdź i uruchom następujący fragment kodu, aby uzyskać praktyczny przykład tego, co opisałem powyżej:

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

AndrewL64
źródło
2

Miałem podobny problem. Aby rozwiązać ten problem (zamiast obliczać wysokość elementu iframe za pomocą treści, dokumentu lub okna), utworzyłem div, który otacza całą zawartość strony (na przykład div z id = "page"), a następnie użyłem jego wysokości.

Juliano
źródło
2

To pytanie zostało zadane w 2012 roku przed Flexboksem. Prawidłowym sposobem rozwiązania tego problemu za pomocą nowoczesnego CSS jest zapytanie o media i odwrócenie kolumny elastycznej dla urządzeń mobilnych. Pozycjonowanie bezwzględne nie jest potrzebne.

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;
  }
}
Hunter Nelson
źródło
1

Wymyśliłem inne rozwiązanie, którego nie kocham, ale wykonuje pracę.

Zasadniczo zduplikuj elementy potomne w taki sposób, aby duplikaty nie były widoczne.

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

Jeśli te elementy potomne zawierają niewiele znaczników, wpływ będzie niewielki.

btx9000
źródło
4
Może to powodować problemy z rankingiem wyszukiwarek
mschadegg
1

„Albo używasz ustalonych wysokości, albo musisz zaangażować JS”.

Oto przykład JS:

---------- Przykład jQuery JS --------------------

    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);
Nikolay
źródło
Ta odpowiedź mogłaby skorzystać z lepszego wyjaśnienia i ukierunkowania proponowanego rozwiązania.
DaniDev
1

Jest bardzo prosty hack, który rozwiązuje ten problem

Oto codeandbox, który ilustruje rozwiązanie: 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; }

możesz bawić się pozycjonowaniem div hacka, aby wpływać na pozycję dziecka.

Oto fragment:

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>

bernatfortet
źródło
0

Teraz jest na to lepszy sposób. Możesz użyć właściwości bottom.

    .my-element {
      position: absolute;
      bottom: 30px;
    }
rlasch
źródło
5
zadziała to tylko wtedy, gdy znasz ostateczną wysokość rodzica, czego nie
znasz
0

Jest to bardzo podobne do sugestii @ChrisC. Nie używa elementu pozycjonowanego absolutnie, ale względnego. Może może ci pomóc

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

Twój css lubi to:

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

Roy Rioio
źródło
0

Rozważ także następne podejście:

CSS:

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

Również, ponieważ próbujesz zmienić położenie div, rozważ css grid

Iegor Benzyk
źródło
-2

Widoki absolutne pozycjonują się względem najbliższego przodka, który nie jest pozycjonowany statycznie ( position: static), dlatego jeśli chcesz, aby widok absolutny był pozycjonowany względem danego rodzica, ustaw rodzica positionna relativei dziecko positionnaabsolute

Isaac Sekamatte
źródło
-4

Spróbuj, to zadziałało dla mnie

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

Ustawi wysokość dziecka na wysokość rodzica

Sarath E.
źródło
świetne rozwiązanie!
Alexander Cherednichenko
3
@AlexanderCherednichenko Nie bardzo, nie trafia w sedno pytania.
wickywills 11.04.2018