Jak uzyskać wymiary rzutni przeglądarki?

788

Chcę zapewnić odwiedzającym możliwość oglądania obrazów w wysokiej jakości, czy jest jakiś sposób na wykrycie rozmiaru okna?

A może jeszcze lepiej, rozmiar okna przeglądarki z JavaScriptem? Zobacz zielony obszar tutaj:

Alix Axel
źródło
10
To, co robię, to ustawienie elementu zwykle w formacie HTML na 100% wysokości i uzyskanie jego wysokości. Prosta działa wszędzie.
Muhammad Umer
1
@MuhammadUmer good catch! Jeśli frustrują Cię otrzymywanie wymiarów (i tak będzie w przypadku telefonów komórkowych bez jQuery), możesz getComputedStylerozwinąć htmltag.
Dan
Możesz także skorzystać z biblioteki W , która obsługuje wykrywanie rzutni w różnych przeglądarkach;)
pyrsmk

Odpowiedzi:

1327

Przeglądarka @media (width) i @media (height)wartości 

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

window.innerWidth i .innerHeight

  • pobiera rzutnię CSS @media (width) i @media (height)które zawierają paski przewijania
  • initial-scalea zmiany powiększenia mogą powodować nieprawidłowe skalowanie wartości mobilnych do tego, co PPK nazywa wizualną rzutnią i może być mniejsze niż @mediawartości
  • Zoom może powodować, że wartości będą wyłączone o 1px z powodu natywnego zaokrąglania
  • undefined w IE8-

document.documentElement.clientWidth i .clientHeight

Zasoby

ryanve
źródło
4
@ 01100001 Wymień $z verge. Jeśli chcesz zintegrować się z jQuery, zrób to jQuery.extend(verge). Zobacz: verge.airve.com/#static
ryanve
4
Chciałem tylko wspomnieć, że w IE8 (i być może w innych) musisz mieć <!DOCTYPE html>na górze strony, aby kod działał.
Tzury Bar Yochay
6
Nie jestem zadowolony z clientWidth / wysokość na urządzeniach mobilnych, naprawdę tripleodeon.com/wp-content/uploads/2011/12/table.html
Dan
24
O ile mi czegoś nie brakuje, ta odpowiedź jest błędna. W Chrome przynajmniej document.documentElement.clientHeightzwraca wysokość strony , a window.innerHeightzwraca wysokość rzutni . Duża różnica.
Nate
2
test zmiennej na żywo dla różnych wielkości / rozwiązań: ryanve.com/lab/dimensions
Alex Pandrea
106

Funkcje wymiaru jQuery

$(window).width() i $(window).height()

Scott Evernden
źródło
60
@allyourcode, niemożliwe, jQuery jest odpowiedzią dla wszystkich .
Xeoncross
21
Nie dostaje to rozmiaru rzutni, ale ogólny rozmiar dokumentu. Spróbuj.
Alejandro García Iglesias
2
W przypadku przeglądarek, które wyświetlają swoje dodatkowe paski narzędzi jako HTML z ustalonym pozycjonowaniem, to rozwiązanie nie działa, szczególnie jeśli chcesz używać w ustawianiu najwyższego kodu i wartości procentowych.
Adib Aroui
7
@AlejandroIglesias: Nie, właśnie przetestowałem to na tej stronie SO. $(window).height();zwraca 536, podczas gdy $("html").height();zwraca 10599
Flimm
2
Ostrzeżenie: te wymiary nie obejmują pasków przewijania (które mają różne rozmiary w różnych przeglądarkach i platformach) i dlatego nie będą pasować do zapytań o media css, inne odpowiedzi tutaj rozwiązują jednak ten problem.
Spencer O'Reilly
75

Możesz użyć właściwości window.innerWidth i window.innerHeight .

innerHeight vs. outerHeight

