Bagaimana cara mendapatkan dimensi viewport browser?

789

Saya ingin memberikan pengunjung saya kemampuan untuk melihat gambar dalam kualitas tinggi, apakah ada cara saya dapat mendeteksi ukuran jendela?

Atau lebih baik lagi, ukuran viewport browser dengan JavaScript? Lihat area hijau di sini:

Alix Axel
sumber
10
Apa yang saya lakukan adalah, mengatur elemen biasanya html ke ketinggian 100% dan mendapatkan ketinggiannya. Pekerjaan sederhana di mana-mana.
Muhammad Umer
1
@MuhammadUmer tangkapan yang bagus! Jika Anda merasa frustrasi mendapatkan dimensi (dan Anda akan, pada ponsel tanpa jQuery), Anda dapat getComputedStylemelakukan htmltag yang diperluas .
Dan
Juga, Anda dapat menggunakan perpustakaan W , yang menangani deteksi viewport lintas-browser;)
pyrsmk

Jawaban:

1328

Peramban silang @media (width) dan @media (height)nilai 

const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);

window.innerWidth dan .innerHeight

  • mendapat viewport CSS @media (width) dan @media (height)yang termasuk scrollbar
  • initial-scaledan variasi pembesaran dapat menyebabkan nilai seluler turun secara salah ke apa yang disebut PPK viewport visual dan lebih kecil dari @medianilai
  • zoom dapat menyebabkan nilai menjadi 1px karena pembulatan asli
  • undefined di IE8-

document.documentElement.clientWidth dan .clientHeight

Sumber daya

ryanve
sumber
4
@ 01100001 Ganti $dengan verge. Jika Anda ingin mengintegrasikan ke dalam jQuery maka lakukan jQuery.extend(verge). Lihat: verge.airve.com/#static
ryanve
4
Hanya ingin menyebutkan bahwa di IE8 (dan mungkin yang lain) Anda harus memiliki <!DOCTYPE html>di bagian atas halaman agar kode berfungsi.
Tzury Bar Yochay
6
Saya tidak senang dengan clientWidth / Height di perangkat seluler, benar-benar tripleodeon.com/wp-content/uploads/2011/12/table.html
Dan
24
Kecuali saya kehilangan sesuatu, jawaban ini salah. Di Chrome, setidaknya, document.documentElement.clientHeightmengembalikan tinggi halaman , sementara window.innerHeightmengembalikan tinggi viewport . Perbedaan besar.
Nate
2
variabel yang berbeda ukuran / solusi uji langsung: ryanve.com/lab/dimensions
Alex Pandrea
106

Fungsi dimensi jQuery

$(window).width() dan $(window).height()

Scott Evernden
sumber
60
@allyourcode, tidak mungkin, jQuery adalah jawaban untuk semua .
Xeoncross
21
Ini tidak mendapatkan ukuran viewport, tetapi ukuran keseluruhan dokumen. Cobalah.
Alejandro García Iglesias
2
Untuk browser yang menampilkan toolbar addon mereka sebagai HTML dengan postitionning tetap, solusi ini tidak berfungsi, terutama jika Anda ingin menggunakan posisi dan persentase teratas kode Anda.
Adib Aroui
7
@AlejandroIglesias: Tidak, saya baru mengujinya di halaman SO ini. $(window).height();mengembalikan 536, sedangkan $("html").height();pengembalian 10599
Flimm
2
Peringatan dimensi ini tidak termasuk scrollbar (yang memiliki ukuran berbeda di browser dan platform yang berbeda) dan oleh karena itu mereka tidak akan cocok dengan pertanyaan media css jawaban lain di sini akan tetapi menyelesaikan masalah ini.
Spencer O'Reilly
75

Anda bisa menggunakan properti window.innerWidth dan window.innerHeight .

innerHeight vs outerHeight

CMS
sumber
29
Meskipun ini tidak berfungsi di IE +1 untuk diagram: D. Untuk pertanyaan seperti ini, adalah kejahatan untuk tidak memiliki lebih dari ini.
allyourcode
8
@CMS document.documentElement.clientWidthlebih akurat dan lebih banyak didukung daripadawindow.innerWidth
ryanve
6
@ryanve Jika dengan "lebih akurat" maksudmu "bahkan tidak melakukan hal yang sama" maka ya: P
kotak
Firefox Beta? Itu adalah sesuatu milik museum.
Derek 朕 會 功夫
@boxed Di Safari seluler, document.documentElement.clientWidthberi saya lebar viewport sementara window.innerWidth memberi saya lebar dokumen. Ya, seperti itu.
John
33

Jika Anda tidak menggunakan jQuery, itu menjadi jelek. Berikut cuplikan yang berfungsi pada semua browser baru. Perilaku ini berbeda dalam mode Quirks dan mode standar di IE. Ini merawatnya.

var elem = (document.compatMode === "CSS1Compat") ? 
    document.documentElement :
    document.body;

