34

Is it possible to avoid transition to landscape view in Safari for iOS when the device is rotated?

iOS Safari has the "orentationchange" event, I tried to intercept it and disable the default behavior, like this:

<html>
<head>
<script type="text/javascript">
function changeOrientation(event) {
    alert("Rotate");
    event.preventDefault();
}
</script>
</head>
<body onorientationchange="changeOrientation(event);">
PAGE CONTENT
</body>
</html>

but when testing the page on my iPhone, when I rotate the device the alert is shown, but the view switch to landscape. It seems that event.preventDefault() does not stops the rotation.

Is there a way to block this behavior?

Davide Gualano
  • 12,813
  • 9
  • 44
  • 65
  • 1
    Related: http://stackoverflow.com/questions/1207008/how-do-i-lock-the-orientation-to-portrait-mode-in-a-iphone-web-application – xdhmoore Sep 04 '13 at 20:13
  • 1
    Read the question linked by @xdhmoore. It is very worthwhile in addition to this one. – Boaz Sep 09 '14 at 08:23

10 Answers10

58

Jonathan Snook has a work around to this problem. In his slides here, he shows how to (sort of) lock to portrait (see slide 54 and 55).

The JS code from those slides:

window.addEventListener('orientationchange', function () {
    if (window.orientation == -90) {
        document.getElementById('orient').className = 'orientright';
    }
    if (window.orientation == 90) {
        document.getElementById('orient').className = 'orientleft';
    }
    if (window.orientation == 0) {
        document.getElementById('orient').className = '';
    }
}, true);

and the CSS:

.orientleft #shell {
    -webkit-transform: rotate(-90deg);
    -webkit-transform-origin:160px 160px;
}

.orientright #shell {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin:230px 230px;
} 

I tried to get this working for landscape on the iPhone, but it never looked 100% correct. I came close with the following jQueryian code, however. This would be within the onready function. Also note: this was within a "saved to homescreen" context, and I think that altered the position of the tranform-origin.

$(window).bind('orientationchange', function(e, onready){
   if(onready){
       $(document.body).addClass('portrait-onready');
   }
   if (Math.abs(window.orientation) != 90){
       $(document.body).addClass('portrait');
   } 
   else {
       $(document.body).removeClass('portrait').removeClass('portrait-onready');
   }
});
$(window).trigger('orientationchange', true); // fire the orientation change event at the start, to make sure 

And the CSS:

.portrait {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: 200px 190px;
}
.portrait-onready {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: 165px 150px;
}

Hope that helps someone get close to the desired result...

Boris Smus
  • 8,220
  • 2
  • 36
  • 33
fisherwebdev
  • 12,658
  • 4
  • 28
  • 27
29

There is no way to force a particular orientation in Mobile Safari; it'll always autorotate when the user rotates their device.

Perhaps you can display something for unsupported orientations informing the user that the orientations aren't supported, and that they need to rotate the device back in order to use your web app.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
6

While you cannot prevent orientation change from taking effect you can emulate no change as stated in other answers.

First detect device orientation or reorientation and, using JavaScript, add a class name to your wrapping element (in this example I use the body tag).

function deviceOrientation() {
  var body = document.body;
  body.classList = '';
  switch(window.orientation) {
    case 90:
      body.classList.add('rotation90');
      break;
    case -90:
      body.classList.add('rotation-90');
      break;
    default:
      body.classList.add('portrait');
      break;
  }
}
window.addEventListener('orientationchange', deviceOrientation);
deviceOrientation();

Then if the device is landscape, use CSS to set the body width to the viewport height and the body height to the viewport width. And let’s set the transform origin while we’re at it.

@media screen and (orientation: landscape) {
  body {
    width: 100vh;
    height: 100vw;
    transform-origin: 0 0;
  }
}

Now, reorient the body element and slide (translate) it into position.

body.rotation-90 {
  transform: rotate(90deg) translateY(-100%);
}
body.rotation90 {
  transform: rotate(-90deg) translateX(-100%);
}
Reggie Pinkham
  • 11,985
  • 4
  • 38
  • 36
