在方向改变时重新渲染网页的最佳方法是什么?

发布于 2024-12-12 01:07:11 字数 576 浏览 0 评论 0原文

我有一个流畅的 CSS 布局,当我改变方向时,它在 iPhone 上渲染得很糟糕。 (刷新后看起来不错)。

我使用下面的代码来刷新方向更改的页面,效果很好 - 只是感觉这样做有点不对。有没有什么方法可以实现这一点而无需重新加载整个页面?这是一个移动网站,我真的不想强迫用户加载页面两次。

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

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

编辑:

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

我的宽度为 100%,背景图像右对齐。 当我将方向从纵向更改为横向时,主体宽度保持在纵向模式下呈现的方式,反之亦然。从横向到纵向,这更是一个问题,因为页面太宽,并且似乎渲染了两次图像。

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

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:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

携君以终年 2024-12-19 01:07:12

假设您的 CSS 已经在各种尺寸的移动设备屏幕上顺利呈现,您需要在 中定义视口。你的模板。

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

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

通过向视口添加 Maximum-scale=1.0 参数,您将强制 iPad/iPhone 保持缩放级别并在方向更改时重新布局页面。这样做的缺点是它将禁用缩放。但是,优点是您可以使用媒体查询进行布局调整,以适合当前方向的方式呈现内容。您可以在此处阅读有关视口的更多信息:选择 ViewPort< /a>

现在进入媒体查询。您应该将媒体查询放在 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 */

}

因此,所有正常样式都在此之上并首先应用,然后如果屏幕为 480px 或更宽,则应用下一个样式块,如果屏幕为 768px 或更宽,则应用最后一个样式块。

通过将固定缩放级别设置为 1.0 和媒体查询相结合,您可以使您的网站响应式地调整大小以适应屏幕尺寸和方向,而无需使用 JavaScript。显然,您需要确保网站设计良好,以便用户不需要缩放。如果您的网站针对移动设备进行了优化,那么这应该不是问题。

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

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.

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.

<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

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:

@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.

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.

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.

骑趴 2024-12-19 01:07:12

2015 更新

所有其他答案都不正确或已过时。这是有效的:

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

该代码监听 orientationchange 事件并强制重新执行通过隐藏 body 元素并在 10 毫秒后显示它来控制其流程。它不依赖于任何标签或媒体查询。

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

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

还有其他答案建议添加 或其变体。从 Safari 7 开始,这不再有效。这是一个演示。为了确保您明白它是如何不起作用的,请从 iPad 的横向模式开始,加载页面,然后旋转。请注意,尽管一直使用 Flexbox,但页面并未扩展到完整高度。

此页面进行比较,我们在生产中使用隐藏/显示正文技术。

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.

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.

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.

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

纸短情长 2024-12-19 01:07:12

使用了在单个 JavaScript 堆栈帧中导致重绘和回流的方法。不热衷于视口特定的答案,因为通常需要可访问性来保持捏缩放等。

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

或非 jquery 等效项

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

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.

$(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

window.addEventListener('orientationchange', function () {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
});
冷月断魂刀 2024-12-19 01:07:12

根据我的经验,最好的方法是像这样做,

<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"/>

当你改变方向时,像@BenSwayne那样做不会重新缩放回初始比例。不知道为什么

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

虐人心 2024-12-19 01:07:12

我有一个类似的问题,这就是我用 jQuery 修复它的方法。

就我而言,我的

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

使用此方法,您不必重新加载整个页面,但您会准确指定哪些元素受到方向变化的影响,在您的情况下,您似乎只需要一个 div。

I had a similar problem and this is how I fixed it with 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.

鹤舞 2024-12-19 01:07:12

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

这是您需要的 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);
        });
    }
});

这是示例元素“背景”的 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;
}

这样您就可以自定义横向和纵向行为,并且可以添加更多类,例如:“landscape_iPhone”、“portrait_Android”或者您需要控制每个特定设备的页面呈现的任何内容。

此外,您不需要重新加载页面,它会即时调整。

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

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.

Here is the Javascript/JQuery code you will need:

// 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.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.

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.

孤独岁月 2024-12-19 01:07:12

尝试这样的事情:

$(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);
    }     
});

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);
    }     
});
黑色毁心梦 2024-12-19 01:07:12
$(window).bind('resize', function() { location.reload(); });

这段代码对我有用。

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

This code worked for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文