CMS
źródło
29
Nawet jeśli to nie działa w IE +1 dla diagramu: D. W przypadku takiego pytania przestępstwem byłoby nie mieć ich więcej.
allyourcode
8
@CMS document.documentElement.clientWidthjest dokładniejszy i szerzej wspierany niżwindow.innerWidth
ryanve,
6
@ryanve Jeśli przez „bardziej dokładny” masz na myśli „nawet nie zdalnie robi to samo”, to tak: P
zapakowane
Firefox Beta? To coś należało do muzeum.
Derek 朕 會 功夫
@boxed W mobilnym Safari document.documentElement.clientWidthdaje mi szerokość rzutni, podczas gdy window.innerWidth daje mi szerokość dokumentu. Tak, na odwrót.
John
33

Jeśli nie używasz jQuery, robi się brzydko. Oto fragment kodu, który powinien działać we wszystkich nowych przeglądarkach. Zachowanie jest inne w trybie dziwactwa i trybie standardów w IE. To się tym zajmuje.

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

var height = elem.clientHeight;
var width = elem.clientWidth;
Chetan Sastry
źródło
8
Czy to nie daje wysokości strony, a nie rzutni? Tak wskazuje ta strona: developer.mozilla.org/en/DOM/element.clientHeight
allyourcode
4
Używasz clientHeightna document.documentElementelemencie, który daje rozmiar rzutni. Aby uzyskać rozmiar dokumentu, musisz to zrobić document.body.clientHeight. Jak wyjaśnia Chetan, takie zachowanie dotyczy współczesnych przeglądarek. To jest łatwe do przetestowania. Wystarczy otworzyć konsolę i wpisać document.documentElement.clientHeightkilka otwartych kart.
Gajus,
13

Wiem, że ma to akceptowalną odpowiedź, ale wpadłem na sytuację, w której clientWidthnie działało, ponieważ iPhone (przynajmniej mój) zwrócił 980, a nie 320, więc użyłem window.screen.width. Pracowałem nad istniejącą witryną, będąc „responsywnym” i musiałem zmusić większe przeglądarki do korzystania z innej meta-rzutni.

Mam nadzieję, że to komuś pomoże, może nie być idealne, ale działa w moich testach na iOS i Androidzie.

//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);
Zgrzytliwy
źródło
13

Spojrzałem i znalazłem sposób na przeglądarkę:

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>

użytkownik2921779
źródło
zauważ, że użycie elementu iframe otaczającego fragment kodu przez stackoverflow zaburza wynik
Miller
11

Ostatecznie udało mi się znaleźć ostateczną odpowiedź w JavaScript: The Definitive Guide, 6. wydanie autorstwa O'Reilly, str. 391:

To rozwiązanie działa nawet w trybie dziwactwa, podczas gdy obecne rozwiązanie Ryanve i ScottEvernden nie.

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 };

}

poza tym, że zastanawiam się, dlaczego if (document.compatMode == "CSS1Compat")nie ma linii if (d.compatMode == "CSS1Compat"), wszystko wygląda dobrze.

niepolarność
źródło
czy mówisz o wyświetlaniu Retina, krajobrazie w pionie, czy o metatagie rzutni? Nie masz na myśli wirtualnych pikseli, jak w snowdragonledhk.com/… ?
nonpolarity
1) Mówiąc o wyświetlaczach o wysokiej DPI mam na myśli wirtualne piksele wyjaśnione tutaj: stackoverflow.com/a/14325619/139361 . Każdy ekran iPhone'a ma dokładnie 320 wirtualnych pikseli. 2) Mówię, że: a) documentElement.clientWidthnie reaguje na zmianę orientacji urządzenia w iOS. b) wyświetla liczbę pikseli fizycznych (praktycznie bezużytecznych) zamiast pikseli wirtualnych
Dan
11

Jeśli szukasz rozwiązania innego niż jQuery, które daje prawidłowe wartości w wirtualnych pikselach na telefonie komórkowym , i uważasz, że to proste window.innerHeightlub document.documentElement.clientHeightmoże rozwiązać problem, najpierw zapoznaj się z tym linkiem: https://tripleodeon.com/assets/2011/12/ table.html

