$ (window) .width () tidak sama dengan kueri media

186

Saya menggunakan Bootstrap Twitter pada sebuah proyek. Serta gaya bootstrap default saya juga menambahkan beberapa dari saya sendiri

//My styles
@media (max-width: 767px)
{
    //CSS here
}

Saya juga menggunakan jQuery untuk mengubah urutan elemen tertentu pada halaman ketika lebar viewport kurang dari 767px.

$(document).load($(window).bind("resize", checkPosition));

function checkPosition()
{
    if($(window).width() < 767)
    {
        $("#body-container .main-content").remove().insertBefore($("#body-container .left-sidebar"));
    } else {
        $("#body-container .main-content").remove().insertAfter($("#body-container .left-sidebar"));
    }
}

Masalah yang saya alami adalah bahwa lebar yang dihitung oleh $(window).width()dan lebar yang dihitung oleh CSS tampaknya tidak sama. Ketika $(window).width()mengembalikan 767 css menghitungnya lebar viewport 751 sehingga tampaknya ada 16px berbeda.

Adakah yang tahu apa yang menyebabkan ini dan bagaimana saya bisa menyelesaikan masalah? Orang-orang telah menyarankan bahwa lebar bilah gulir tidak dipertimbangkan dan menggunakan $(window).innerWidth() < 751adalah cara untuk pergi. Namun idealnya saya ingin menemukan solusi yang menghitung lebar scrollbar dan yang konsisten dengan permintaan media saya (misalnya di mana kedua kondisi memeriksa terhadap nilai 767). Karena pasti tidak semua browser akan memiliki lebar scrollbar 16px?

Ternak
sumber
1
Coba sesuatu jika ($ ('html'). Width () <= 767) {// Lakukan sesuatu}
Vaibs_Cool
@Vaibs_Cool Terima kasih atas sarannya tetapi saya masih mendapatkan hasil yang sama
Pattle
Jawab saya di sini [masukkan uraian tautan di sini] [1] [1]: stackoverflow.com/questions/11309859/…
Rantiev
Apakah "document.documentElement.clientWidth" (bukan "$ (window) .width ()") berfungsi sesuai keinginan Anda? Sunting: Kesalahan saya, baru melihat jawaban Vaibs_Cool.
joshhunt

Jawaban:

293

Jika Anda tidak harus mendukung IE9, Anda cukup menggunakan window.matchMedia()( dokumentasi MDN ).

function checkPosition() {
    if (window.matchMedia('(max-width: 767px)').matches) {
        //...
    } else {
        //...
    }
}

window.matchMediasepenuhnya konsisten dengan permintaan media CSS dan dukungan browser cukup baik: http://caniuse.com/#feat=matchmedia

MEMPERBARUI:

Jika Anda harus mendukung lebih banyak peramban, Anda dapat menggunakan metode mq Modernizr , ia mendukung semua peramban yang memahami kueri media dalam CSS.

if (Modernizr.mq('(max-width: 767px)')) {
    //...
} else {
    //...
}
ausi
sumber
8
Jika Anda mampu menggunakan perpustakaan Modernizr, ini adalah jawaban terbaik di luar sana.
richsinn
1
Solusi ini lebih baik: stackoverflow.com/a/19292035/1136132 (kode 2). Hanya JS.
joseantgv
@joseantgv Solusi saya juga hanya js. Bisakah Anda menjelaskan mengapa solusi yang Anda tautkan lebih baik?
ausi
2
@edwardm Modernizr.mqhanya mengembalikan nilai boolean, jadi Anda harus menyebutnya sendiri dalam onresizepengendali event.
ausi
2
@Bernig window.matchMediaadalah cara yang disarankan, karena tidak memicu reflow , tergantung pada seberapa sering Anda memanggil fungsi ini dapat menyebabkan masalah kinerja. Jika Anda tidak ingin menggunakan Modernizr secara langsung, Anda dapat menyalin kode sumber dari src / mq.js dan src / injectElementWithStyles.js .
ausi
175

Periksa aturan CSS yang diubah oleh kueri media. Ini dijamin selalu berhasil.

http://www.fourfront.us/blog/jquery-window-width-and-media-queries

HTML:

<body>
    ...
    <div id="mobile-indicator"></div>
</body>

Javascript:

function isMobileWidth() {
    return $('#mobile-indicator').is(':visible');
}

CSS:

#mobile-indicator {
    display: none;
}