var height = elem.clientHeight;
var width = elem.clientWidth;
Chetan Sastry
sumber
8
Bukankah ini memberi Anda ketinggian halaman, bukan viewport? Itulah yang ditunjukkan oleh halaman ini: developer.mozilla.org/en/DOM/element.clientHeight
allyourcode
4
Anda menggunakan clientHeightpada document.documentElementelemen, yang akan memberi Anda ukuran viewport. Untuk mendapatkan ukuran dokumen, Anda harus melakukannya document.body.clientHeight. Seperti yang dijelaskan oleh Chetan, perilaku ini berlaku untuk browser modern. Mudah untuk diuji. Cukup buka konsol dan ketik document.documentElement.clientHeightbeberapa tab terbuka.
Gajus
13

Saya tahu ini memiliki jawaban yang dapat diterima, tetapi saya mengalami situasi di mana clientWidthtidak berfungsi, karena iPhone (setidaknya milik saya) mengembalikan 980, bukan 320, jadi saya menggunakanwindow.screen.width . Saya sedang bekerja di situs yang ada, dibuat "responsif" dan perlu memaksa browser yang lebih besar untuk menggunakan meta-viewport yang berbeda.

Semoga ini bisa membantu seseorang, ini mungkin tidak sempurna, tetapi berfungsi dalam pengujian saya pada iOs dan Android.

//sweet hack to set meta viewport for desktop sites squeezing down to mobile that are big and have a fixed width 
  //first see if they have window.screen.width avail
  (function() {
    if (window.screen.width)
    {
      var setViewport = {
        //smaller devices
        phone: 'width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no',
        //bigger ones, be sure to set width to the needed and likely hardcoded width of your site at large breakpoints  
        other: 'width=1045,user-scalable=yes',
        //current browser width
        widthDevice: window.screen.width,
        //your css breakpoint for mobile, etc. non-mobile first
        widthMin: 560,
        //add the tag based on above vars and environment 
        setMeta: function () {
          var params = (this.widthDevice <= this.widthMin) ? this.phone : this.other; 
          var head = document.getElementsByTagName("head")[0];
          var viewport = document.createElement('meta');
          viewport.setAttribute('name','viewport');
          viewport.setAttribute('content',params);
          head.appendChild(viewport);
        }
      }
      //call it 
      setViewport.setMeta();
    }
  }).call(this);
Jazzy
sumber
13

Saya melihat dan menemukan cara lintas browser:

function myFunction(){
  if(window.innerWidth !== undefined && window.innerHeight !== undefined) { 
    var w = window.innerWidth;
    var h = window.innerHeight;
  } else {  
    var w = document.documentElement.clientWidth;
    var h = document.documentElement.clientHeight;
  }
  var txt = "Page size: width=" + w + ", height=" + h;
  document.getElementById("demo").innerHTML = txt;
}
<!DOCTYPE html>
<html>
  <body onresize="myFunction()" onload="myFunction()">
   <p>
    Try to resize the page.
   </p>
   <p id="demo">
    &nbsp;
   </p>
  </body>
</html>

pengguna2921779
sumber
perhatikan bahwa penggunaan stackoverflow untuk iframe yang mengelilingi potongan kode mengacaukan hasilnya
Miller
11

Saya dapat menemukan jawaban pasti dalam JavaScript: The Definitive Guide, Edisi ke-6 oleh O'Reilly, hlm. 391:

Solusi ini berfungsi bahkan dalam mode Quirks, sedangkan solusi ryanve dan ScottEvernden saat ini tidak.

function getViewportSize(w) {

    // Use the specified window or the current window if no argument
    w = w || window;

    // This works for all browsers except IE8 and before
    if (w.innerWidth != null) return { w: w.innerWidth, h: w.innerHeight };

    // For IE (or any browser) in Standards mode
    var d = w.document;
    if (document.compatMode == "CSS1Compat")
        return { w: d.documentElement.clientWidth,
           h: d.documentElement.clientHeight };

    // For browsers in Quirks mode
    return { w: d.body.clientWidth, h: d.body.clientHeight };

}

kecuali fakta bahwa saya bertanya-tanya mengapa garis if (document.compatMode == "CSS1Compat")tidak if (d.compatMode == "CSS1Compat"), semuanya terlihat bagus.

nonopolaritas
sumber
Anda berbicara tentang tampilan Retina atau Landscape vs Portrait atau tag meta viewport? Maksud Anda bukan piksel virtual seperti pada snowdragonledhk.com/… ?
nonopolaritas
1) Ketika berbicara tentang tampilan DPI tinggi, maksud saya piksel virtual dijelaskan di sini: stackoverflow.com/a/14325619/139361 . Setiap layar iPhone persis 320 piksel virtual. 2) Saya katakan: a) documentElement.clientWidthtidak merespons perubahan orientasi perangkat di iOS. b) menampilkan jumlah piksel fisik (praktis tidak berguna), bukan piksel virtual
Dan
11

Jika Anda mencari solusi non-jQuery yang memberikan nilai yang benar dalam piksel virtual pada perangkat seluler , dan Anda pikir itu jelas window.innerHeightatau document.documentElement.clientHeightdapat menyelesaikan masalah Anda, pelajari tautan ini terlebih dahulu: https://tripleodeon.com/assets/2011/12/ table.html

