重新呈现网页的最佳方法是什么?

时间:2021-12-14 00:51:17

I have a fluid CSS layout which is rendering badly on an iphone when I change the orientation. (It looks fine when it is refreshed).

我有一个流畅的CSS布局,当我改变方向时,在iphone上表现得很糟糕。(当它刷新时看起来很好)。

I am using the code below to refresh the page on orientation change, which works fine - it just feels a little wrong doing so. Is there any way of achieving this without having to reload the entire page? It is a mobile site, I don't really want to force the user to load the page twice.

我正在使用下面的代码来刷新关于方向改变的页面,它工作得很好——只是感觉这样做有点不对。有什么方法可以在不重载整个页面的情况下实现这一点吗?这是一个移动站点,我并不想强迫用户加载两次页面。

var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    window.location.reload()
}, false);   

Edit:

编辑:

The two main issues when testing on an iphone are:

在iphone上测试的两个主要问题是:

I have a which is 100% width, with a right aligned background image. When I change the orientation from portrait to landscape the body width remains as how it rendered on portrait mode and vice versa. It is more of an issue from landscape to portrait as the page is too wide and it seems to render the images twice.

我有一个100%的宽度,有一个右对齐的背景图像。当我改变从肖像到风景的方向时,身体的宽度仍然保持在肖像模式下,反之亦然。从横向到纵向,这是一个更大的问题,因为页面太宽了,而且看起来会渲染两次。

8 个解决方案

#1


23  

Assuming your CSS is already happily rendering on your various size mobile device screens, you need to define the viewport in the <head> of your template.

假设您的CSS已经在各种大小的移动设备屏幕上愉快地呈现,您需要在模板的中定义viewport。

Example, this sets the page width to be the device's screen width and an initial zoom of 100%. Initial zoom is applied at page load, but not when the orientation is changed.

例如,这将页面宽度设置为设备的屏幕宽度,初始放大为100%。初始变焦是在页面加载时应用的,但不会在方向改变时应用。

<meta name="viewport" content="width=device-width, initial-scale=1.0">

By adding a maximum-scale=1.0 parameter to the viewport you will force the iPad/iPhone to maintain the zoom level and re-layout the page on orientation change. The disadvantage of this is that it will disable zooming. However, the advantage is that you can make layout adjustments with media queries to present the content in a suitable fashion for the current orientation. You can read more about viewport here: Choosing a ViewPort

通过向viewport添加最大比例=1.0参数,您将迫使iPad/iPhone保持缩放级别,并在方向改变时重新布局页面。这样做的缺点是它会禁用缩放。但是,优点是您可以通过媒体查询进行布局调整,以适合当前方向的方式呈现内容。您可以在这里阅读更多关于viewport的内容:选择viewport

Now onto media queries. You should put media queries at the bottom of your CSS file and in the order of smallest width to largest width for screen widths. For example, taken from the Html5BoilerPlate CSS example:

现在媒体上查询。您应该将媒体查询置于您的CSS文件的底部,并以最小宽度的顺序将屏幕宽度设为最大宽度。例如,取自Html5BoilerPlate CSS示例:

@media only screen and (min-width: 480px) {
  /* Style adjustments for viewports 480px and over go here */

}

@media only screen and (min-width: 768px) {
  /* Style adjustments for viewports 768px and over go here */

}

So all your normal styles are above this and applied first, then if the screen is 480px or wider the next block of styles are applied, then if the screen is 768px or wider the last block of styles are applied.

所以你所有的正常样式都在上面,首先应用,如果屏幕是480px或者更宽,那么下一个样式块被应用,如果屏幕是768px或者更宽,最后一个样式块被应用。

By combining the fixed zoom level to 1.0 and the media-queries, you can make your site responsively resize to the screen size and orientation without javascript. Obviously you need to make sure the site is then well designed so users don't need zooming. If your site is optimized for mobile this shouldn't be a problem.