@media (max-width: 767px) {
    #mobile-indicator {
        display: block;
    }
}
NateS
sumber
9
Itu solusi yang lebih elegan daripada peretasan JS yang disebutkan dalam jawaban lain.
René Roth
3
+1 ini pintar. Saya suka bagaimana jika Anda ingin mengubah breakpoint yang harus Anda lakukan adalah mengubah css dan bukan javascript.
JoeMoe1984
Solusi ini berfungsi dengan baik dan saya merasa lebih elegan daripada hack javascript yang diusulkan dalam jawaban yang paling banyak dipilih.
Andrés Meza-Escallón
2
Jika Anda menggunakan bootstrap, Anda dapat melakukannya tanpa css seperti<div id="xs-indicator" class="xs-visible">
Čamo
33

Mungkin karena scrollbar, gunakan innerWidthbukan widthsuka

if($(window).innerWidth() <= 751) {
   $("#body-container .main-content").remove()
                                .insertBefore($("#body-container .left-sidebar"));
} else {
   $("#body-container .main-content").remove()
                                .insertAfter($("#body-container .left-sidebar"));
}

Anda juga bisa mendapatkan viewportsejenisnya

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

Sumber kode di atas

Rohan Kumar
sumber
Terima kasih. Ini akan bekerja tetapi apakah ada saya bisa menggunakan jquery untuk memasukkan lebar scrollbar. Saya hanya berpikir bahwa lebar scrollbar dapat berubah pada browser yang berbeda?
Pattle
1
Ya gunakan innerWidth()atau Anda dapat menggunakannya seperti $('body').innerWidth();Lihat ini stackoverflow.com/questions/8339377/…
Rohan Kumar
3
Maksud Anda window.innerWidth, bukan pada objek jQuery $ (window), $ (window) .width () mengembalikannya dengan tidak benar
EJanuszewski
1
window.innerWidthtidak konsisten dengan kueri media CSS di Safari 8 jika bilah gulir diaktifkan di preferensi sistem OSX.
ausi
10

ya, itu karena scrollbar. Sumber jawaban yang benar: masukkan uraian tautan di sini

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' ] };
}
Rantiev
sumber
4

Ini mungkin praktik yang lebih baik bukan untuk JS-lingkup lebar dokumen tetapi semacam perubahan yang dibuat oleh css @media query. Dengan metode ini Anda dapat yakin bahwa fungsi JQuery dan perubahan css terjadi secara bersamaan.

css:

#isthin {
    display: inline-block;
    content: '';
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media only screen and (max-width: 990px) {
    #isthin {
        display: none;
    }
}

jquery:

$(window).ready(function(){
    isntMobile = $('#isthin').is(":visible");
    ...
});

$(window).resize(function(){
    isntMobile = $('#isthin').is(":visible");
    ...
});
gram
sumber
3

Saya menghadapi masalah yang sama baru-baru ini - juga dengan Bootstrap 3.

$ .Width () atau $ .innerWidth () tidak akan berfungsi untuk Anda.

Solusi terbaik yang saya temukan - dan secara khusus dirancang untuk BS3 -
adalah memeriksa lebar .containerelemen.

Karena Anda mungkin tahu bagaimana .containerelemen bekerja,
itu satu-satunya elemen yang akan memberi Anda lebar saat ini yang ditetapkan oleh aturan BS css.

Jadi begitulah kira-kira

bsContainerWidth = $("body").find('.container').width()
if (bsContainerWidth <= 768)
    console.log("mobile");
