Pozycjonowanie bezwzględne ignorujące dopełnienie elementu nadrzędnego

173

Jak sprawić, by element pozycjonowany bezwzględnie przestrzegał dopełnienia swojego rodzica? Chcę, aby wewnętrzny element DIV rozciągał się na szerokość swojego elementu nadrzędnego i był umieszczony na dole tego elementu nadrzędnego, czyli w zasadzie w stopce. Ale dziecko musi uszanować wyściółkę rodzica i tego nie robi. Dziecko jest przyciśnięte do krawędzi rodzica.

Więc chcę tego:

wprowadź opis obrazu tutaj

ale rozumiem to:

wprowadź opis obrazu tutaj

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
      <div style="background-color: gray; position: absolute; left: 0px; right: 0px; bottom: 0px;">css sux</div>
    </div>
  </body>
</html>

Mogę to zrobić z marginesem wokół wewnętrznego div, ale wolałbym nie musieć tego dodawać.

d512
źródło
5
Dlaczego nie zmienić lewej / prawej / dolnej części wewnętrznego div na style="background-color: gray; position: absolute; left: 10px; right: 10px; bottom: 10px;"?
j08691
12
Tak, pomyślałem o tym, ale szybko staje się to bólem głowy związanym z utrzymaniem, ponieważ każde dziecko musi mieć własny zestaw kompensacji, aby to uwzględnić. Gdyby tylko uszanowali wyściółkę rodzica, możesz po prostu ustawić ją raz w rodzicu i nie martwić się o wszystkie dzieci.
d512
Jak wskazano powyżej, jeśli użyjesz wartości wypełnienia rodzica (pozycjonowanego względnie) jako left:i right:na (pozycjonowanym bezwzględnie) dziecku, problem zostanie rozwiązany. Dodaję ten b / c, to jest odpowiedź, której prawdopodobnie szukają inni z tym samym problemem.
rda3000
Masz podobny problem tutaj: jsfiddle.net/5n4By/6 . Stopka honoruje lewe wypełnienie rodzica, ale przelewa się po prawej stronie. Spodziewałbyś się, że będzie on uwzględniał również odpowiednie wypełnienie, aby zachować spójność ...
rafiki_rafi,

Odpowiedzi:

186

Najpierw zobaczmy, dlaczego tak się dzieje.

Powodem jest to, że, co zaskakujące, kiedy pudełko ma position: absoluteswoje pudełko zawierające, jest to pole wyściółki rodzica (to znaczy pudełko wokół jego wypełnienia). Jest to zaskakujące, ponieważ zwykle (to znaczy, gdy używasz pozycjonowania statycznego lub względnego), pole zawierające jest polem zawartości nadrzędnej .

Oto odpowiednia część specyfikacji CSS :

W przypadku, gdy element nadrzędny jest elementem śródliniowym, zawierający blok jest obwiednią wokół pól dopełniających pierwszego i ostatniego pola wbudowanego wygenerowanego dla tego elementu ... W przeciwnym razie blok zawierający jest utworzony przez krawędź dopełniającą elementu przodek.

Najprostszym podejściem - zgodnie z sugestią Wintera - jest użycie padding: inheritna pozycjach absolutnie pozycjonowanych div. Działa to jednak tylko wtedy, gdy nie chcesz, aby pozycja absolutna divmiała własne dodatkowe wypełnienie. Myślę, że najbardziej uniwersalne rozwiązania (w tym, że oba elementy mogą mieć własne niezależne wypełnienie) to:

  1. Dodaj dodatkowe względnie ustawione div(bez wyściółki) wokół absolutnie pozycjonowanego div. Ten nowy divbędzie uwzględniał wypełnienie swojego rodzica, a absolutnie pozycjonowany divwypełni go.

    Wadą jest oczywiście to, że modyfikujesz kod HTML tylko w celach prezentacyjnych.

  2. Powtórz wypełnienie (lub dodaj do niego) na absolutnie pozycjonowanym elemencie.

    Wadą jest to, że musisz powtarzać wartości w swoim CSS, co jest kruche, jeśli piszesz CSS bezpośrednio. Jeśli jednak używasz narzędzia do wstępnego przetwarzania, takiego jak SASSlub LESSmożesz uniknąć tego problemu, używając zmiennej. To jest metoda, której osobiście używam.