通过将固定的缩放级别结合到1.0和媒体查询,您可以使您的站点响应屏幕大小和方向,而无需使用javascript。很明显,你需要确保网站设计得很好,这样用户就不需要放大了。如果你的网站是为移动设备优化的,这应该不是问题。

Please note: other non-safari mobile browsers may re-layout the page without setting the maximum-scale on the viewport. But this behavior is inconsistent and most developers seem to cater to apple devices even if the implementation is worse than other devices. Some other devices would maintain the zoom level and recenter the viewport when the orientation changes. But all devices are ok to fix the zoom level to 1.0.

请注意:其他非safari移动浏览器可能会重新布局页面,而不会在viewport上设置最大值。但这种行为是不一致的,大多数开发人员似乎是在迎合苹果设备,即使其实现比其他设备更糟糕。其他一些设备将保持缩放级别并在方向改变时重新输入viewport。但所有设备都可以将缩放级别调整到1.0。

#2


11  

2015 update

All the other answers are incorrect or outdated. Here's what works:

其他的答案都是不正确或过时的。的工作原理:

  window.addEventListener('orientationchange', function () {
    var originalBodyStyle = getComputedStyle(document.body).getPropertyValue('display');
    document.body.style.display='none';
    setTimeout(function () {
      document.body.style.display = originalBodyStyle;
    }, 10);
  });

The code listens to the orientationchange event and forces a re-flow of the body element by hiding it and showing it 10 milliseconds later. It does not depend on any <meta> tags or media queries.

该代码将侦听定向更改事件,并通过隐藏它并在10毫秒后显示它,从而强制执行主体元素的重新流。它不依赖于任何 标记或媒体查询。

Other answers suggested using media queries, but you already use them, since you said "It looks fine when it is refreshed".

其他回答建议使用媒体查询,但您已经使用了它们,因为您说过“刷新后看起来很好”。

Some other answers suggest using location.reload(). This is very inefficient, because it will reload the entire page, including images etc. Especially on mobile, you don't want to do that.

一些其他的答案建议使用locationreload()。这是非常低效的,因为它将重新加载整个页面,包括图像等。尤其是在移动设备上,您不希望这样做。

Yet other answers suggested adding <meta name="viewport" content="width=device-width, initial-scale=1.0"> or variations thereof. As of Safari 7, this no longer works. Here's a demo. To make sure you see how it doesn't work, start with the iPad in landscape mode, load the page, then rotate. Notice the page doesn't expand to full height, despite using flexbox all the way.

但是其他的答案建议添加 或其变体。从Safari 7开始,这就不再有效了。这是一个演示。为了确保你看到它是如何工作的,从iPad开始在横向模式,加载页面,然后旋转。请注意,尽管一直在使用flexbox,页面并没有扩展到全高度。

Compare that to this page, where we use the hide/show body technique in production.

与这个页面相比,我们在这个页面中使用了隐藏/显示身体技术。

#3


3  

Used a method that causes a repaint and a reflow in a single javascript stack frame. Not keen on viewport specific answers as it is often a requirement for accessibility to keep pinch zooming etc.

使用的方法导致在一个javascript堆栈框架中重新绘制和再流。不喜欢查看端口特定的答案,因为通常需要可访问性来保持缩放等等。

$(window).on('orientationchange', function() {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
}); 

Or non-jquery equivalent

或non-jquery等效

window.addEventListener('orientationchange', function () {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
});

#4


0  

I had a similar problem and this is how I fixed it with jQuery.

我遇到了类似的问题,这就是我如何用jQuery修复它的方法。

In my case the styles were not changing correctly for my <nav> element. I used a modified version of kidkaos77's code combined with $.get() to only load a certain part of the page:

在我的例子中,我的

$(window).bind("resize",function() {
    //on resize reload only nav & replace
    $.get("index.php" +  ' nav', function(data) {
        $("nav").replaceWith($(data).find("nav"));
    });
});