5

A spec to implement this functionality has been proposed.

Also, see this Chromium bug for additional information (still unclear whether it will be implemented in WebKit or Chromium).

Boris Smus
  • 8,220
  • 2
  • 36
  • 33
3

Maybe in a new future...

As for May 2015,

there is an experimental functionality that does that. But it only works on Firefox 18+, IE11+, and Chrome 38+.

However, it does not work on Opera or Safari yet.

https://developer.mozilla.org/en-US/docs/Web/API/Screen/lockOrientation#Browser_compatibility

Here is the current code for the compatible browsers:

var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation;

lockOrientation("landscape-primary");
Fabio Nolasco
  • 7,122
  • 6
  • 35
  • 32
3

The following solution seems working for me on iPhone4, 5, 6, and 6+ as of June 2016.

<script>
  /**
   * we are locking mobile devices orientation to portrait mode only
   */
  var devWidth, devHeight;
  window.addEventListener('load', function() {
    devWidth  = screen.width;
    devHeight = screen.height;
  });
  window.addEventListener('orientationchange', function () {
    if (devWidth < 768 && (window.orientation === 90 || window.orientation == -90)) {
      document.body.style.width = devWidth + 'px';
      document.body.style.height = devHeight + 'px';
      document.body.style.transform = 'rotate(90deg)';
      document.body.style.transformOrigin = ''+(devHeight/2)+'px '+(devHeight/2)+'px';
    } else {
      document.body.removeAttribute('style');
    }
  }, true);
</script>
allenhwkim
  • 27,270
  • 18
  • 89
  • 122
1

I think for our case where we need to provide a consistent view of the data we are displaying on the screen for medical surveys, rotation of the device's screen cannot be allowed. We design the application to work in portrait. So the best solution for use is to either lock it, which can't be done via the browser, or display an error/message indicating the application can't be used until the orientation is fixed.

0

I test this way work for me:

@media (orientation: portrait) {
  body {
    transform: rotate(-90deg);
  }
}
Behnam
  • 6,244
  • 1
  • 39
  • 36
0

Haven't tested this on an iPhone yet but you can try

screen.orientation.lock('portrait');
screen.orientation.unlock();

More info at MDN

Whip
  • 1,891
  • 22
  • 43
-6

If it is possible (which I don't believe it is), then I'd strongly advise against it. Users hate being forced into viewing pages in a particular way. What if they're using their iphone in a dock and can't stand it in landscape mode without undocking it, or what if they prefer the landscape version of the keyboard because the keys are bigger?

If your design requires a particular orientation then you might want to rethink your design.

GordonM
  • 31,179
  • 15
  • 87
  • 129
  • 2
    The webapp I'm building is targeting users walking on foot around the city, so I was thinking that the default portrait view could be the more natural way to experience it. I'll have to think about different scenarios, thanks for pointing this to me. – Davide Gualano Mar 14 '11 at 13:20
  • 13
    If your app uses deviceorientation events for example, you wouldn't want it to autorotate when the user moves the device too far in one direction, for a game that would get super annoying. – Adam M-W Jul 16 '11 at 01:21
  • 9
    these kinds of comments are so arrogant. most non-nerd users only use these 'custom view' options because the web page they are looking at has horrible usability and layout or tiny font etc... simply stating users want flexibility is just not very helpful. a meta tag addition to prevent auto-rotating content is very much warranted - apps can do it... – tim Sep 25 '12 at 20:12
  • 4
    If you want the face of the phone to look like a physical object like a playing card, orientation changes are irrelevant and distracting. To restate the above, If your design requires a particular orientation, you may have stumbled across a novel use case, which may require different technology to implement. – Dean Radcliffe Jun 02 '13 at 14:31
  • 2
    Another legit use case I had was making a demo site that would get thrown away, so we didn't want to spend the time working on a fully responsive site, but we wanted the demo to look good to our clients on their iPhones. Also, not a big fan of answers that say "don't do it", without also attempting to answer the OP's question of how, and showing some respect to the OP. – xdhmoore Sep 08 '15 at 16:54