2012-11-14 9 views
6

To nie jest błąd, ponieważ zachowanie jest spójne w FF, Chrome, IE9 i Safari na Win7.Przesunięcie jQuery() z powodu pozycji ciała: względne połączone z marginesem elementu

Aplikacja, nad którą pracuję, jest stroną trzecią strony głównej, więc CSS jest niezmienny. Skrypt próbuje wyrównać nowy element div z istniejącym elementem.

  • Ciało jest position: relative
  • Istnieje H1 na górze strony
  • Marża od H1 wydaje się zmieniać, gdzie 0,0 ciało jest obliczany od - choć tle na ciele rozciąga się aż do krawędzi i jest to offsetowe raporty właściwości 0
  • Ustawienie granicy na ciele rozwiązuje problem - wydaje się dziwne zachowanie, ale jest spójne w różnych przeglądarkach? (Nie jest to rozwiązaniem)
  • Usuwanie marginesy H1 rozwiązuje problem (nie jest dobrym rozwiązaniem)

przykład tutaj, JS jest komentuje do replikacji w każdym przypadku:
http://codepen.io/anon/pen/EGvlb

i don” t myślisz, że jest to błąd z jQuery - wydaje się, że zależy to od prawnego związku między marginesem H1 a elementem body?

$(function(){ 

    /* Setting body to position:relative breaks offset() 
    because H1 margin moves body down */ 
    $(document.body).css({position: "relative"}); 

    /* Strange: putting a border on body fixes things? */ 
    //$(document.body).css({border: "1px solid #000"}); 

    /* Removing H1 margin removes problem */ 
    //$("h1").css({margin: 0}); 

    $("#overlay").css({ 
     left: $("#existing").offset().left, 
     top: $("#existing").offset().top 
    }) 
}); 
+0

Występują z tym powodu, ponieważ przypadkowo zbyt długo nie mogłem tego wymyślić. Dzięki. Naprawdę powinienem trafić w worek teraz :) – BoltClock

Odpowiedz

4

Nie sądzę, że jest to błąd w jQuery - wydaje się, że zależy to od prawnego związku między marginesem H1 a elementem body?

Tak: marginesy ciała i H1 są collapsing, więc nie tylko get h1 przesunięte w dół przez domyślny margines, ale tak nie ciało. To dlatego byli w stanie dokonać tych uwag:

  • wyznaczając granicę na ciele rozwiązuje problemu - wydaje dziwne zachowanie, ale jest zgodny w różnych przeglądarkach? (Nie jest to opłacalne rozwiązanie)
  • Usunięcie marginesów H1 rozwiązuje problem (nie opłacalne rozwiązanie)

Zresztą ustawiając ciało position: relative, mówisz #overlay absolutnie pozycjonować się z ciała użytkownika górne przesunięcie jako początek. Twój skrypt przesuwa go w stosunku do offsetu #existing. Wartość jego offsetTop jest względna względem rzutni, która jest obliczana na podstawie położenia tego pola ..., które samo jest w stosunku do h1, ponieważ bezpośrednio następuje po h1 w normalnym przepływie.

Ponieważ marginesy elementów h1 i body są zwijane, mają te same marginesy renderowania.Co dzieje się potem jest dwojaki:

  1. #existing jest popychany w dół przez h1 jak jego rodzeństwo w poniższej normalnego przepływu. Zwiększa to jego przesunięcie względem okienka ekranu (w przypadku testowym CodePen jest to górna część panelu podglądu), co powoduje, że jego offsetTop jest większe.

  2. Gdy ciało jest ustawiony na position: relative, #overlay kończy się coraz umieszczony z jego pochodzenia ustawiony do organizmu, który sam został również przesuwana z powodu zawalenia się z marginesem za H1. Zwiększa to górne przesunięcie swojego pochodzenia, co nie byłoby możliwe, gdybyś nie umieścił ciała, ponieważ wtedy #overlay używa zamiast niego punktu początkowego, który nigdy się nie porusza.

Odległość #existing z góry wziernika jest dodawany do przesunięcia #overlay od jego pochodzenia, to jest jednostka, w wyniku czego w tym zakresie.

Podsumowując: ze względu na margines upadku, przeglądarka kończy się konieczności uwzględnienia zmian w dół zarówno H1 i ciała. H1 wpływa #existing az kolei jego offsetTop, podczas gdy ciało wpływa #overlay gdy umieścisz je stosunkowo. Efekt przesunięcia wydaje się podwójny.

Jako szybkie obejście, można odjąć marginesy h1 z przesunięciami #existing dla celów potrącenia #overlay:

$("#overlay").css({ 
     left: $("#existing").offset().left - $("h1").offset().left, 
     top: $("#existing").offset().top - $("h1").offset().top 
    }) 

Updated example

Zauważ, że używając $(document.body) zamiast $("h1") powyżej nie będzie praca. To dlatego, że margines upadek jest wyłącznie efekt renderingu, a nie faktycznie wpływają przesunięcia organizmu aż nadać mu własną marżę (innymi słowy, marginesy ciała są wciąż obliczeniowych do zera, więc DOM pozostaje żaden mądrzejszy).


nie są bezpośrednio związane z emisją pod ręką, ale i tak warto zajęcie:

  • Marża od H1 wydaje się zmieniać, gdzie 0,0 ciało jest obliczany od - choć tło na ciało rozciąga się aż do krawędzi, a to offsetTop raporty własności 0

pierwszy i ostatni części niniejszego punktu mają pszczoła n omówiony powyżej.

Jeśli chodzi o tło ciała: podczas gdy wydaje się ono rozciągać aż do krawędzi, to rozszerzone tło nie należy w rzeczywistości do ciała - jest ono propagowane z ciała do, a zatem przynależy do elementu głównego (html) i rzutnia. Zobacz this answer o wyjaśnienia.

No i tak:

To nie jest błąd, ponieważ zachowanie jest spójne FF, Chrome, Safari i IE9 na Win7.

mnie uśmiech.Bo raz, ktoś ma rację, mówiąc to.

+0

Świetna odpowiedź dzięki! Wymyśliłem bardziej ogólne rozwiązanie, punkt zerowy o wartości 0,0: http://codepen.io/anon/pen/IdhoK. Nadal nie rozumiem, dlaczego dodanie obramowania do ciała usuwa jego margines? – robC

+0

@robC: ponieważ ze specyfikacji wynika, że ​​marginesy są kwalifikujące się do zwijania tylko wtedy, gdy nie są rozdzielane przez obramowanie, obramowanie lub odstępy. Dodając obramowanie, zapobiegasz zawijaniu się marginesów, więc margines h1 nie zostanie zastosowany do treści. – BoltClock

+0

Wow, że specyfikacja jest ezoteryczną lekturą, nie mogę oprzeć się wrażeniu, że ten typ funkcji jest o wiele mniej przydatny, niż jest mylący. Dziękuję za wyjaśnienie :) – robC

0

Jeśli stanowisko overlay zmianie z absolute do fixed to działa dobrze. oznacza to, że wartość przesunięcia jest poprawna. Myślę, że jest to coś związanego z pozycją elementu overlay w stosunku do poprzedniego elementu.

Powiązane problemy