Pengembang telah melakukan pengujian yang baik yang mengungkapkan masalah: Anda bisa mendapatkan nilai yang tidak terduga untuk Android / iOS, lanskap / potret, tampilan normal / kepadatan tinggi.

Jawaban saya saat ini bukan peluru perak (// todo), melainkan peringatan bagi mereka yang akan dengan cepat menyalin-menempelkan solusi apa pun dari utas ini ke dalam kode produksi.

Saya mencari lebar halaman dalam piksel virtual di ponsel, dan saya menemukan satu-satunya kode yang berfungsi adalah (tanpa terduga!) window.outerWidth. Saya nanti akan memeriksa tabel ini untuk solusi yang benar memberikan ketinggian tidak termasuk bar navigasi, ketika saya punya waktu.

Dan
sumber
10

Kode ini dari http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/

function viewport() {
    var e = window, a = 'inner';
    if (!('innerWidth' in window )) {
        a = 'client';
        e = document.documentElement || document.body;
    }
    return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}

NB: untuk membaca lebarnya, gunakan console.log('viewport width'+viewport().width);

Xavier Blondel
sumber
9

Ada perbedaan antara window.innerHeightdan document.documentElement.clientHeight. Yang pertama termasuk ketinggian scrollbar horisontal.

Szépe Viktor
sumber
1
Apakah Anda menguji jawaban Anda di seluruh OS, pada tampilan Retina dan dalam mode landscape / portrait? Tautan ini mencakup sistem yang agak ketinggalan zaman, tetapi ini membuktikan bahwa kode Anda tidak berfungsi: tripleodeon.com/wp-content/uploads/2011/12/table.html
Dan
6

Solusi yang sesuai dengan standar W3C adalah membuat div transparan (misalnya secara dinamis dengan JavaScript), atur lebar dan tingginya menjadi 100vw / 100vh (unit Viewport) lalu dapatkan offsetWidth dan offsetHeight. Setelah itu, elemen dapat dihapus kembali. Ini tidak akan berfungsi di browser lama karena unit viewport relatif baru, tetapi jika Anda tidak peduli tentang mereka tetapi tentang standar (yang akan datang) sebagai gantinya, Anda pasti bisa seperti ini:

var objNode = document.createElement("div");
objNode.style.width  = "100vw";
objNode.style.height = "100vh";
document.body.appendChild(objNode);
var intViewportWidth  = objNode.offsetWidth;
var intViewportHeight = objNode.offsetHeight;
document.body.removeChild(objNode);

Tentu saja, Anda juga dapat mengatur objNode.style.position = "diperbaiki" dan kemudian menggunakan 100% sebagai lebar / tinggi - ini harus memiliki efek yang sama dan meningkatkan kompatibilitas sampai batas tertentu. Juga, mengatur posisi untuk diperbaiki mungkin merupakan ide yang baik secara umum, karena jika tidak div akan tidak terlihat tetapi menghabiskan beberapa ruang, yang akan menyebabkan scrollbar muncul dll.

Api jatuh
sumber
Sayangnya, kenyataannya benar-benar menghancurkan "solusi standar W3C" Anda: 1) caniuse.com/viewport-units , 2) caniuse.com/#feat=css-fixed . Apa yang dibutuhkan pengembang adalah solusi yang berfungsi, bukan "seharusnya secara teori berhasil".
Dan
Jika kita dapat mengandalkan standar maka kita bahkan tidak memerlukan semua solusi lintas browser itu. Solusi yang menjawab spesifikasi bukanlah solusi.
Derek 朕 會 功夫
3

Ini adalah cara saya melakukannya, saya mencobanya di IE 8 -> 10, FF 35, Chrome 40, itu akan bekerja sangat lancar di semua browser modern (seperti window.innerWidth didefinisikan) dan di IE 8 (tanpa jendela. innerWidth) berfungsi dengan baik juga, masalah apa pun (seperti flashing karena overflow: "hidden"), tolong laporkan. Saya tidak terlalu tertarik pada ketinggian viewport karena saya membuat fungsi ini hanya untuk menyelesaikan beberapa alat responsif, tetapi mungkin dapat diimplementasikan. Semoga ini bisa membantu, saya menghargai komentar dan saran.

function viewportWidth () {
  if (window.innerWidth) return window.innerWidth;
  var
  doc = document,
  html = doc && doc.documentElement,
  body = doc && (doc.body || doc.getElementsByTagName("body")[0]),
  getWidth = function (elm) {
    if (!elm) return 0;
    var setOverflow = function (style, value) {
      var oldValue = style.overflow;
      style.overflow = value;
      return oldValue || "";
    }, style = elm.style, oldValue = setOverflow(style, "hidden"), width = elm.clientWidth || 0;
    setOverflow(style, oldValue);
    return width;
  };
  return Math.max(
    getWidth(html),
    getWidth(body)
  );
}
manolinjr81
sumber