With this method you don't have to reload the entire page, but you would have to specify exactly which elements are being affected by the orientation change, which in your case it seems like you just need one div.

使用这个方法,您不必重载整个页面,但您必须确切地指定哪些元素受到方向更改的影响,在您的示例中,似乎您只需要一个div。

#5


-1  

Another option could be to add & remove CSS classes from your html elements (div, var, span, etc). This way you can modify only the elements that are giving you troubles and also you can adjust the content on non-mobile browsers if the user resize the browser window.

另一种选择是从html元素(div, var, span等)中添加和删除CSS类。通过这种方式,您可以只修改给您带来麻烦的元素,还可以调整非移动浏览器上的内容,如果用户调整浏览器窗口的大小。

Here is the Javascript/JQuery code you will need:

下面是您需要的Javascript/JQuery代码:

// Code to run when page has finished loading
$(function() {
    // Add CSS-class to body depending on device platform using user agent string
    // You can add more validations here and/or separate Android from iPhone or add more customized classes like "landscape_iPad", "landscape_iPhone", etc.
   // You can also validate browser types and add classes like "background_IE" or "background_Chrome", etc
    if ((navigator.userAgent.indexOf("iPad") != -1)) {
        $("#background").addClass("landscape");
    } else if ((navigator.userAgent.indexOf("Android") != -1) || (navigator.userAgent.indexOf("iPhone") != -1) || 
    (navigator.userAgent.indexOf("iPhone") != -1)) {
        $("body").addClass("iPhone");
    }

    // Get the initial orientation on iOS devices
    if (!isNaN(window.orientation)) {
        var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
        // Index php
        $("#background").addClass(orientation);
    } else {
        // Choose layout depending on viewport/window width
        var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
        // Index php
        $("#background").addClass(orientation);
    }

    // Bind orientationChange (or viewport/window size changes)
    if (window.onorientationchange != undefined) {
        window.onorientationchange = function() {
            var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
            // Index php
            $("#background").removeClass("portrait landscape").addClass(orientation);
        }
    } else {
        // Use landscape styling if it's wider than 980 pixels. 
        // This is for non mobile browsers, this way if the user resize the browser window, content will adjust too.
        $(window).bind('resize', function(){
            var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
            // Index php
            $("#background").removeClass("portrait landscape").addClass(orientation);
        });
    }
});

And here is the CSS class for the sample element "background":

下面是示例元素“background”的CSS类:

#background.portrait {
    position:absolute;
    top:0px;
    left:0px;
    width:768px;
    height:946px;
    z-index:0;
    background:url(background.png) top center no-repeat;
}
#background.landscape {
    position:absolute;
    top:10px;
    left:20px;
    width:1024px;
    height:724px;
    z-index:0;
    background:url(background_landscape.png) top center no-repeat;
}

This way you can customize the landscape and portrait behavior and you can add more clases like: "landscape_iPhone", "portrait_Android" or whatever you need to control the rendering of the page for each specific device.

通过这种方式,您可以自定义横向和纵向行为,并可以添加更多的clases,如“landscape - ape_iphone”、“portrait_Android”或任何您需要控制每个特定设备的页面呈现的东西。

Also, you don't need to reload the page, it will adjust it on the fly.

而且,你不需要重新加载页面,它会动态地调整它。

Hope it helps you or someone else =), this has enabled me to create web sites customized for each screen size, mobile brand or even browser type with the same HTML but different CSS classes.

希望它能帮助您或其他人=),这使我能够创建为每个屏幕大小、移动品牌甚至浏览器类型定制的web站点,使用相同的HTML但不同的CSS类。

#6


-1  

Try something like this:

试试这样:

