korzystałem z tych 7 linii kodu, który działa we wszystkich przeglądarkach z rozbieżnościami w ie, 6, 6, 7 (nie pamiętałem, że miałem problem ... może to być typ dokumentu) ... quirksmode.org/js/findpos. HTML i używałem go przez wiele lat. może być sombody może wskazywać ewentualne wady.
Jayapal Chandran
98
@AnthonyWJones, przypuszczam, że potrzebowałeś pedantycznej przyjemności, ale jest oczywiste, jak zawsze, gdy nie jest określone, że OP odnosi się do najbardziej ogólnego przypadku lub odnosi się do współrzędnych okna przeglądarki.
Motes
7
@ Uwaga, nie, to nie jest takie oczywiste. Pomiń wnioskowanie, subiektywność i fałszywe aksjomaty. Może być względny w stosunku do rzutni lub góry strony (aka document.documentElement).
Andre Figueiredo
15
Domyślnie najbardziej ogólny nie jest wnioskowanie, jest to logiczny postęp, więc byłby względny w stosunku do okna, lub „góra strony” może być terminem, jak to określasz. W teorii gier jest ona skodyfikowana jako koncepcja zwana punktem Schellinga. Określ, kiedy nie masz na myśli najbardziej ogólnego przypadku.
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
Internet Explorer obsługuje to od czasu, gdy będziesz się tym przejmować, i został w końcu ujednolicony w widokach CSSOM . Wszystkie inne przeglądarki przyjęły to dawno temu .
Niektóre przeglądarki zwracają również właściwości wysokości i szerokości, choć jest to niestandardowe. Jeśli martwisz się o starszą kompatybilność przeglądarki, sprawdź wersje tej odpowiedzi, aby uzyskać zoptymalizowaną degradującą implementację.
Wartości zwracane przez element.getBoundingClientRect()są względne do rzutni. Jeśli potrzebujesz go względem innego elementu, po prostu odejmij jeden prostokąt od drugiego:
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
alert('Element is '+ offset +' vertical pixels from <body>');
Nie działa ... ma 8 pikseli w pionie i poziomie, ze względu na margines 8 pikseli w ciele. Rozwiązanie Meouw działa idealnie. Jeśli chcesz, mam mały test, aby zademonstrować problem.
CpnCrunch
3
Właściwie myślę, że to zależy od tego, co naprawdę chcesz uzyskać. Pytanie jest trochę dwuznaczne. Twoja odpowiedź jest prawidłowa, jeśli chcesz tylko współrzędne względem rzutni lub względem elementu ciała, ale to nie pomaga w przypadku, gdy chcesz bezwzględnej pozycji elementu (co, jak sądzę, jest tym, czego większość ludzi chce). . Odpowiedź meouw też tego nie daje, chyba że usuniesz bity „-scrollLeft” i „-scrollTop”.
CpnCrunch
4
@CpnCrunch: Rozumiem, co masz na myśli; Nie zdawałem sobie sprawy, że odnosisz się do drugiej części mojej odpowiedzi. Gdy ciało ma margines, jego obwiednia zostanie przesunięta o tę liczbę pikseli z każdej odpowiedniej strony. W takim przypadku należy również odjąć obliczony styl marginesu od współrzędnych bryły. Warto jednak zauważyć, że resety CSS usuwają margines <body>.
Andy E
3
element.getBoundingClientRect().topnie zwraca poprawnego górnego przesunięcia w przypadku position: fixedelementu w iOS (iPhone 8), jeśli zawiera on skoncentrowany element wejściowy, a wirtualna klawiatura przesuwa się w górę. Na przykład, jeśli faktyczne przesunięcie od góry okna wynosi 200 pikseli, zgłosi to jako 420 pikseli, gdzie 220 pikseli to wysokość wirtualnej klawiatury. Jeśli ustawisz element position: absolutei umieścisz go w tej samej pozycji, jak gdyby był ustalony, otrzymasz poprawną wartość 200 pikseli. Nie znam rozwiązania tego.
Jānis Elmeris
327
Biblioteki dokładają starań, aby uzyskać dokładne przesunięcia elementu.
oto prosta funkcja, która wykonuje zadanie w każdych okolicznościach, których próbowałem.
function getOffset( el ){var _x =0;var _y =0;while( el &&!isNaN( el.offsetLeft )&&!isNaN( el.offsetTop )){
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
el = el.offsetParent;}return{ top: _y, left: _x };}var x = getOffset( document.getElementById('yourElId')).left;
zmień: el = el.parentNode na: el = el.offsetParent; i wydaje się, że teraz działa dla zagnieżdżonych ramek iframe ... Myślę, że to właśnie zamierzałeś?
Adam
4
To rozwiązanie jest niekompletne. Spróbuj nałożyć grubą ramkę na div i zagnieździć ją kilka razy. W każdej wersji Firefoksa (2-5) będzie on wyłączony przez szerokość (-y) ramki (nawet w trybie zgodności ze standardami).
ck_
3
czy nie ma na to lepszego sposobu, takiego jak el.totalOffsetLeft i totalOffsetTop? jQuery z pewnością ma tę opcję, ale szkoda, że nie ma na to oficjalnej metody, czy musimy czekać na DOM4? Tworzę aplikację płótna HTML5, więc myślę, że najlepszym rozwiązaniem byłoby wstawienie elementu canvas w ramce iframe, aby uzyskać rzeczywiste współrzędne z clientX i clientY po kliknięciu elementu.
baptx
1
@Adam i meouw, czy mówisz, że pierwszy blok kodu jest nieprawidłowy? Dlaczego więc nie usunąć tego całkowicie? (To pytanie widziały całkiem sporo widzów na przestrzeni lat; może byłoby miło usunąć rzeczy, jeśli się mylą?)
Arjan
2
@baptx: Wiem, że to późna odpowiedź, ale nie widziałem twojego komentarza wcześniej. Zobacz moją odpowiedź poniżej, aby znaleźć alternatywę zgodną ze standardami - tak naprawdę nie potrzebujesz nawet kodu rezerwowego, ponieważ przeglądarki obsługują go od dłuższego czasu.
Andy E
242
To zadziałało dla mnie (zmodyfikowane w stosunku do najlepiej głosowanej odpowiedzi):
function getOffset(el){const rect = el.getBoundingClientRect();return{
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};}
Tylko to rozwiązanie działa dla mnie, gdy element jest umieszczony w divśrodku, którego użycie css jest top:50%, left:50%; transform:translate(-50%, -50%);... doskonałe. Zgadzam się z pytaniem @ScottBiggs. Logiczne jest poszukiwanie prostoty.
nelek
3
może nie jest zwycięzcą, ponieważ jest taki sam jak rozwiązanie Andy'ego E, ale nie działa w starych przeglądarkach <IE9
niltoid
getBoundingClientRect powoduje ogromny skok odmalowania na moich wykresach wydajności
frumbert
1
Należy zdefiniować rectza pomocą var, letlub const. W przeciwnym razie jest to zdefiniowane jako window.rect.
hev1
2
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)zwróci środkową pozycję elementu
abhishake
95
Jeśli chcesz to zrobić tylko w javascript , oto jeden wkładki wykorzystującegetBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
Pierwszy wiersz zwróci wartość offsetTopY względem dokumentu. Drugi wiersz zwróci „ offsetLeftX” względem dokumentu.
getBoundingClientRect() to funkcja javascript, która zwraca pozycję elementu względem okienka okna.
To powinno być rozwiązanie. Nie ma tutaj długiego kodu bs, jest zrozumiały i bardzo dokładny!
E Alexis MT,
2
co jeśli element znajduje się w przewijalnym elemencie? Jedynym sposobem, aby to zrobić, jest zsumowanie offsetTop wszystkich elementów nadrzędnych, jak sugerują inne odpowiedzi
Dmitri Pisarev z
Jak stwierdza Dmitri, jest to niepoprawne i bardzo wadliwe. Nie powinna mieć tyle głosów, ile ma. ZAWSZE znajdzie się w przewijalnym elemencie, ponieważ sam dokument można przewijać. Innymi słowy, chyba że cały dokument mieści się w rzutni, zawsze będzie niepoprawny, jeśli użytkownik w ogóle przewinie okno główne.
Lev
46
Elementy HTML w większości przeglądarek będą miały: -
offsetLeft
offsetTop
Określają one pozycję elementu względem najbliższego elementu nadrzędnego, który ma układ. Do tego rodzica często można uzyskać dostęp, jeśli właściwość offsetParent.
IE i FF3 mają
clientLeft
clientTop
Te właściwości są mniej powszechne, określają pozycję elementów z nadrzędnym obszarem klienta (obszar wypełniony jest częścią obszaru klienta, ale nie ma granicy i marginesu).
Jeśli strona zawiera - przynajmniej - „DIV”, funkcja podana przez meouw wyrzuca wartość „Y” poza obecne limity strony. Aby znaleźć dokładną pozycję, musisz obsługiwać zarówno offsetParent, jak i parentNode.
Wypróbuj kod podany poniżej (jest sprawdzany pod kątem FF2):
modyfikowanie Element.prototypejest ogólnie uważane za zły pomysł . Prowadzi to do naprawdę trudnego do utrzymania kodu. Ponadto ten kod nie uwzględnia przewijania.
Jared Forsyth
23
Aby efektywnie pobrać pozycję względem strony i bez korzystania z funkcji rekurencyjnej: (obejmuje również IE)
var element = document.getElementById('elementId');//replace elementId with your element's Id.var rect = element.getBoundingClientRect();var elementLeft,elementTop;//x and yvar scrollTop = document.documentElement.scrollTop?
document.documentElement.scrollTop:document.body.scrollTop;var scrollLeft = document.documentElement.scrollLeft?
document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
Dołączenie wszystkich ważnych scrollTop / scrollLeft sprawia, że ta odpowiedź jest nieco bardziej poprawna.
scunliffe,
19
Co powiesz na coś takiego, przekazując identyfikator elementu, a zwróci on lewą lub górną część, możemy je również połączyć:
1) znajdź w lewo
function findLeft(element){var rec = document.getElementById(element).getBoundingClientRect();return rec.left + window.scrollX;}//call it like findLeft('#header');
2) znajdź górę
function findTop(element){var rec = document.getElementById(element).getBoundingClientRect();return rec.top + window.scrollY;}//call it like findTop('#header');
lub 3) znajdź razem lewą i górną
function findTopLeft(element){var rec = document.getElementById(element).getBoundingClientRect();return{top: rec.top + window.scrollY, left: rec.left + window.scrollX};}//call it like findTopLeft('#header');
Możesz być lepiej obsługiwany za pomocą frameworka JavaScript, który ma funkcje zwracania takich informacji (i wiele więcej!) W sposób niezależny od przeglądarki. Tu jest kilka:
@Costa Wszystkie używają tego rodzaju funkcji, chociaż jest to pole ewoluujące, ponieważ różne przeglądarki różnie się dostosowują do specyfikacji. Tyle kodu dotyczy „naprawiania” rzeczy, które się nie udają. Naprawdę powinieneś spojrzeć na kod źródłowy.
Shalom Craimer
18
@scraimer: jQuery i YUI NIE są ramami !!! To są biblioteki ! To nie to samo. Powołując się na jquery.com : „jQuery to szybka, mała i bogata w funkcje biblioteka JavaScript ”. Powołując się na yuilibrary.com (możesz również zobaczyć słowo „magiczne” w adresie URL…): „YUI to darmowa biblioteka JavaScript i CSS o otwartym kodzie źródłowym do tworzenia bogato interaktywnych aplikacji internetowych”.
Sk8erPeter
29
Więc powinieneś używać ogromnych bibliotek tylko do tego prostego zadania? Niekoniecznie. Nienawidzę tego, że za każdym razem, gdy chcę coś zrobić z js, otrzymuję te rozwiązania jQuery. jQuery to nie JS!
Opptatt Jobber
1
@OpptattJobber Zgadzam się ... JQuery nie jest javascript. Opiera się na JavaScript, ale jest to zupełnie inny język programowania.
Nick Manning
5
@NickManning Nie jest to nowy język, jest to warstwa abstrakcji dla DOM, która eliminuje konieczność zapisywania obejść zgodności i wydajności bezpośrednio w kodzie. Jeśli nie używasz jQuery, i tak powinieneś użyć jakiegoś rodzaju warstwy abstrakcji.
ginman
15
jQuery .offset () pobierze bieżące współrzędne pierwszego elementu lub ustawi współrzędne każdego elementu w zestawie dopasowanych elementów względem dokumentu.
Z jakiegoś powodu nie daje takich samych wyników w IE w porównaniu do innych przeglądarek. Myślę, że w IE podaje pozycję względem okna, więc jeśli przewiniesz, będziesz uzyskiwał inne wyniki w IE w porównaniu do innych
Abdul Rahim Haddad
1
offset () jest mylony przez zoom, przynajmniej w Android Chrome, więc jest bezużyteczny. stackoverflow.com/a/11396681/1691517 pokazuje sposób tolerancji powiększenia.
Timo Kähkönen
10
Wziąłem odpowiedź @ meouw, dodałem w clientLeft, która pozwala na obramowanie, a następnie utworzyłem trzy wersje:
getAbsoluteOffsetFromBody - podobnie jak @ meouw, uzyskuje bezwzględną pozycję względem treści lub elementu HTML dokumentu (w zależności od trybu dziwactwa)
getAbsoluteOffsetFromGivenElement - zwraca pozycję bezwzględną względem podanego elementu (relativeEl). Zauważ, że dany element musi zawierać element el, inaczej będzie on zachowywać się tak samo jak getAbsoluteOffsetFromBody. Jest to przydatne, jeśli masz dwa elementy zawarte w innym (znanym) elemencie (opcjonalnie kilka węzłów powyżej drzewa węzłów) i chcesz ustawić je w tej samej pozycji.
getAbsoluteOffsetFromRelative - zwraca pozycję bezwzględną względem pierwszego elementu nadrzędnego z pozycją: względna. Jest to podobne do getAbsoluteOffsetFromGivenElement, z tego samego powodu, ale pójdzie tylko tak daleko, jak pierwszy pasujący element.
getAbsoluteOffsetFromBody =function( el ){// finds the offset of el from the body or html elementvar _x =0;var _y =0;while( el &&!isNaN( el.offsetLeft )&&!isNaN( el.offsetTop )){
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;}return{ top: _y, left: _x };}
getAbsoluteOffsetFromGivenElement =function( el, relativeEl ){// finds the offset of el from relativeElvar _x =0;var _y =0;while( el && el != relativeEl &&!isNaN( el.offsetLeft )&&!isNaN( el.offsetTop )){
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;}return{ top: _y, left: _x };}
getAbsoluteOffsetFromRelative =function( el ){// finds the offset of el from the first parent with position: relativevar _x =0;var _y =0;while( el &&!isNaN( el.offsetLeft )&&!isNaN( el.offsetTop )){
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;if(el !=null){if(getComputedStyle !=='undefined')
valString = getComputedStyle(el,null).getPropertyValue('position');else
valString = el.currentStyle['position'];if(valString ==="relative")
el =null;}}return{ top: _y, left: _x };}
Jeśli nadal masz problemy, szczególnie związane z przewijaniem, możesz spróbować spojrzeć na stronę http://www.greywyvern.com/?post=331 - Zauważyłem co najmniej jeden wątpliwy kod w getStyle, który powinien być odpowiedni przy założeniu, że przeglądarki zachowują się , ale w ogóle nie przetestowałem reszty.
Ciekawe ... ale w Edge getAbsoluteOffsetFromBody (element) .top zwraca inną wartość podczas przewijania, w Chrome pozostaje spójny podczas przewijania. Wygląda na to, że Edge dostosowuje się do pozycji przewijania. Kiedy element jest przewijany poza pole widzenia, otrzymuję wartość ujemną.
Norman
getAbsoluteOffsetFromRelative zrobił mój dzień, musiałem odtworzyć podpowiedź bootstrap bez Javascript bootstrap, bardzo mi pomogło.
Nolyurn,
Na wszelki wypadek, jeśli Meouw zmieni nazwę użytkownika, link do odpowiedzi: stackoverflow.com/a/442474/3654837 . (Nie chcę podbijać tego starego wątku, więc tak,
dodam
8
jeśli używasz jQuery, wtyczka wymiarów jest doskonała i pozwala ci dokładnie określić, czego chcesz.
na przykład
Pozycja względna, pozycja bezwzględna, pozycja bezwzględna bez wypełnienia, z wypełnieniem ...
To trwa, powiedzmy, że możesz wiele z tym zrobić.
Plus zaletą korzystania z jQuery jest niewielki rozmiar pliku i łatwa obsługa, bez niego nie wrócisz do JavaScript.
To najlepszy kod, jaki udało mi się stworzyć (działa również w ramkach iframe, w przeciwieństwie do offset () jQuery). Wygląda na to, że webkit ma trochę inne zachowanie.
Na podstawie komentarza meouw:
function getOffset( el ){var _x =0;var _y =0;while( el &&!isNaN( el.offsetLeft )&&!isNaN( el.offsetTop )){
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;// chrome/safariif($.browser.webkit){
el = el.parentNode;}else{// firefox/IE
el = el.offsetParent;}}return{ top: _y, left: _x };}
function getPosition( el ){var x =0;var y =0;while( el &&!isNaN( el.offsetLeft )&&!isNaN( el.offsetTop )){
x += el.offsetLeft - el.scrollLeft;
y += el.offsetTop - el.scrollTop;
el = el.offsetParent;}return{ top: y, left: x };}
To niestety nie działa dla wszystkich elementów, które można znaleźć w nowoczesnym dokumencie HTML. Wbudowane <svg>elementy, na przykład, nie mam offsetLeft, offsetTopi offsetParentwłaściwości.
Jonathan Eunice,
To jest po prostu DIVlub IMGnie SVG. Wyświetl „Zobacz przykładowe współrzędne”? możesz znaleźć obiekt svg to wywołanie pozycji getOffsetRect , spróbuj uzależnić pracę obiektu.
KingRider,
7
Najczystsze podejście, jakie znalazłem, to uproszczona wersja techniki używanej przez jQuery's offset. Podobnie jak niektóre inne odpowiedzi, zaczyna się od getBoundingClientRect; następnie używa windowi documentElementdo regulacji pozycji przewijania, a także rzeczy takich jak margines na body(często domyślny).
Chociaż jest bardzo prawdopodobne, że zostanie to utracone u podstaw tak wielu odpowiedzi, najlepsze rozwiązania tutaj nie działały dla mnie.
O ile mogłem powiedzieć, żadna z pozostałych odpowiedzi nie pomogłaby.
Sytuacja :
na stronie HTML5 miałem menu, które było elementem nawigacyjnym w nagłówku (nie w nagłówku, ale w innym elemencie).
Chciałem, aby nawigacja trzymała się góry, gdy użytkownik przewinął ją, ale wcześniej nagłówek był pozycjonowany absolutnie (więc mogłem pozwolić, aby nakładało się na coś innego).
Powyższe rozwiązania nigdy nie wywołały zmiany, ponieważ .offsetTop nie miał się zmienić, ponieważ był to element pozycjonowany bezwzględnie. Dodatkowo właściwość .scrollTop była po prostu najwyższym elementem na najwyższym poziomie ... to znaczy 0 i zawsze wynosiłaby 0.
Wszelkie testy, które przeprowadziłem przy użyciu tych dwóch (i to samo z wynikami getBoundingClientRect) nie powiedziały mi, że góra paska nawigacyjnego kiedykolwiek przewinęła się do góry widocznej strony (ponownie, jak podano w konsoli, po prostu pozostały te same liczby podczas przewijania wystąpił).
Rozwiązanie
Rozwiązanie było dla mnie przydatne
window.visualViewport.pageTop
Wartość właściwości pageTop odzwierciedla widoczną sekcję ekranu, dzięki czemu mogę śledzić, gdzie element znajduje się w odniesieniu do granic widocznego obszaru.
Prawdopodobnie nie trzeba dodawać, że kiedykolwiek zajmuję się przewijaniem, spodziewam się, że użyję tego rozwiązania, aby programowo reagować na ruch przewijanych elementów.
Mam nadzieję, że pomoże to komuś innemu.
WAŻNA UWAGA: Wygląda na to, że działa obecnie w Chrome i Operze i zdecydowanie nie w Firefoksie (6-2018) ... dopóki Firefox nie obsługuje visualViewport, NIE zalecam używania tej metody (i mam nadzieję, że wkrótce to zrobi ... bardziej sensowny niż reszta).
AKTUALIZACJA:
Tylko uwaga dotycząca tego rozwiązania. Chociaż wciąż uważam, że to, co odkryłem, jest bardzo cenne w sytuacjach, w których „… programowo reaguję na ruch przewijanych elementów”. ma zastosowanie. Lepszym rozwiązaniem problemu, jaki miałem, było użycie CSS do ustawienia pozycji: lepkina elemencie. Używając opcji lepkiej możesz pozostawić element na górze bez użycia javascript (UWAGA: czasami nie będzie to działało tak skutecznie, jak zmiana elementu na naprawioną, ale dla większości zastosowań lepkie podejście będzie prawdopodobnie lepsze)
UPDATE01:
Więc zdałem sobie sprawę, że dla innej strony miałem wymóg, w którym musiałem wykryć pozycję elementu w nieco złożonej konfiguracji przewijania (paralaksa plus elementy przewijające się w ramach wiadomości). W tym scenariuszu zdałem sobie sprawę, że poniższe informacje podały wartość, którą wykorzystałem do ustalenia, kiedy coś zrobić:
jest to bardzo prawdopodobne, że znajdzie się na szczycie tak wielu odpowiedzi, gdy klikniesz „ Aktywny”, aby posortować odpowiedzi
lucchi
@lucchi: D cóż, przypuszczam, że mógłbym usunąć tekst @ na górze ... chociaż zdarzyło mi się to powtórzyć i zdałem sobie sprawę, że znalazłem lepsze rozwiązanie dla mojego problemu ... chociaż moja odpowiedź jest bardziej uwaga do pełniejszych odpowiedzi. Podejrzewam, że moje wymagania nie były tak powszechne, że inne odpowiedzi nie działały dla mnie?
MER
1
W każdym razie doceniam twoją odpowiedź, chciałem ci tylko powiedzieć, że każdy chętny będzie wiedział, że napisałeś coś nowego. Nie jesteś sam ....
Lucchi
5
Zrobiłem to w ten sposób, aby był kompatybilny ze starymi przeglądarkami.
// For really old browser's or incompatible onesfunction getOffsetSum(elem){var top =0,
left =0,
bottom =0,
right =0var width = elem.offsetWidth;var height = elem.offsetHeight;while(elem){
top += elem.offsetTop;
left += elem.offsetLeft;
elem = elem.offsetParent;}
right = left + width;
bottom = top + height;return{
top: top,
left: left,
bottom: bottom,
right: right,}}function getOffsetRect(elem){var box = elem.getBoundingClientRect();var body = document.body;var docElem = document.documentElement;var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;var clientTop = docElem.clientTop;var clientLeft = docElem.clientLeft;var top = box.top + scrollTop - clientTop;var left = box.left + scrollLeft - clientLeft;var bottom = top +(box.bottom - box.top);var right = left +(box.right - box.left);return{
top:Math.round(top),
left:Math.round(left),
bottom:Math.round(bottom),
right:Math.round(right),}}function getOffset(elem){if(elem){if(elem.getBoundingClientRect){return getOffsetRect(elem);}else{// old browserreturn getOffsetSum(elem);}}elsereturnnull;}
Z powodzeniem zastosowałem rozwiązanie Andy E do pozycjonowania modalu bootstrap 2 w zależności od tego, który link w wierszu tabeli kliknie użytkownik. Strona jest stroną Tapestry 5, a javascript poniżej jest importowany do klasy strony java.
Ten kod js pomógł mi, mam starą aplikację webforms używającą wielu symboli zastępczych do wstrzykiwania stron .aspx i nie mogłem wymyślić, jak appendChild () okna wyskakującego, które tworzyłem, aby dostać się do okienka ekranu, ponieważ całe drzewo DOM jest walone z wieloma symbolami zastępczymi i niepoprawnym znacznikiem. Potrzebne było użycie body.getBoundingClientRect (), a następnie użycie jego górnej pozycji w pozycjonowaniu. Dzięki.
Brad Martin,
1
Po wielu badaniach i testach wydaje się, że to działa
function getPosition(e){var isNotFirefox =(navigator.userAgent.toLowerCase().indexOf('firefox')==-1);var x =0, y =0;while(e){
x += e.offsetLeft - e.scrollLeft +(isNotFirefox ? e.clientLeft :0);
y += e.offsetTop - e.scrollTop +(isNotFirefox ? e.clientTop :0);
e = e.offsetParent;}return{ x: x + window.scrollX, y: y + window.scrollY };}
Ponieważ różne przeglądarki wyświetlają ramki, wypełnienia, marginesy itp. W różny sposób. Napisałem małą funkcję, aby pobrać górne i lewe pozycje określonego elementu w każdym elemencie głównym, który chcesz w dokładnym wymiarze:
var elm = $('#div_id');//get the divvar posY_top = elm.offset().top;//get the position from topvar posX_left = elm.offset().left;//get the position from left
Odpowiedzi:
Prawidłowe podejście polega na użyciu
element.getBoundingClientRect()
:Internet Explorer obsługuje to od czasu, gdy będziesz się tym przejmować, i został w końcu ujednolicony w widokach CSSOM . Wszystkie inne przeglądarki przyjęły to dawno temu .
Niektóre przeglądarki zwracają również właściwości wysokości i szerokości, choć jest to niestandardowe. Jeśli martwisz się o starszą kompatybilność przeglądarki, sprawdź wersje tej odpowiedzi, aby uzyskać zoptymalizowaną degradującą implementację.
Wartości zwracane przez
element.getBoundingClientRect()
są względne do rzutni. Jeśli potrzebujesz go względem innego elementu, po prostu odejmij jeden prostokąt od drugiego:źródło
<body>
.element.getBoundingClientRect().top
nie zwraca poprawnego górnego przesunięcia w przypadkuposition: fixed
elementu w iOS (iPhone 8), jeśli zawiera on skoncentrowany element wejściowy, a wirtualna klawiatura przesuwa się w górę. Na przykład, jeśli faktyczne przesunięcie od góry okna wynosi 200 pikseli, zgłosi to jako 420 pikseli, gdzie 220 pikseli to wysokość wirtualnej klawiatury. Jeśli ustawisz elementposition: absolute
i umieścisz go w tej samej pozycji, jak gdyby był ustalony, otrzymasz poprawną wartość 200 pikseli. Nie znam rozwiązania tego.Biblioteki dokładają starań, aby uzyskać dokładne przesunięcia elementu.
oto prosta funkcja, która wykonuje zadanie w każdych okolicznościach, których próbowałem.
źródło
To zadziałało dla mnie (zmodyfikowane w stosunku do najlepiej głosowanej odpowiedzi):
Za pomocą tego możemy zadzwonić
lub
źródło
div
środku, którego użycie css jesttop:50%, left:50%; transform:translate(-50%, -50%);
... doskonałe. Zgadzam się z pytaniem @ScottBiggs. Logiczne jest poszukiwanie prostoty.rect
za pomocąvar
,let
lubconst
. W przeciwnym razie jest to zdefiniowane jakowindow.rect
.left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)
zwróci środkową pozycję elementuJeśli chcesz to zrobić tylko w javascript , oto jeden wkładki wykorzystujące
getBoundingClientRect()
Pierwszy wiersz zwróci wartość
offsetTop
Y względem dokumentu. Drugi wiersz zwróci „offsetLeft
X” względem dokumentu.getBoundingClientRect()
to funkcja javascript, która zwraca pozycję elementu względem okienka okna.źródło
Elementy HTML w większości przeglądarek będą miały: -
Określają one pozycję elementu względem najbliższego elementu nadrzędnego, który ma układ. Do tego rodzica często można uzyskać dostęp, jeśli właściwość offsetParent.
IE i FF3 mają
Te właściwości są mniej powszechne, określają pozycję elementów z nadrzędnym obszarem klienta (obszar wypełniony jest częścią obszaru klienta, ale nie ma granicy i marginesu).
źródło
Jeśli strona zawiera - przynajmniej - „DIV”, funkcja podana przez meouw wyrzuca wartość „Y” poza obecne limity strony. Aby znaleźć dokładną pozycję, musisz obsługiwać zarówno offsetParent, jak i parentNode.
Wypróbuj kod podany poniżej (jest sprawdzany pod kątem FF2):
źródło
Możesz dodać dwie właściwości, aby
Element.prototype
uzyskać górę / lewo dowolnego elementu.To się nazywa tak:
Oto demo porównujące wyniki z jQuery
offset().top
i.left
: http://jsfiddle.net/ThinkingStiff/3G7EZ/źródło
Element.prototype
jest ogólnie uważane za zły pomysł . Prowadzi to do naprawdę trudnego do utrzymania kodu. Ponadto ten kod nie uwzględnia przewijania.Aby efektywnie pobrać pozycję względem strony i bez korzystania z funkcji rekurencyjnej: (obejmuje również IE)
źródło
Co powiesz na coś takiego, przekazując identyfikator elementu, a zwróci on lewą lub górną część, możemy je również połączyć:
1) znajdź w lewo
2) znajdź górę
lub 3) znajdź razem lewą i górną
źródło
Możesz być lepiej obsługiwany za pomocą frameworka JavaScript, który ma funkcje zwracania takich informacji (i wiele więcej!) W sposób niezależny od przeglądarki. Tu jest kilka:
Za pomocą tych ram możesz zrobić coś takiego:
$('id-of-img').top
uzyskać współrzędną y-piksela obrazu.źródło
jQuery .offset () pobierze bieżące współrzędne pierwszego elementu lub ustawi współrzędne każdego elementu w zestawie dopasowanych elementów względem dokumentu.
źródło
Wziąłem odpowiedź @ meouw, dodałem w clientLeft, która pozwala na obramowanie, a następnie utworzyłem trzy wersje:
getAbsoluteOffsetFromBody - podobnie jak @ meouw, uzyskuje bezwzględną pozycję względem treści lub elementu HTML dokumentu (w zależności od trybu dziwactwa)
getAbsoluteOffsetFromGivenElement - zwraca pozycję bezwzględną względem podanego elementu (relativeEl). Zauważ, że dany element musi zawierać element el, inaczej będzie on zachowywać się tak samo jak getAbsoluteOffsetFromBody. Jest to przydatne, jeśli masz dwa elementy zawarte w innym (znanym) elemencie (opcjonalnie kilka węzłów powyżej drzewa węzłów) i chcesz ustawić je w tej samej pozycji.
getAbsoluteOffsetFromRelative - zwraca pozycję bezwzględną względem pierwszego elementu nadrzędnego z pozycją: względna. Jest to podobne do getAbsoluteOffsetFromGivenElement, z tego samego powodu, ale pójdzie tylko tak daleko, jak pierwszy pasujący element.
Jeśli nadal masz problemy, szczególnie związane z przewijaniem, możesz spróbować spojrzeć na stronę http://www.greywyvern.com/?post=331 - Zauważyłem co najmniej jeden wątpliwy kod w getStyle, który powinien być odpowiedni przy założeniu, że przeglądarki zachowują się , ale w ogóle nie przetestowałem reszty.
źródło
jeśli używasz jQuery, wtyczka wymiarów jest doskonała i pozwala ci dokładnie określić, czego chcesz.
na przykład
Pozycja względna, pozycja bezwzględna, pozycja bezwzględna bez wypełnienia, z wypełnieniem ...
To trwa, powiedzmy, że możesz wiele z tym zrobić.
Plus zaletą korzystania z jQuery jest niewielki rozmiar pliku i łatwa obsługa, bez niego nie wrócisz do JavaScript.
źródło
To najlepszy kod, jaki udało mi się stworzyć (działa również w ramkach iframe, w przeciwieństwie do offset () jQuery). Wygląda na to, że webkit ma trochę inne zachowanie.
Na podstawie komentarza meouw:
źródło
jQuery
użyć$.browser.webkit
; Musisz się pobawić,navigator.userAgent
aby zrobić to samo z czystymJavaScript
.Jeśli używasz jQuery, może to być proste rozwiązanie:
źródło
Różnica między małym a małym
Zobacz przykładowe współrzędne: http://javascript.info/tutorial/coordinates
źródło
<svg>
elementy, na przykład, nie mamoffsetLeft
,offsetTop
ioffsetParent
właściwości.DIV
lubIMG
nieSVG
. Wyświetl „Zobacz przykładowe współrzędne”? możesz znaleźć obiekt svg to wywołanie pozycji getOffsetRect , spróbuj uzależnić pracę obiektu.Najczystsze podejście, jakie znalazłem, to uproszczona wersja techniki używanej przez jQuery's
offset
. Podobnie jak niektóre inne odpowiedzi, zaczyna się odgetBoundingClientRect
; następnie używawindow
idocumentElement
do regulacji pozycji przewijania, a także rzeczy takich jak margines nabody
(często domyślny).Pokaż fragment kodu
źródło
Chociaż jest bardzo prawdopodobne, że zostanie to utracone u podstaw tak wielu odpowiedzi, najlepsze rozwiązania tutaj nie działały dla mnie.
O ile mogłem powiedzieć, żadna z pozostałych odpowiedzi nie pomogłaby.
Sytuacja :
na stronie HTML5 miałem menu, które było elementem nawigacyjnym w nagłówku (nie w nagłówku, ale w innym elemencie).
Chciałem, aby nawigacja trzymała się góry, gdy użytkownik przewinął ją, ale wcześniej nagłówek był pozycjonowany absolutnie (więc mogłem pozwolić, aby nakładało się na coś innego).
Powyższe rozwiązania nigdy nie wywołały zmiany, ponieważ .offsetTop nie miał się zmienić, ponieważ był to element pozycjonowany bezwzględnie. Dodatkowo właściwość .scrollTop była po prostu najwyższym elementem na najwyższym poziomie ... to znaczy 0 i zawsze wynosiłaby 0.
Wszelkie testy, które przeprowadziłem przy użyciu tych dwóch (i to samo z wynikami getBoundingClientRect) nie powiedziały mi, że góra paska nawigacyjnego kiedykolwiek przewinęła się do góry widocznej strony (ponownie, jak podano w konsoli, po prostu pozostały te same liczby podczas przewijania wystąpił).
Rozwiązanie
Rozwiązanie było dla mnie przydatne
Wartość właściwości pageTop odzwierciedla widoczną sekcję ekranu, dzięki czemu mogę śledzić, gdzie element znajduje się w odniesieniu do granic widocznego obszaru.
Prawdopodobnie nie trzeba dodawać, że kiedykolwiek zajmuję się przewijaniem, spodziewam się, że użyję tego rozwiązania, aby programowo reagować na ruch przewijanych elementów.
Mam nadzieję, że pomoże to komuś innemu.
WAŻNA UWAGA: Wygląda na to, że działa obecnie w Chrome i Operze i zdecydowanie nie w Firefoksie (6-2018) ... dopóki Firefox nie obsługuje visualViewport, NIE zalecam używania tej metody (i mam nadzieję, że wkrótce to zrobi ... bardziej sensowny niż reszta).
AKTUALIZACJA:
Tylko uwaga dotycząca tego rozwiązania.
Chociaż wciąż uważam, że to, co odkryłem, jest bardzo cenne w sytuacjach, w których „… programowo reaguję na ruch przewijanych elementów”. ma zastosowanie. Lepszym rozwiązaniem problemu, jaki miałem, było użycie CSS do ustawienia pozycji: lepkina elemencie. Używając opcji lepkiej możesz pozostawić element na górze bez użycia javascript (UWAGA: czasami nie będzie to działało tak skutecznie, jak zmiana elementu na naprawioną, ale dla większości zastosowań lepkie podejście będzie prawdopodobnie lepsze)
UPDATE01:
Więc zdałem sobie sprawę, że dla innej strony miałem wymóg, w którym musiałem wykryć pozycję elementu w nieco złożonej konfiguracji przewijania (paralaksa plus elementy przewijające się w ramach wiadomości). W tym scenariuszu zdałem sobie sprawę, że poniższe informacje podały wartość, którą wykorzystałem do ustalenia, kiedy coś zrobić:
Mam nadzieję, że ta odpowiedź jest teraz bardziej przydatna.
źródło
Zrobiłem to w ten sposób, aby był kompatybilny ze starymi przeglądarkami.
Więcej informacji o współrzędnych w JavaScript tutaj: http://javascript.info/tutorial/coordinates
źródło
Aby uzyskać całkowite przesunięcie elementu, można rekurencyjnie sumować wszystkie przesunięcia nadrzędne:
dzięki tej funkcji narzędzia całkowite górne przesunięcie elementu dom wynosi:
źródło
Dziękuję ThinkingStiff za odpowiedź , to tylko inna wersja.
źródło
Z powodzeniem zastosowałem rozwiązanie Andy E do pozycjonowania modalu bootstrap 2 w zależności od tego, który link w wierszu tabeli kliknie użytkownik. Strona jest stroną Tapestry 5, a javascript poniżej jest importowany do klasy strony java.
javascript:
}
Mój kod modalny:
Link w pętli:
I kod Java w klasie strony:
Mam nadzieję, że to komuś pomoże, ten post pomógł.
źródło
Po wielu badaniach i testach wydaje się, że to działa
patrz http://jsbin.com/xuvovalifo/edit?html,js,output
źródło
Pomyślałem, że też to wyrzucę.
Nie byłem w stanie przetestować go w starszych przeglądarkach, ale działa on w najnowszej wersji 3. :)
źródło
Ponieważ różne przeglądarki wyświetlają ramki, wypełnienia, marginesy itp. W różny sposób. Napisałem małą funkcję, aby pobrać górne i lewe pozycje określonego elementu w każdym elemencie głównym, który chcesz w dokładnym wymiarze:
Aby odzyskać lewą pozycję, musisz wrócić:
źródło
źródło
el.offsetTop
iel.offsetLeft
(OP nie mówi nic o jQuery ... Nie jestem pewien, dlaczego twoja odpowiedź używa jQuery też ...)