Kevin Christopher Henry
źródło
Dlaczego jest to ustawienie domyślne position: absolute? Zaskakujące jest to, że pole zawierające jest pudełkiem wyściółkowym, ale musiał być ku temu powód, tak jak jestem pewien, że istnieje powód, dla którego (bez box-sizing) width& heightnie zawierają wypełnienia ani obramowania.
trysis
1
Tylko dodatek: nic z tego nie ma wpływu na box-sizingmajątek rodzica lub dziecka. Dzieje się tak, ponieważ wpływa to na rozmiar , jak na szerokość / wysokość, ale nie na pole zawierające, chociaż przyznaję, że miałoby to większy sens, gdyby miało to wpływ na oba.
trysis
2
To dobra informacja, ale jest to ZŁA odpowiedź. Prawidłowa odpowiedź to Winter poniżej ... użyj dopełnienia: inherit, a Twój element Absolute otrzyma wypełnienie, którego potrzebuje. Nie wiem, dlaczego to ma więcej głosów pozytywnych niż prawidłowa odpowiedź ...: P
NotaGuruAtAll
1
@NotaGuruAtAll: padding: inheritdziała dobrze, jeśli pozycja absolutnie pozycjonowana divnie wymaga własnego dopełnienia i dodałem wzmiankę o tej technice. Jest jednak mniej elastyczny, ponieważ nie możesz dodać żadnego dodatkowego wypełnienia do pozycji absolutnej div(tj. Nie możesz tego powiedzieć padding: inherit + 5px). Dlatego wolę techniki, o których tu wspominam.
Kevin Christopher Henry
1
Dziedziczenie position:absolutedopełnienia w elemencie potomnym rzeczywiście działa, jeśli po prostu szukasz dziecka, aby szanowało wypełnienie rodzica. Jeśli jednak chcesz dodać dodatkowe wypełnienie dziecku, musisz zachować proporcję wypełnienia w swoim kodzie. Nie ma prostego sposobu na zrobienie tego za pomocą samego CSS.
Dylan Pierce
51

Jedną z rzeczy, które możesz spróbować, jest użycie następującego CSS:

.child-element {
    padding-left: inherit;
    padding-right: inherit;
    position: absolute;
    left: 0;
    right: 0;
}

Pozwala elementowi podrzędnemu dziedziczyć wypełnienie po rodzicu, a następnie ustawić dziecko tak, aby pasowało do szerokości i wypełnienia rodziców.

Używam box-sizing: border-box;również elementów zaangażowanych.

Nie testowałem tego we wszystkich przeglądarkach, ale wygląda na to, że działa w Chrome, Firefox i IE10.

Zimowy
źródło
Połączyłem tę odpowiedź z odpowiedzią @NewSpender. W moim konkretnym przypadku absolutnie pozycjonowany element div nadal ignorował dopełnienie, ale był ograniczony przez swój element nadrzędny. Tak więc podanie absolutnie pozycjonowanego elementu div z białymi grubymi krawędziami naśladowało wypełnienie, którego potrzebowałem. Warunkiem wstępnym jest jednak to, że tło musi mieć ten sam kolor.
Ogier Schelvis
Ale OP nie chce, aby dziecko odziedziczyło wyściółkę rodzica. Chce, aby dziecko było wyrównane zgodnie z wyściółką rodzica.
Michael Gummelt
30

Cóż, może to nie być najbardziej eleganckie rozwiązanie (semantycznie), ale w niektórych przypadkach będzie działać bez żadnych wad: zamiast wypełnienia użyj przezroczystej ramki na elemencie nadrzędnym. Elementy podrzędne pozycjonowane bezwzględnie będą honorować obramowanie i będą renderowane dokładnie tak samo (z wyjątkiem tego, że do stylizacji używasz obramowania elementu nadrzędnego).

NewSpender
źródło
6