$(function(){

    changeOrientation(window.orientation == 0 ? "portrait" : "landscape");

    $('body').bind('orientationchange',function(event){
        changeOrientation(event.orientation)
    });

    function changeOrientation(ori){
        $("#orientation").removeClass('portrait landscape');
        $("#orientation").addClass(ori);
    }     
});

#7


-1  

In my experience the best way is to have it like this

在我的经验中,最好的方法是这样做。

<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width /">
<meta name="apple-mobile-web-app-capable" content="yes"/>

Doing it like @BenSwayne in my experience does not rescale back to the initial scale when you change the orientation. Dont know why that is

按照我的经验,像@BenSwayne那样做并不会在你改变方向时回到最初的规模。不知道为什么

#8


-2  

$(window).bind('resize', function() { location.reload(); });

This code worked for me.

这段代码对我有用。

#1


23  

Assuming your CSS is already happily rendering on your various size mobile device screens, you need to define the viewport in the <head> of your template.

假设您的CSS已经在各种大小的移动设备屏幕上愉快地呈现,您需要在模板的中定义viewport。

Example, this sets the page width to be the device's screen width and an initial zoom of 100%. Initial zoom is applied at page load, but not when the orientation is changed.

例如,这将页面宽度设置为设备的屏幕宽度,初始放大为100%。初始变焦是在页面加载时应用的,但不会在方向改变时应用。

<meta name="viewport" content="width=device-width, initial-scale=1.0">

By adding a maximum-scale=1.0 parameter to the viewport you will force the iPad/iPhone to maintain the zoom level and re-layout the page on orientation change. The disadvantage of this is that it will disable zooming. However, the advantage is that you can make layout adjustments with media queries to present the content in a suitable fashion for the current orientation. You can read more about viewport here: Choosing a ViewPort

通过向viewport添加最大比例=1.0参数,您将迫使iPad/iPhone保持缩放级别,并在方向改变时重新布局页面。这样做的缺点是它会禁用缩放。但是,优点是您可以通过媒体查询进行布局调整,以适合当前方向的方式呈现内容。您可以在这里阅读更多关于viewport的内容:选择viewport

Now onto media queries. You should put media queries at the bottom of your CSS file and in the order of smallest width to largest width for screen widths. For example, taken from the Html5BoilerPlate CSS example:

现在媒体上查询。您应该将媒体查询置于您的CSS文件的底部,并以最小宽度的顺序将屏幕宽度设为最大宽度。例如,取自Html5BoilerPlate CSS示例:

@media only screen and (min-width: 480px) {
  /* Style adjustments for viewports 480px and over go here */

}

@media only screen and (min-width: 768px) {
  /* Style adjustments for viewports 768px and over go here */

}

So all your normal styles are above this and applied first, then if the screen is 480px or wider the next block of styles are applied, then if the screen is 768px or wider the last block of styles are applied.

所以你所有的正常样式都在上面,首先应用,如果屏幕是480px或者更宽,那么下一个样式块被应用,如果屏幕是768px或者更宽,最后一个样式块被应用。

By combining the fixed zoom level to 1.0 and the media-queries, you can make your site responsively resize to the screen size and orientation without javascript. Obviously you need to make sure the site is then well designed so users don't need zooming. If your site is optimized for mobile this shouldn't be a problem.

通过将固定的缩放级别结合到1.0和媒体查询,您可以使您的站点响应屏幕大小和方向,而无需使用javascript。很明显,你需要确保网站设计得很好,这样用户就不需要放大了。如果你的网站是为移动设备优化的,这应该不是问题。

Please note: other non-safari mobile browsers may re-layout the page without setting the maximum-scale on the viewport. But this behavior is inconsistent and most developers seem to cater to apple devices even if the implementation is worse than other devices. Some other devices would maintain the zoom level and recenter the viewport when the orientation changes. But all devices are ok to fix the zoom level to 1.0.

