Saya telah menggunakan 7 baris kode ini yang berfungsi di semua browser dengan perbedaan dalam ie5,6,7 (saya tidak ingat memiliki masalah ... mungkin jenis dokumen) ... quirksmode.org/js/findpos. html dan saya sudah sering menggunakannya selama bertahun-tahun. mungkin sombody dapat menunjukkan kekurangannya jika ada.
Jayapal Chandran
99
@AnthonyWJones, saya kira Anda membutuhkan kesenangan pedantic, tetapi jelas, karena selalu ketika tidak ditentukan, bahwa OP mengacu pada kasus yang paling umum, atau mengacu pada koordinat jendela browser.
Motes
7
@Mote, Tidak, tidak terlalu jelas. Tinggalkan inferensi, subjektivitas dan aksioma palsu. Ini bisa relatif ke viewport atau bagian atas halaman (alias document.documentElement).
Andre Figueiredo
16
Default ke yang paling umum bukan inferensi, itu adalah perkembangan logis, sehingga itu akan relatif ke jendela, atau "bagian atas halaman" mungkin istilah seperti yang Anda katakan. Dalam Game Theory, ini dikodifikasikan sebagai konsep yang disebut titik Schelling. Pastikan untuk menentukan kapan Anda tidak bermaksud kasus yang paling umum.
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
Internet Explorer telah mendukung ini sejak Anda cenderung peduli dan akhirnya standar di Tampilan CSSOM . Semua browser lain sudah lama menggunakannya .
Beberapa browser juga mengembalikan properti tinggi dan lebar, meskipun ini tidak standar. Jika Anda khawatir tentang kompatibilitas browser yang lebih lama, periksa revisi jawaban ini untuk penerapan penurunan yang dioptimalkan.
Nilai yang dikembalikan element.getBoundingClientRect()relatif terhadap viewport. Jika Anda membutuhkannya relatif terhadap elemen lain, cukup kurangi satu persegi panjang dari yang lain:
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
alert('Element is '+ offset +' vertical pixels from <body>');
Tidak berfungsi ... itu 8 piksel keluar secara vertikal dan horizontal, karena margin 8px dalam tubuh. Solusi Meouw bekerja dengan sempurna. Jika Anda mau, saya memiliki tes kecil untuk menunjukkan masalahnya.
CpnCrunch
3
Sebenarnya, saya pikir itu tergantung pada apa yang sebenarnya ingin Anda dapatkan dari koordinasi. Pertanyaannya sedikit ambigu. Jawaban Anda benar jika Anda hanya menginginkan koordinat relatif terhadap viewport atau relatif terhadap elemen tubuh, tetapi itu tidak membantu Anda jika Anda menginginkan posisi absolut elemen (yang saya bayangkan adalah apa yang diinginkan kebanyakan orang) . jawaban meouw juga tidak memberi Anda hal itu, kecuali jika Anda menghapus bit '-scrollLeft' dan '-scrollTop'.
CpnCrunch
4
@CpnCrunch: Saya mengerti maksud Anda sekarang; Saya tidak menyadari bahwa Anda mengacu pada bagian terakhir dari jawaban saya. Ketika tubuh memiliki margin, kotak pembatasnya akan diimbangi dengan jumlah piksel tersebut di masing-masing sisi. Dalam hal ini, Anda juga harus mengurangi gaya margin yang dihitung dari koordinat tubuh. Perlu dicatat bahwa reset CSS menghapus margin dari <body>, meskipun.
Andy E
3
element.getBoundingClientRect().toptidak mengembalikan offset atas yang benar jika ada position: fixedelemen di iOS (iPhone 8) jika mengandung elemen input terfokus dan keyboard virtual telah meluncur. Misalnya, jika offset aktual dari bagian atas jendela adalah 200px, itu akan melaporkannya sebagai 420px, di mana 220px adalah ketinggian keyboard virtual. Jika Anda mengatur elemen position: absolutedan memposisikannya pada posisi yang sama seperti jika diperbaiki, maka Anda akan mendapatkan 200px yang benar. Saya tidak tahu solusi untuk ini.
Jānis Elmeris
327
Perpustakaan berusaha keras untuk mendapatkan offset yang akurat untuk suatu elemen.
inilah fungsi sederhana yang melakukan pekerjaan dalam setiap keadaan yang telah saya coba.
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;
ubah: el = el.parentNode ke: el = el.offsetParent; dan tampaknya berfungsi untuk iframe bersarang sekarang ... Saya pikir itu yang Anda maksud?
Adam
4
Solusi ini tidak lengkap. Coba letakkan batas tebal pada div dan bersarang beberapa kali. Dalam versi apa pun dari Firefox (2-5) akan dimatikan oleh lebar perbatasan (bahkan dalam mode kepatuhan standar).
ck_
3
tidakkah ada cara yang lebih bersih untuk melakukan itu, seperti fungsi el.totalOffsetLeft dan totalOffsetTop? jQuery tentu saja memiliki opsi ini tetapi sayang sekali tidak ada metode resmi untuk ini, apakah kita perlu menunggu DOM4? Saya sedang membangun aplikasi kanvas HTML5, jadi saya pikir solusi terbaik adalah dengan memasukkan elemen kanvas dalam iframe sehingga saya bisa mendapatkan koordinat nyata dengan clientX dan clientY ketika kita mengklik elemen.
baptx
1
Jadi, @Adam dan meouw, apakah Anda mengatakan blok kode pertama salah? Lalu mengapa tidak menghapus itu sama sekali? (Pertanyaan ini telah dilihat beberapa pemirsa selama bertahun-tahun; mungkin menyenangkan untuk menghapus hal-hal jika mereka salah?)
Arjan
2
@aptx: Saya tahu ini adalah jawaban yang terlambat, tetapi saya tidak melihat komentar Anda lebih awal. Lihat jawaban saya di bawah ini untuk alternatif yang lebih sesuai standar - Anda bahkan tidak benar-benar membutuhkan kode cadangan, karena browser telah mendukungnya sejak lama.
Andy E
242
Ini bekerja untuk saya (dimodifikasi dari jawaban pilihan tertinggi):
function getOffset(el){const rect = el.getBoundingClientRect();return{
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};}
Hanya solusi ini yang bekerja untuk saya ketika elemen ditempatkan di divyang berpusat menggunakan css top:50%, left:50%; transform:translate(-50%, -50%);... sangat baik. Setuju dengan pertanyaan @ScottBiggs. Logis adalah mencari kesederhanaan.
nelek
3
mungkin itu bukan pemenang karena sama dengan solusi Andy E, tetapi tidak berfungsi di browser lama <IE9
niltoid
getBoundingClientRect menyebabkan lonjakan
pengecatan
1
Anda harus mendefinisikan rectmenggunakan var, letatau const. Kalau tidak, itu didefinisikan sebagai window.rect.
hev1
2
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)akan mengembalikan posisi tengah elemen
abhishake
97
Jika Anda ingin melakukannya hanya dalam javascript , berikut adalah beberapa baris yang digunakangetBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
Baris pertama akan mengembalikan offsetTopsay Y relatif ke dokumen. Baris kedua akan mengembalikan offsetLeftkatakan X relatif terhadap dokumen.
getBoundingClientRect() adalah fungsi javascript yang mengembalikan posisi elemen relatif ke viewport jendela.
Ini harus menjadi solusinya. Tidak ada kode panjang bs di sini, dapat dimengerti dan sangat akurat!
E Alexis MT
2
bagaimana jika elemen tersebut berada dalam elemen yang dapat digulir? Satu-satunya cara untuk melakukannya adalah dengan menghitung offset semua elemen induk, seperti yang disarankan oleh jawaban lain
Dmitri Pisarev
Seperti yang dikatakan Dmitri, ini tidak benar dan sangat cacat. Seharusnya tidak memiliki suara sebanyak yang ada. Ini akan SELALU berada dalam elemen yang dapat digulir juga karena dokumen itu sendiri dapat digulir. Dengan kata lain, kecuali seluruh dokumen cocok dengan viewport, itu akan selalu salah jika pengguna telah menggulir jendela utama sama sekali.
Im
46
Elemen HTML pada sebagian besar browser akan memiliki: -
offsetLeft
offsetTop
Ini menentukan posisi elemen relatif orang tua terdekatnya yang memiliki tata letak. Induk ini sering dapat diakses jika properti offsetParent.
IE dan FF3 miliki
clientLeft
clientTop
Properti ini kurang umum, mereka menentukan posisi elemen dengan area klien orang tuanya (area empuk adalah bagian dari area klien tetapi batas dan margin tidak).
Jika halaman menyertakan - setidaknya- "DIV" apa saja, fungsi yang diberikan oleh meouw melempar nilai "Y" melampaui batas halaman saat ini. Untuk menemukan posisi yang tepat, Anda harus menangani offsetParent dan parentNode.
Coba kode yang diberikan di bawah ini (diperiksa untuk FF2):
seperti dengan solusi lain bahkan dengan FF 24.4 kode di atas tidak berfungsi ketika ada batas lebar sebagai bagian dari tata letak posisi.
merampok
Anda seorang penyelamat. Saya sedang mengerjakan beberapa bug GWT yang cukup dalam sekarang dan melemparkan ini dalam metode JSNI menyelesaikan semua masalah saya !!
Will Byrne
35
Anda dapat menambahkan dua properti Element.prototypeuntuk mendapatkan bagian atas / kiri elemen apa pun.
memodifikasi Element.prototypeumumnya dianggap ide yang buruk . Itu menyebabkan sangat sulit untuk mempertahankan kode. Selain itu, kode ini tidak memperhitungkan pengguliran.
Jared Forsyth
23
Untuk mengambil posisi relatif terhadap halaman secara efisien, dan tanpa menggunakan fungsi rekursif: (termasuk IE juga)
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;
Termasuk semua scrollTop / scrollLeft penting membuat jawaban ini sedikit lebih benar.
scunliffe
19
Bagaimana dengan sesuatu seperti ini, dengan melewati ID elemen dan itu akan mengembalikan kiri atau atas, kita juga dapat menggabungkan mereka:
1) temukan kiri
function findLeft(element){var rec = document.getElementById(element).getBoundingClientRect();return rec.left + window.scrollX;}//call it like findLeft('#header');
2) temukan top
function findTop(element){var rec = document.getElementById(element).getBoundingClientRect();return rec.top + window.scrollY;}//call it like findTop('#header');
atau 3) temukan kiri dan atas bersamaan
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');
Anda mungkin lebih baik dilayani dengan menggunakan kerangka kerja JavaScript, yang memiliki fungsi untuk mengembalikan informasi tersebut (dan banyak lagi!) Dengan cara yang tidak tergantung pada browser. Berikut ini beberapa di antaranya:
@Costa Mereka semua menggunakan fungsi-fungsi semacam itu, meskipun ini adalah bidang yang berkembang, karena peramban yang berbeda sesuai dengan spesifikasi. Begitu banyak kode yang berhubungan dengan "memperbaiki" hal-hal yang salah. Anda benar-benar harus melihat kode sumbernya.
Shalom Craimer
18
@scraimer: jQuery dan YUI BUKAN kerangka kerja !!! Ini adalah perpustakaan ! Ini tidak sama. Mengutip jquery.com : "jQuery adalah perpustakaan JavaScript yang cepat, kecil, dan kaya fitur ." Mengutip yuilibrary.com (Anda juga dapat melihat kata "ajaib" di URL ...): "YUI adalah pustaka JavaScript dan CSS sumber terbuka gratis untuk membuat aplikasi web kaya interaktif."
Sk8erPeter
29
Jadi, Anda harus menggunakan perpustakaan besar hanya untuk tugas sederhana ini? Tidak perlu. Saya benci bahwa setiap kali saya ingin melakukan sesuatu dengan js, saya mendapatkan solusi jQuery ini. jQuery bukan JS!
Opptatt Jobber
1
@OpptattJobber Saya setuju ... JQuery bukan javascript. Itu bergantung pada Javascript tetapi bahasa pemrograman yang berbeda sama sekali.
Nick Manning
5
@NickManning Ini bukan bahasa baru, ini lapisan abstraksi untuk DOM yang menghilangkan keharusan untuk menulis kompatibilitas dan solusi kinerja langsung ke dalam kode Anda. Jika Anda tidak menggunakan jQuery, Anda harus menggunakan beberapa jenis lapisan abstraksi.
ginman
15
jQuery .offset () akan mendapatkan koordinat saat ini dari elemen pertama, atau mengatur koordinat setiap elemen, di set elemen yang cocok, relatif terhadap dokumen.
Untuk beberapa alasan itu tidak memberikan hasil yang sama di IE dibandingkan dengan browser lain. Saya berpikir bahwa di IE memberikan posisi relatif ke jendela, jadi jika Anda menggulir, Anda akan mendapatkan hasil yang berbeda di IE dibandingkan dengan yang lain
Abdul Rahim Haddad
1
offset () dikacaukan oleh zoom, setidaknya di Android Chrome, jadi tidak ada gunanya. stackoverflow.com/a/11396681/1691517 menunjukkan cara yang toleran terhadap zoom.
Timo Kähkönen
10
Saya telah mengambil jawaban @ meouw, ditambahkan di clientLeft yang memungkinkan untuk perbatasan, dan kemudian membuat tiga versi:
getAbsoluteOffsetFromBody - mirip dengan @ meouw, ini mendapatkan posisi absolut relatif terhadap elemen tubuh atau html dokumen (tergantung pada mode quirks)
getAbsoluteOffsetFromGivenElement - mengembalikan posisi absolut relatif terhadap elemen yang diberikan (relatifEl). Perhatikan bahwa elemen yang diberikan harus mengandung elemen el, atau ini akan berperilaku sama dengan getAbsoluteOffsetFromBody. Ini berguna jika Anda memiliki dua elemen yang terkandung di dalam elemen (dikenal) lainnya (opsional beberapa node di atas simpul pohon) dan ingin menjadikannya posisi yang sama.
getAbsoluteOffsetFromRelative - mengembalikan posisi absolut relatif ke elemen induk pertama dengan posisi: relatif. Ini mirip dengan getAbsoluteOffsetFromGivenElement, untuk alasan yang sama tetapi hanya akan sejauh elemen pencocokan pertama.
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 };}
Jika Anda masih mengalami masalah, terutama yang berkaitan dengan pengguliran, Anda dapat mencoba melihat http://www.greywyvern.com/?post=331 - Saya perhatikan setidaknya satu potong kode yang dipertanyakan di getStyle yang seharusnya baik-baik saja dengan asumsi browser berperilaku , tetapi belum menguji sisanya sama sekali.
Menarik ... tetapi di Edge getAbsoluteOffsetFromBody (elemen) .top mengembalikan nilai yang berbeda saat saya menggulir, di Chrome itu tetap konsisten saat saya menggulir. Sepertinya Edge menyesuaikan dengan posisi gulir. Ketika elemen digulir ke luar dari tampilan saya mendapatkan nilai negatif.
Norman
getAbsoluteOffsetFromRelative membuat hari saya, saya harus mereproduksi tooltip bootstrap tanpa Javascript dari bootstrap, itu banyak membantu saya.
Nolyurn
Untuk jaga-jaga jika Meouw mengubah nama pengguna mereka, tautan untuk menjawab: stackoverflow.com/a/442474/3654837 . (Saya tidak ingin menabrak utas lama ini jadi ya, saya memberi komentar)
Mukyuu
8
jika menggunakan jQuery, plugin dimensi sangat bagus dan memungkinkan Anda menentukan dengan tepat apa yang Anda inginkan.
misalnya
Posisi relatif, posisi absolut, posisi absolut tanpa bantalan, dengan bantalan ...
Terus, katakan saja ada banyak yang bisa Anda lakukan dengannya.
Plus bonus menggunakan jQuery adalah ukuran file yang ringan dan mudah digunakan, Anda tidak akan kembali ke JavaScript tanpa itu sesudahnya.
Ini adalah kode terbaik yang berhasil saya buat (berfungsi di iframe juga, tidak seperti offset jQuery ()). Sepertinya webkit memiliki sedikit perilaku yang berbeda.
Berdasarkan komentar 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 };}
Perhatikan bahwa Anda harus jQuerymenggunakan $.browser.webkit; Anda harus bermain-main dengan navigator.userAgentuntuk melakukan hal yang sama dengan murni JavaScript.
SP
2
$ .browser tidak lagi tersedia dalam versi terbaru jQuery
Gus
sayangnya bahkan dengan FF 24.4 kode di atas tidak berfungsi ketika ada batas lebar sebagai bagian dari tata letak positioning.
merampok
8
Jika Anda menggunakan jQuery, ini bisa menjadi solusi sederhana:
<script>var el = $("#element");var position = el.position();
console.log("left: "+ position.left +", top: "+ position.top );</script>
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 };}
Sayangnya ini tidak berfungsi untuk semua elemen yang mungkin ditemukan di dalam dokumen HTML modern. Tertanam <svg>elemen, misalnya, tidak memiliki offsetLeft, offsetTop, dan offsetParentproperti.
Jonathan Eunice
Hanya DIVatau IMGtidak SVG. Lihat "Lihat contoh koordinat"? Anda dapat menemukan objek svg adalah panggilan posisi getOffsetRect , mencoba dan bergantung pada objek.
KingRider
7
Pendekatan terbersih yang saya temukan adalah versi sederhana dari teknik yang digunakan oleh jQuery offset. Mirip dengan beberapa jawaban lain yang dimulai dengan getBoundingClientRect; kemudian menggunakan windowdan documentElementuntuk menyesuaikan posisi gulir serta hal-hal seperti margin pada body(seringkali default).
Meskipun ini sangat mungkin hilang di bagian bawah dari begitu banyak jawaban, solusi teratas di sini tidak bekerja untuk saya.
Sejauh yang saya tahu, tidak ada jawaban lain yang akan membantu.
Situasi :
Di halaman HTML5 saya memiliki menu yang merupakan elemen nav di dalam header (bukan header tetapi header di elemen lain).
Saya ingin navigasi untuk tetap di atas setelah pengguna menggulir ke sana, tapi sebelumnya header ini diposisikan absolut (jadi saya bisa sedikit overlay sesuatu yang lain).
Solusi di atas tidak pernah memicu perubahan karena .offsetTop tidak akan berubah karena ini adalah elemen yang diposisikan mutlak. Selain itu, properti .scrollTop hanyalah bagian atas elemen paling atas ... yaitu 0 dan selalu 0.
Setiap tes yang saya lakukan menggunakan kedua (dan sama dengan hasil getBoundingClientRect) tidak akan memberi tahu saya jika bagian atas bilah navigasi pernah menggulir ke bagian atas halaman yang dapat dilihat (sekali lagi, seperti yang dilaporkan dalam konsol, mereka hanya tinggal nomor yang sama saat menggulir terjadi).
Solusi
Solusi bagi saya adalah memanfaatkan
window.visualViewport.pageTop
Nilai properti pageTop mencerminkan bagian layar yang dapat dilihat, oleh karena itu memungkinkan saya untuk melacak di mana elemen mengacu pada batas-batas area yang dapat dilihat.
Mungkin tidak perlu dikatakan, kapan pun saya berurusan dengan pengguliran, saya berharap untuk menggunakan solusi ini untuk merespons secara sistematis terhadap pergerakan elemen yang sedang digulir.
Semoga ini bisa membantu orang lain.
CATATAN PENTING: Ini tampaknya berfungsi di Chrome dan Opera saat ini & pasti tidak di Firefox (6-2018) ... sampai Firefox mendukung visualViewport Saya sarankan TIDAK menggunakan metode ini, (dan saya harap mereka segera melakukannya ... itu membuat banyak lebih masuk akal daripada yang lain).
UPDATE:
Hanya sebuah catatan mengenai solusi ini. Sementara saya masih menemukan apa yang saya temukan sangat berharga untuk situasi di mana "... terprogram merespons pergerakan elemen yang sedang digulir." berlaku. Solusi yang lebih baik untuk masalah yang saya miliki adalah menggunakan CSS untuk mengatur posisi: stickypada elemen. Menggunakan sticky Anda dapat memiliki elemen tetap di atas tanpa menggunakan javascript (CATATAN: ada kalanya ini tidak akan bekerja seefektif mengubah elemen untuk diperbaiki tetapi untuk sebagian besar menggunakan pendekatan sticky kemungkinan akan lebih unggul)
UPDATE01:
Jadi saya menyadari bahwa untuk halaman yang berbeda saya memiliki persyaratan di mana saya perlu mendeteksi posisi elemen dalam pengaturan pengguliran yang agak rumit (paralaks plus elemen yang menggulir melewati sebagai bagian dari pesan). Saya menyadari dalam skenario itu bahwa berikut ini memberikan nilai yang saya gunakan untuk menentukan kapan harus melakukan sesuatu:
ini sangat mungkin berada di bagian atas dari begitu banyak jawaban ketika Anda mengklik aktif untuk mengurutkan jawaban
lucchi
@ Lucchi: D yah saya kira saya bisa menghapus teks @ atas ... meskipun saya baru saja terjadi pada yang satu ini dan menyadari bahwa saya telah menemukan solusi yang lebih baik untuk masalah saya sendiri ... meskipun jawaban saya lebih dari satu catatan kaki untuk jawaban yang lebih lengkap. Saya menduga persyaratan saya mungkin tidak umum sehingga jawaban yang lain tidak berhasil untuk saya?
MER
1
Saya menghargai jawaban Anda, itu hanya untuk memberi tahu Anda bahwa, siapa pun yang mau akan sadar bahwa Anda menulis sesuatu yang baru. Anda tidak sendirian ....
lucchi
5
Saya melakukannya seperti ini sehingga kompatibel dengan browser lama.
// 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;}
Saya berhasil menggunakan solusi Andy E untuk memposisikan modal bootstrap 2 tergantung pada tautan apa di baris tabel yang diklik pengguna. Halaman ini adalah halaman Tapestry 5 dan javascript di bawah ini diimpor dalam kelas halaman java.
Kode js ini membantu saya, saya memiliki aplikasi webform lama menggunakan banyak placeholder menyuntikkan halaman .aspx dan saya tidak tahu bagaimana cara menambahkanChild () dari kotak popup yang saya buat untuk memasukkannya ke dalam viewport karena seluruh pohon DOM rusak. dengan beberapa placeholder dan markup yang salah. Menggunakan body.getBoundingClientRect () lalu menggunakan topinya dalam penentuan posisi adalah yang saya butuhkan. Terima kasih.
Brad Martin
1
Setelah banyak penelitian dan pengujian, ini tampaknya berhasil
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 };}
Hanya berpikir saya akan membuang ini di sana juga.
Saya belum bisa mengujinya di browser yang lebih lama, tetapi ia bekerja di yang terbaru dari atas 3. :)
Karena browser yang berbeda memberikan batas, padding, margin, dll dengan cara yang berbeda. Saya menulis sedikit fungsi untuk mengambil posisi atas dan kiri elemen tertentu di setiap elemen root yang Anda inginkan dalam dimensi yang tepat:
Dapatkan posisi div sehubungan dengan kiri dan Atas
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
Saya memilih sebagai bawah dan kanan bukan sifat offset ()
MacroMan
@ MacroMan, saya menghormati keputusan Anda tetapi saya sudah menjelaskan dalam teks bahwa "kode di bagian bawah dan kanan tidak diuji.". Juga, saya akan segera memperbarui kode saya.
Vishal
Saya pikir itu el.offsetTopdan el.offsetLeft(OP tidak mengatakan apa pun tentang jQuery ... Saya juga tidak yakin mengapa jawaban Anda menggunakan jQuery ...)
Jawaban:
Pendekatan yang benar adalah dengan menggunakan
element.getBoundingClientRect()
:Internet Explorer telah mendukung ini sejak Anda cenderung peduli dan akhirnya standar di Tampilan CSSOM . Semua browser lain sudah lama menggunakannya .
Beberapa browser juga mengembalikan properti tinggi dan lebar, meskipun ini tidak standar. Jika Anda khawatir tentang kompatibilitas browser yang lebih lama, periksa revisi jawaban ini untuk penerapan penurunan yang dioptimalkan.
Nilai yang dikembalikan
element.getBoundingClientRect()
relatif terhadap viewport. Jika Anda membutuhkannya relatif terhadap elemen lain, cukup kurangi satu persegi panjang dari yang lain:sumber
<body>
, meskipun.element.getBoundingClientRect().top
tidak mengembalikan offset atas yang benar jika adaposition: fixed
elemen di iOS (iPhone 8) jika mengandung elemen input terfokus dan keyboard virtual telah meluncur. Misalnya, jika offset aktual dari bagian atas jendela adalah 200px, itu akan melaporkannya sebagai 420px, di mana 220px adalah ketinggian keyboard virtual. Jika Anda mengatur elemenposition: absolute
dan memposisikannya pada posisi yang sama seperti jika diperbaiki, maka Anda akan mendapatkan 200px yang benar. Saya tidak tahu solusi untuk ini.Perpustakaan berusaha keras untuk mendapatkan offset yang akurat untuk suatu elemen.
inilah fungsi sederhana yang melakukan pekerjaan dalam setiap keadaan yang telah saya coba.
sumber
Ini bekerja untuk saya (dimodifikasi dari jawaban pilihan tertinggi):
Dengan ini kita bisa menelepon
atau
sumber
div
yang berpusat menggunakan csstop:50%, left:50%; transform:translate(-50%, -50%);
... sangat baik. Setuju dengan pertanyaan @ScottBiggs. Logis adalah mencari kesederhanaan.rect
menggunakanvar
,let
atauconst
. Kalau tidak, itu didefinisikan sebagaiwindow.rect
.left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)
akan mengembalikan posisi tengah elemenJika Anda ingin melakukannya hanya dalam javascript , berikut adalah beberapa baris yang digunakan
getBoundingClientRect()
Baris pertama akan mengembalikan
offsetTop
say Y relatif ke dokumen. Baris kedua akan mengembalikanoffsetLeft
katakan X relatif terhadap dokumen.getBoundingClientRect()
adalah fungsi javascript yang mengembalikan posisi elemen relatif ke viewport jendela.sumber
Elemen HTML pada sebagian besar browser akan memiliki: -
Ini menentukan posisi elemen relatif orang tua terdekatnya yang memiliki tata letak. Induk ini sering dapat diakses jika properti offsetParent.
IE dan FF3 miliki
Properti ini kurang umum, mereka menentukan posisi elemen dengan area klien orang tuanya (area empuk adalah bagian dari area klien tetapi batas dan margin tidak).
sumber
Jika halaman menyertakan - setidaknya- "DIV" apa saja, fungsi yang diberikan oleh meouw melempar nilai "Y" melampaui batas halaman saat ini. Untuk menemukan posisi yang tepat, Anda harus menangani offsetParent dan parentNode.
Coba kode yang diberikan di bawah ini (diperiksa untuk FF2):
sumber
Anda dapat menambahkan dua properti
Element.prototype
untuk mendapatkan bagian atas / kiri elemen apa pun.Ini disebut seperti ini:
Berikut ini adalah demo yang membandingkan hasilnya dengan jQuery
offset().top
dan.left
: http://jsfiddle.net/ThinkingStiff/3G7EZ/sumber
Element.prototype
umumnya dianggap ide yang buruk . Itu menyebabkan sangat sulit untuk mempertahankan kode. Selain itu, kode ini tidak memperhitungkan pengguliran.Untuk mengambil posisi relatif terhadap halaman secara efisien, dan tanpa menggunakan fungsi rekursif: (termasuk IE juga)
sumber
Bagaimana dengan sesuatu seperti ini, dengan melewati ID elemen dan itu akan mengembalikan kiri atau atas, kita juga dapat menggabungkan mereka:
1) temukan kiri
2) temukan top
atau 3) temukan kiri dan atas bersamaan
sumber
Anda mungkin lebih baik dilayani dengan menggunakan kerangka kerja JavaScript, yang memiliki fungsi untuk mengembalikan informasi tersebut (dan banyak lagi!) Dengan cara yang tidak tergantung pada browser. Berikut ini beberapa di antaranya:
Dengan kerangka kerja ini, Anda dapat melakukan sesuatu seperti:
$('id-of-img').top
untuk mendapatkan koordinat y-pixel dari gambar.sumber
jQuery .offset () akan mendapatkan koordinat saat ini dari elemen pertama, atau mengatur koordinat setiap elemen, di set elemen yang cocok, relatif terhadap dokumen.
sumber
Saya telah mengambil jawaban @ meouw, ditambahkan di clientLeft yang memungkinkan untuk perbatasan, dan kemudian membuat tiga versi:
getAbsoluteOffsetFromBody - mirip dengan @ meouw, ini mendapatkan posisi absolut relatif terhadap elemen tubuh atau html dokumen (tergantung pada mode quirks)
getAbsoluteOffsetFromGivenElement - mengembalikan posisi absolut relatif terhadap elemen yang diberikan (relatifEl). Perhatikan bahwa elemen yang diberikan harus mengandung elemen el, atau ini akan berperilaku sama dengan getAbsoluteOffsetFromBody. Ini berguna jika Anda memiliki dua elemen yang terkandung di dalam elemen (dikenal) lainnya (opsional beberapa node di atas simpul pohon) dan ingin menjadikannya posisi yang sama.
getAbsoluteOffsetFromRelative - mengembalikan posisi absolut relatif ke elemen induk pertama dengan posisi: relatif. Ini mirip dengan getAbsoluteOffsetFromGivenElement, untuk alasan yang sama tetapi hanya akan sejauh elemen pencocokan pertama.
Jika Anda masih mengalami masalah, terutama yang berkaitan dengan pengguliran, Anda dapat mencoba melihat http://www.greywyvern.com/?post=331 - Saya perhatikan setidaknya satu potong kode yang dipertanyakan di getStyle yang seharusnya baik-baik saja dengan asumsi browser berperilaku , tetapi belum menguji sisanya sama sekali.
sumber
jika menggunakan jQuery, plugin dimensi sangat bagus dan memungkinkan Anda menentukan dengan tepat apa yang Anda inginkan.
misalnya
Posisi relatif, posisi absolut, posisi absolut tanpa bantalan, dengan bantalan ...
Terus, katakan saja ada banyak yang bisa Anda lakukan dengannya.
Plus bonus menggunakan jQuery adalah ukuran file yang ringan dan mudah digunakan, Anda tidak akan kembali ke JavaScript tanpa itu sesudahnya.
sumber
Ini adalah kode terbaik yang berhasil saya buat (berfungsi di iframe juga, tidak seperti offset jQuery ()). Sepertinya webkit memiliki sedikit perilaku yang berbeda.
Berdasarkan komentar meouw:
sumber
jQuery
menggunakan$.browser.webkit
; Anda harus bermain-main dengannavigator.userAgent
untuk melakukan hal yang sama dengan murniJavaScript
.Jika Anda menggunakan jQuery, ini bisa menjadi solusi sederhana:
sumber
Perbedaan antara kecil dan kecil
Lihat contoh koordinat: http://javascript.info/tutorial/coordinates
sumber
<svg>
elemen, misalnya, tidak memilikioffsetLeft
,offsetTop
, danoffsetParent
properti.DIV
atauIMG
tidakSVG
. Lihat "Lihat contoh koordinat"? Anda dapat menemukan objek svg adalah panggilan posisi getOffsetRect , mencoba dan bergantung pada objek.Pendekatan terbersih yang saya temukan adalah versi sederhana dari teknik yang digunakan oleh jQuery
offset
. Mirip dengan beberapa jawaban lain yang dimulai dengangetBoundingClientRect
; kemudian menggunakanwindow
dandocumentElement
untuk menyesuaikan posisi gulir serta hal-hal seperti margin padabody
(seringkali default).Tampilkan cuplikan kode
sumber
Meskipun ini sangat mungkin hilang di bagian bawah dari begitu banyak jawaban, solusi teratas di sini tidak bekerja untuk saya.
Sejauh yang saya tahu, tidak ada jawaban lain yang akan membantu.
Situasi :
Di halaman HTML5 saya memiliki menu yang merupakan elemen nav di dalam header (bukan header tetapi header di elemen lain).
Saya ingin navigasi untuk tetap di atas setelah pengguna menggulir ke sana, tapi sebelumnya header ini diposisikan absolut (jadi saya bisa sedikit overlay sesuatu yang lain).
Solusi di atas tidak pernah memicu perubahan karena .offsetTop tidak akan berubah karena ini adalah elemen yang diposisikan mutlak. Selain itu, properti .scrollTop hanyalah bagian atas elemen paling atas ... yaitu 0 dan selalu 0.
Setiap tes yang saya lakukan menggunakan kedua (dan sama dengan hasil getBoundingClientRect) tidak akan memberi tahu saya jika bagian atas bilah navigasi pernah menggulir ke bagian atas halaman yang dapat dilihat (sekali lagi, seperti yang dilaporkan dalam konsol, mereka hanya tinggal nomor yang sama saat menggulir terjadi).
Solusi
Solusi bagi saya adalah memanfaatkan
Nilai properti pageTop mencerminkan bagian layar yang dapat dilihat, oleh karena itu memungkinkan saya untuk melacak di mana elemen mengacu pada batas-batas area yang dapat dilihat.
Mungkin tidak perlu dikatakan, kapan pun saya berurusan dengan pengguliran, saya berharap untuk menggunakan solusi ini untuk merespons secara sistematis terhadap pergerakan elemen yang sedang digulir.
Semoga ini bisa membantu orang lain.
CATATAN PENTING: Ini tampaknya berfungsi di Chrome dan Opera saat ini & pasti tidak di Firefox (6-2018) ... sampai Firefox mendukung visualViewport Saya sarankan TIDAK menggunakan metode ini, (dan saya harap mereka segera melakukannya ... itu membuat banyak lebih masuk akal daripada yang lain).
UPDATE:
Hanya sebuah catatan mengenai solusi ini.
Sementara saya masih menemukan apa yang saya temukan sangat berharga untuk situasi di mana "... terprogram merespons pergerakan elemen yang sedang digulir." berlaku. Solusi yang lebih baik untuk masalah yang saya miliki adalah menggunakan CSS untuk mengatur posisi: stickypada elemen. Menggunakan sticky Anda dapat memiliki elemen tetap di atas tanpa menggunakan javascript (CATATAN: ada kalanya ini tidak akan bekerja seefektif mengubah elemen untuk diperbaiki tetapi untuk sebagian besar menggunakan pendekatan sticky kemungkinan akan lebih unggul)
UPDATE01:
Jadi saya menyadari bahwa untuk halaman yang berbeda saya memiliki persyaratan di mana saya perlu mendeteksi posisi elemen dalam pengaturan pengguliran yang agak rumit (paralaks plus elemen yang menggulir melewati sebagai bagian dari pesan). Saya menyadari dalam skenario itu bahwa berikut ini memberikan nilai yang saya gunakan untuk menentukan kapan harus melakukan sesuatu:
Semoga jawaban ini lebih bermanfaat sekarang.
sumber
Saya melakukannya seperti ini sehingga kompatibel dengan browser lama.
Lebih lanjut tentang koordinat dalam JavaScript di sini: http://javascript.info/tutorial/coordinates
sumber
Untuk mendapatkan total offset elemen, Anda bisa meringkas semua offset induk secara rekursif:
dengan fungsi utilitas ini offset total atas elemen dom adalah:
sumber
Terima kasih ThinkingStiff atas jawabannya , ini hanya versi lain.
sumber
Saya berhasil menggunakan solusi Andy E untuk memposisikan modal bootstrap 2 tergantung pada tautan apa di baris tabel yang diklik pengguna. Halaman ini adalah halaman Tapestry 5 dan javascript di bawah ini diimpor dalam kelas halaman java.
javascript:
}
Kode modal saya:
Tautan di loop:
Dan kode java di kelas halaman:
Semoga ini bisa membantu seseorang, posting ini membantu.
sumber
Setelah banyak penelitian dan pengujian, ini tampaknya berhasil
lihat http://jsbin.com/xuvovalifo/edit?html,js,output
sumber
Hanya berpikir saya akan membuang ini di sana juga.
Saya belum bisa mengujinya di browser yang lebih lama, tetapi ia bekerja di yang terbaru dari atas 3. :)
sumber
Karena browser yang berbeda memberikan batas, padding, margin, dll dengan cara yang berbeda. Saya menulis sedikit fungsi untuk mengambil posisi atas dan kiri elemen tertentu di setiap elemen root yang Anda inginkan dalam dimensi yang tepat:
Untuk mengambil posisi kiri, Anda harus kembali:
sumber
sumber
el.offsetTop
danel.offsetLeft
(OP tidak mengatakan apa pun tentang jQuery ... Saya juga tidak yakin mengapa jawaban Anda menggunakan jQuery ...)