Deweloper wykonał dobre testy, które ujawniają problem: można uzyskać nieoczekiwane wartości dla Androida / iOS, poziomej / pionowej, normalnej / wysokiej gęstości wyświetlaczy.

Moja obecna odpowiedź nie jest jeszcze srebrną kulą (// todo), ale raczej ostrzeżeniem dla tych, którzy zamierzają szybko skopiować i wkleić dowolne rozwiązanie z tego wątku do kodu produkcyjnego.

Szukałem szerokości strony w wirtualnych pikselach na urządzeniach mobilnych i okazało się, że jedynym działającym kodem jest (nieoczekiwanie!) window.outerWidth. Później zbadam tę tabelę pod kątem prawidłowego rozwiązania, podając wysokość bez paska nawigacyjnego, kiedy będę miał czas.

Dan
źródło
10

Ten kod pochodzi z 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' ] };
}

Uwaga: aby odczytać szerokość, użyj console.log('viewport width'+viewport().width);

Xavier Blondel
źródło
9

Istnieje różnica między window.innerHeighti document.documentElement.clientHeight. Pierwszy obejmuje wysokość poziomego paska przewijania.

Szépe Viktor
źródło
1
Czy przetestowałeś swoją odpowiedź w różnych systemach operacyjnych, na wyświetlaczach Retina oraz w trybie poziomym / pionowym? Ten link dotyczy raczej przestarzałych systemów, ale dowodzi, że Twój kod nie działa: tripleodeon.com/wp-content/uploads/2011/12/table.html
Dan
6

Rozwiązaniem, które byłoby zgodne ze standardami W3C byłoby utworzenie przezroczystej div (na przykład dynamicznie z JavaScript), ustawienie jej szerokości i wysokości na 100vw / 100vh (jednostki Viewport), a następnie uzyskanie jej offsetWidth i offsetHeight. Następnie element można ponownie usunąć. Nie będzie to działać w starszych przeglądarkach, ponieważ jednostki rzutni są stosunkowo nowe, ale jeśli nie przejmujesz się nimi, ale (przyszłymi) standardami, zdecydowanie możesz pójść tą drogą:

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);

Oczywiście możesz również ustawić objNode.style.position = "fixed", a następnie użyć 100% jako szerokość / wysokość - powinno to mieć ten sam efekt i do pewnego stopnia poprawić kompatybilność. Również ustawienie pozycji na ustaloną może być ogólnie dobrym pomysłem, ponieważ w przeciwnym razie div będzie niewidoczny, ale zajmie trochę miejsca, co spowoduje pojawienie się pasków przewijania itp.

Firefall
źródło
Niestety, rzeczywistość całkowicie niszczy twoje „W3C - standardy rozwiązanie”: 1) caniuse.com/viewport-units , 2) caniuse.com/#feat=css-fixed . Programiści potrzebują rozwiązania, które działa, a nie „powinno teoretycznie działać”.
Dan
Jeśli możemy polegać na standardach, nie potrzebujemy nawet wszystkich rozwiązań dla różnych przeglądarek. Rozwiązanie, które odpowiada w specyfikacji, nie jest rozwiązaniem.
Derek 朕 會 功夫
3

W ten sposób to robię, wypróbowałem to w IE 8 -> 10, FF 35, Chrome 40, będzie działać bardzo płynnie we wszystkich współczesnych przeglądarkach (jak zdefiniowano window.innerWidth) oraz w IE 8 (bez okna). innerWidth) działa również płynnie, każdy problem (jak flashowanie z powodu przepełnienia: „ukryty”), zgłoś to. Tak naprawdę nie interesuje mnie wysokość rzutni, ponieważ stworzyłem tę funkcję, aby obejść niektóre responsywne narzędzia, ale można ją zaimplementować. Mam nadzieję, że to pomaga, doceniam komentarze i sugestie.

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
źródło