请注意:其他非safari移动浏览器可能会重新布局页面,而不会在viewport上设置最大值。但这种行为是不一致的,大多数开发人员似乎是在迎合苹果设备,即使其实现比其他设备更糟糕。其他一些设备将保持缩放级别并在方向改变时重新输入viewport。但所有设备都可以将缩放级别调整到1.0。

#2


11  

2015 update

All the other answers are incorrect or outdated. Here's what works:

其他的答案都是不正确或过时的。的工作原理:

  window.addEventListener('orientationchange', function () {
    var originalBodyStyle = getComputedStyle(document.body).getPropertyValue('display');
    document.body.style.display='none';
    setTimeout(function () {
      document.body.style.display = originalBodyStyle;
    }, 10);
  });

The code listens to the orientationchange event and forces a re-flow of the body element by hiding it and showing it 10 milliseconds later. It does not depend on any <meta> tags or media queries.

该代码将侦听定向更改事件,并通过隐藏它并在10毫秒后显示它,从而强制执行主体元素的重新流。它不依赖于任何 标记或媒体查询。

Other answers suggested using media queries, but you already use them, since you said "It looks fine when it is refreshed".

其他回答建议使用媒体查询,但您已经使用了它们,因为您说过“刷新后看起来很好”。

Some other answers suggest using location.reload(). This is very inefficient, because it will reload the entire page, including images etc. Especially on mobile, you don't want to do that.

一些其他的答案建议使用locationreload()。这是非常低效的,因为它将重新加载整个页面,包括图像等。尤其是在移动设备上,您不希望这样做。

Yet other answers suggested adding <meta name="viewport" content="width=device-width, initial-scale=1.0"> or variations thereof. As of Safari 7, this no longer works. Here's a demo. To make sure you see how it doesn't work, start with the iPad in landscape mode, load the page, then rotate. Notice the page doesn't expand to full height, despite using flexbox all the way.

但是其他的答案建议添加 或其变体。从Safari 7开始,这就不再有效了。这是一个演示。为了确保你看到它是如何工作的,从iPad开始在横向模式,加载页面,然后旋转。请注意,尽管一直在使用flexbox,页面并没有扩展到全高度。

Compare that to this page, where we use the hide/show body technique in production.

与这个页面相比,我们在这个页面中使用了隐藏/显示身体技术。

#3


3  

Used a method that causes a repaint and a reflow in a single javascript stack frame. Not keen on viewport specific answers as it is often a requirement for accessibility to keep pinch zooming etc.

使用的方法导致在一个javascript堆栈框架中重新绘制和再流。不喜欢查看端口特定的答案,因为通常需要可访问性来保持缩放等等。

$(window).on('orientationchange', function() {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
}); 

Or non-jquery equivalent

或non-jquery等效

window.addEventListener('orientationchange', function () {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
});

#4


0  

I had a similar problem and this is how I fixed it with jQuery.

我遇到了类似的问题,这就是我如何用jQuery修复它的方法。

In my case the styles were not changing correctly for my <nav> element. I used a modified version of kidkaos77's code combined with $.get() to only load a certain part of the page:

在我的例子中,我的

$(window).bind("resize",function() {
    //on resize reload only nav & replace
    $.get("index.php" +  ' nav', function(data) {
        $("nav").replaceWith($(data).find("nav"));
    });
});

With this method you don't have to reload the entire page, but you would have to specify exactly which elements are being affected by the orientation change, which in your case it seems like you just need one div.

使用这个方法,您不必重载整个页面,但您必须确切地指定哪些元素受到方向更改的影响,在您的示例中,似乎您只需要一个div。

#5


-1  

Another option could be to add & remove CSS classes from your html elements (div, var, span, etc). This way you can modify only the elements that are giving you troubles and also you can adjust the content on non-mobile browsers if the user resize the browser window.

另一种选择是从html元素(div, var, span等)中添加和删除CSS类。通过这种方式,您可以只修改给您带来麻烦的元素,还可以调整非移动浏览器上的内容,如果用户调整浏览器窗口的大小。