else if (bsContainerWidth <= 950)
    console.log("small");
else if (bsContainerWidth <= 1170)
    console.log("medium");
else
    console.log("large");
pengguna3041539
sumber
3

Menggunakan

window.innerWidth

Ini menyelesaikan masalah saya

pengguna4451021
sumber
3

Berikut ini adalah alternatif dari metode yang disebutkan sebelumnya yang mengandalkan perubahan sesuatu melalui CSS dan membacanya melalui Javascript. Metode ini tidak perlu window.matchMediaatau Modernizr. Itu juga tidak memerlukan elemen HTML tambahan. Ia bekerja dengan menggunakan elemen pseudo-HTML untuk menyimpan informasi breakpoint:

body:after {
  visibility: hidden;
  height: 0;
  font-size: 0;
}

@media (min-width: 20em) {
  body:after {
    content: "mobile";
  }
}

@media (min-width: 48em) {
  body:after {
    content: "tablet";
  }
}

@media (min-width: 64em) {
  body:after {
    content: "desktop";
  }
}

Saya menggunakan bodysebagai contoh, Anda dapat menggunakan elemen HTML apa pun untuk ini. Anda dapat menambahkan string atau nomor apa pun yang Anda inginkan ke dalam contentelemen pseudo. Tidak harus 'mobile' dan seterusnya.

Sekarang kita dapat membaca informasi ini dari Javascript dengan cara berikut:

var breakpoint = window.getComputedStyle(document.querySelector('body'), ':after').getPropertyValue('content').replace(/"/g,'');

if (breakpoint === 'mobile') {
    doSomething();
}

Dengan cara ini kami selalu yakin bahwa informasi breakpoint sudah benar, karena itu datang langsung dari CSS dan kami tidak perlu repot mendapatkan lebar layar yang tepat melalui Javascript.

dschenk
sumber
Anda tidak perlu menggunakan querySelector()atau getPropertyValue(). Anda dapat mencari penawaran tunggal di regex juga (karena tidak konsisten). Ini: window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, ''). Dan, untuk membuatnya sedikit lebih murah, Anda dapat membungkusnya dengan underscore / lodash ._debounce()dengan ~ 100ms menunggu. Akhirnya, menambahkan attribs ke <html> membuat output tersedia untuk hal-hal lain seperti klausa tooltip disable yang mencari flag / data mentah di luar vars. Contoh: gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin
2

Javascript menyediakan lebih dari satu metode untuk memeriksa lebar viewport. Seperti yang Anda perhatikan, innerWidth tidak termasuk lebar bilah alat, dan lebar bilah alat akan berbeda di seluruh sistem. Ada juga opsi outerWidth , yang akan mencakup lebar toolbar. The Mozilla Javascript API negara:

Window.outerWidth mendapatkan lebar bagian luar jendela browser. Ini mewakili lebar seluruh jendela browser termasuk sidebar (jika diperluas), chrome jendela dan batas ukuran jendela / pegangan.

Keadaan javascript sedemikian rupa sehingga orang tidak dapat mengandalkan makna khusus untuk outerWidth di setiap browser di setiap platform.

outerWidthadalah tidak didukung pada yang lebih tua browser ponsel , meskipun mendapat dukungan di browser desktop utama dan paling baru browser ponsel pintar.

Seperti yang ditunjukkan oleh ausi, matchMediaakan menjadi pilihan bagus karena CSS distandarisasi dengan lebih baik (matchMedia menggunakan JS untuk membaca nilai viewport yang terdeteksi oleh CSS). Tetapi bahkan dengan standar yang diterima, browser terbelakang masih ada yang mengabaikannya (IE <10 dalam hal ini, yang membuat matchMedia tidak terlalu berguna setidaknya sampai XP mati).

Dalam ringkasan , jika Anda hanya mengembangkan untuk browser desktop dan mobile browser yang lebih baru, outerWidth harus memberikan apa yang Anda cari, dengan beberapa keberatan .