Oto moja najlepsza szansa. Dodałem kolejny element Div, uczyniłem go czerwonym i zmieniłem wysokość rodzica na 200 pikseli, aby go przetestować. Chodzi o to, że dziecko staje się teraz wnukiem, a rodzic staje się dziadkiem. Więc rodzic szanuje swojego rodzica. Mam nadzieję, że zrozumiesz mój pomysł.

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 200px;">
     <div style="background-color: red;  position: relative; height: 100%;">    
        <div style="background-color: gray; position: absolute; left: 0px; right: 0px;bottom: 0px;">css sux</div>
     </div>
    </div>
  </body>
</html>

Edytować:

Myślę, że tego, co próbujesz zrobić, nie da się zrobić. Absolutna pozycja oznacza, że ​​zamierzasz nadać mu współrzędne, które musi uszanować. A co, jeśli rodzic ma wypełnienie 5 pikseli. I absolutnie umieszczasz dziecko na górze: -5px; po lewej: -5px . Jak można szanować rodzica i Ciebie w tym samym czasie?

Moje rozwiązanie

Jeśli chcesz, aby to szanowało rodzica, nie pozycjonuj go wtedy absolutnie.

Dotknąć
źródło
Dziękuję, doceniam ten post, ale nadal jest to obejście prawdziwego problemu. Naprawdę chcę wiedzieć, czy możesz sprawić, by dzieci przestrzegały dopełnienia elementu nadrzędnego. Jeśli okaże się, że nie, dam ci przedstawiciela.
d512
Jeśli absolutnie je umieścisz, nie będą szanować swojego elementu nadrzędnego. Będą cię szanować. Z tego samego powodu, jeśli nie ustawisz ich absolutnie w pozycji, nie możesz tak naprawdę używać rzeczy takich jak bottom: 10px, ponieważ szanują one swój element nadrzędny. Ale to, co chcesz zrobić, zgaduję, że zrobi miejsce na sprzeczność, a zatem będzie się różnić w przeglądarkach. Myślę, że wystarczy obejść.
Dotknij
3
Pozycjonowanie bezwzględne honoruje rodzica, to jest używany przez niego układ współrzędnych. Kiedy powiesz górne 0 pikseli, oznacza to, że 0 pikseli od góry elementu nadrzędnego. Pytanie brzmi, czy należy brać pod uwagę wyściółkę rodziców. Jeśli rodzic miał wypełnienie 5px i dałeś dziecku górną wartość: -5px, to ustawiłoby to równo z rodzicem, jeśli wypełnienie rodzica było honorowane, lub 5 pikseli powyżej rodzica, jeśli nie było.
d512
3

1.) nie możesz użyć dużej ramki na rodzicu - w przypadku, gdy chcesz mieć określone obramowanie

2.) nie możesz dodać marginesu - w przypadku, gdy Twój rodzic jest częścią innego pojemnika i chcesz, aby rodzic odebrał całą szerokość tego dziadka.

Jedynym rozwiązaniem, które powinno mieć zastosowanie, jest owinięcie dzieci w inny pojemnik, tak aby rodzic stał się dziadkiem, a następnie zastosowanie wyściółki do opakowania / rodzica nowego dziecka. Lub możesz bezpośrednio zastosować wyściółkę do dzieci.

W Twoim przypadku:

.css-sux{
  padding: 0px 10px 10px 10px;
}
bhavya_w
źródło
1

Można to było łatwo zrobić przy użyciu dodatkowego poziomu Div.

<div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
  <div style="position: absolute; left: 0px; right: 0px; bottom: 10px; padding:0px 10px;">
    <div style="background-color: gray;">css sux</div>
  </div>
</div>

Demo: https://jsfiddle.net/soxv3vr0/

asankasri
źródło
0

dodaj dopełnienie: dziedzicz w swojej pozycji bezwzględnej

.box{
  background: red;
  position: relative;
  padding: 30px;
  width:500px;
  height:200px;
 box-sizing: border-box;
 

}
<div  class="box">

  <div style="position: absolute;left:0;top:0;padding: inherit">top left</div>
  <div style="position: absolute;right:0;top:0;padding: inherit">top right</div>
  <div style="text-align: center;padding: inherit">center</div>
  <div style="position: absolute;left:0;bottom:0;padding: inherit">bottom left</div>
  <div style="position: absolute;right:0;bottom:0;padding: inherit">bottom right</div>


</div>

ßãlãjî
źródło