Here is the Javascript/JQuery code you will need:

下面是您需要的Javascript/JQuery代码:

// Code to run when page has finished loading
$(function() {
    // Add CSS-class to body depending on device platform using user agent string
    // You can add more validations here and/or separate Android from iPhone or add more customized classes like "landscape_iPad", "landscape_iPhone", etc.
   // You can also validate browser types and add classes like "background_IE" or "background_Chrome", etc
    if ((navigator.userAgent.indexOf("iPad") != -1)) {
        $("#background").addClass("landscape");
    } else if ((navigator.userAgent.indexOf("Android") != -1) || (navigator.userAgent.indexOf("iPhone") != -1) || 
    (navigator.userAgent.indexOf("iPhone") != -1)) {
        $("body").addClass("iPhone");
    }

    // Get the initial orientation on iOS devices
    if (!isNaN(window.orientation)) {
        var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
        // Index php
        $("#background").addClass(orientation);
    } else {
        // Choose layout depending on viewport/window width
        var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
        // Index php
        $("#background").addClass(orientation);
    }

    // Bind orientationChange (or viewport/window size changes)
    if (window.onorientationchange != undefined) {
        window.onorientationchange = function() {
            var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
            // Index php
            $("#background").removeClass("portrait landscape").addClass(orientation);
        }
    } else {
        // Use landscape styling if it's wider than 980 pixels. 
        // This is for non mobile browsers, this way if the user resize the browser window, content will adjust too.
        $(window).bind('resize', function(){
            var orientation = ($(window).width() < 980) ? "portrait" : "landscape";
            // Index php
            $("#background").removeClass("portrait landscape").addClass(orientation);
        });
    }
});

And here is the CSS class for the sample element "background":

下面是示例元素“background”的CSS类:

#background.portrait {
    position:absolute;
    top:0px;
    left:0px;
    width:768px;
    height:946px;
    z-index:0;
    background:url(background.png) top center no-repeat;
}
#background.landscape {
    position:absolute;
    top:10px;
    left:20px;
    width:1024px;
    height:724px;
    z-index:0;
    background:url(background_landscape.png) top center no-repeat;
}

This way you can customize the landscape and portrait behavior and you can add more clases like: "landscape_iPhone", "portrait_Android" or whatever you need to control the rendering of the page for each specific device.

通过这种方式,您可以自定义横向和纵向行为,并可以添加更多的clases,如“landscape - ape_iphone”、“portrait_Android”或任何您需要控制每个特定设备的页面呈现的东西。

Also, you don't need to reload the page, it will adjust it on the fly.

而且,你不需要重新加载页面,它会动态地调整它。

Hope it helps you or someone else =), this has enabled me to create web sites customized for each screen size, mobile brand or even browser type with the same HTML but different CSS classes.

希望它能帮助您或其他人=),这使我能够创建为每个屏幕大小、移动品牌甚至浏览器类型定制的web站点,使用相同的HTML但不同的CSS类。

#6


-1  

Try something like this:

试试这样:

$(function(){

    changeOrientation(window.orientation == 0 ? "portrait" : "landscape");

    $('body').bind('orientationchange',function(event){
        changeOrientation(event.orientation)
    });

    function changeOrientation(ori){
        $("#orientation").removeClass('portrait landscape');
        $("#orientation").addClass(ori);
    }     
});

#7


-1  

In my experience the best way is to have it like this

在我的经验中,最好的方法是这样做。

<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width /">
<meta name="apple-mobile-web-app-capable" content="yes"/>

Doing it like @BenSwayne in my experience does not rescale back to the initial scale when you change the orientation. Dont know why that is

按照我的经验,像@BenSwayne那样做并不会在你改变方向时回到最初的规模。不知道为什么

#8


-2  

$(window).bind('resize', function() { location.reload(); });

This code worked for me.

这段代码对我有用。