fzzylogic
sumber
1

Berikut adalah trik yang kurang terlibat untuk menangani pertanyaan media. Dukungan lintas browser agak terbatas karena tidak mendukung IE mobile.

     if (window.matchMedia('(max-width: 694px)').matches)
    {
        //do desired changes
    }

Lihat dokumentasi Mozilla untuk lebih jelasnya.

pengguna2128205
sumber
1

coba ini

getData(){
    if(window.innerWidth <= 768) {
      alert('mobile view')
      return;
    }

   //else function will work

    let body= {
      "key" : 'keyValue'
    }
    this.dataService.getData(body).subscribe(
      (data: any) => {
        this.myData = data
      }
    )
}
DINESH Adhikari
sumber
0

Solusi yang selalu berfungsi dan disinkronkan dengan kueri media CSS.

Tambahkan div ke badan

<body>
    ...
    <div class='check-media'></div>
    ...
</body>

Tambahkan gaya dan ubah dengan memasukkan ke dalam kueri media tertentu

.check-media{
    display:none;
    width:0;
}
@media screen and (max-width: 768px) {
    .check-media{
         width:768px;
    }
    ...
}

Kemudian dalam gaya periksa JS yang Anda ubah dengan memasukkan ke dalam kueri media

if($('.check-media').width() == 768){
    console.log('You are in (max-width: 768px)');
}else{
    console.log('You are out of (max-width: 768px)');
}

Jadi secara umum Anda dapat memeriksa gaya apa pun yang sedang diubah dengan memasukkan ke dalam kueri media tertentu.

Arsen Pyuskyulyan
sumber
0

Solusi lintas-browser terbaik adalah dengan menggunakan Modernizr.mq

tautan: https://modernizr.com/docs/#mq

Modernizr.mq memungkinkan Anda untuk memeriksa secara terprogram apakah kondisi jendela browser saat ini cocok dengan kueri media.

var query = Modernizr.mq('(min-width: 900px)');
if (query) {
   // the browser window is larger than 900px
}

Catatan Browser tidak mendukung permintaan media (mis. IE lama) mq akan selalu kembali salah.

Sanjib Debnath
sumber
0
if(window.matchMedia('(max-width: 768px)').matches)
    {
        $(".article-item").text(function(i, text) {

            if (text.length >= 150) {
                text = text.substring(0, 250);
                var lastIndex = text.lastIndexOf(" ");     
                text = text.substring(0, lastIndex) + '...'; 
            }

            $(this).text(text);

        });

    }
Adam Colton
sumber
0

Apa yang saya lakukan ;

<body>
<script>
function getWidth(){
return Math.max(document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth);
}
var aWidth=getWidth();
</script>
...

dan memanggil variabel Lebar di mana saja setelahnya.

Anda perlu memasang getWidth () di badan dokumen Anda untuk memastikan bahwa lebar scrollbar dihitung, jika tidak, lebar scrollbar browser dikurangi dari getWidth ().

burkul
sumber
-1

Implementasi slider yang licin dan tampilkan jumlah slide yang berbeda di blok tergantung pada resolusi (jQuery)

   if(window.matchMedia('(max-width: 768px)').matches) {
      $('.view-id-hot_products .view-content').slick({
        infinite: true,
        slidesToShow: 3,
        slidesToScroll: 3,
        dots: true,
      });
    }

    if(window.matchMedia('(max-width: 1024px)').matches) {
      $('.view-id-hot_products .view-content').slick({
        infinite: true,
        slidesToShow: 4,
        slidesToScroll: 4,
        dots: true,
      });
    }
Vitalii
sumber
-2

Coba ini

if (document.documentElement.clientWidth < 767) {
   // scripts
}

Untuk Referensi Lebih Lanjut klik di sini

Vaibs_Cool
sumber
Terima kasih, ini masih memiliki hasil yang sama
Pattle