62

Is it possible to detect on my page, for example using Javascript, when user visit it using mobile device in portrait mode, and stop orientation changing when user rotate its phone to landscape? There is game on my page, optimized for portrait display only and I don't want it in landscape.

qqryq
  • 1,814
  • 3
  • 18
  • 20
  • I disagree that it is always bad to "take over a users device like that". With modern phones being so sensor rich, we are able to write applications that depend on phone orientation and movement, and it is a show-stopper when the screen goes flipping around when taking advantage of these sensor capabilities! It is way past time to fix this issue. – lonce Aug 13 '14 at 15:44
  • Mobile browsers can usually detect orientation and right itself. The advantage to letting the device do this for you (aside from less code) is that it also puts all of the browser chrome and system UI in the right place for the user. If the user chooses to disable autorotation, they probably have good reason (e.g. when browsing while laying on their side). The proposed functionality in this question would interfere with that with no advantages. – Lèse majesté Apr 30 '15 at 04:59
  • This is not an answer you'll probably like, but i would find that behavior pretty annoying on a mobile device. Cater for your users. Would they like to be able to see the screen in landscape mode? If so, then design for that scenario. – MrBliz Aug 17 '10 at 10:41
  • 9
    ok, but i made mobile game on my page in html5&JS, and it is impossible to see whole screen when it is rotate to landscape. – qqryq Aug 17 '10 at 10:44
  • agreed - as a web designer its your job to make your website accessible for all users. – Thomas Clayson Aug 17 '10 at 10:44
  • 3
    @MichalBe -Instead of blocking the rotation, why not detect it instead, and then display a message to your users that the game is only viewable in portrait mode? – MrBliz Aug 17 '10 at 10:51
  • This same logic is not applied to apps. Why do you think the browser should be different? – gman Mar 30 '14 at 23:47
  • Well to be honest i find it pretty annoying in apps as well. – MrBliz Apr 08 '14 at 09:09
  • 58
    @MrBliz - Ugh. So many holier-than-though comments here from people who think every website is some kind of blog. Hello? This is 2015. Responsive design is very cool, but it's inappropriate for the thousands of web apps and games that are designed for a fixed orientation. It is absolutely not the developer's "responsibility" to make a complex HTML5 game or application work in all orientations. – Bangkokian May 11 '15 at 08:37
  • 1
    Example of when the user **wants** to lock orientation: if the website is designed to work with a joystick that attaches to the screen (simulating touch). For example, using a phone to control a remote control car. You don't want the screen rotating, thus the touch areas for the joystick moving from were the joystick is positioned, no matter which of the 4 orientations the device believes is wanted. The site can always provide the user with the option to "unlock/unlock" the device orientation change, so in that scenario, an API to lock orientation would give the very best user experience. – Jodes Jan 05 '17 at 09:58
  • @Thomas Clayson As a developer, it's your job to execute your vision and put users in the correct lane to get the highest quality of the experience you envision. If a user doesn't like it, the user can occupy their time with anything other than your product. I think this is a perfectly valid case in which orientation lock is acceptable. – user2985898 Jan 29 '18 at 06:10

9 Answers9

45

New API's are developing (and are currently available)!

screen.orientation.lock();   // webkit only

and

screen.lockOrientation("orientation");

Where "orientation" can be any of the following:

portrait-primary - It represents the orientation of the screen when it is in its primary portrait mode. A screen is considered in its primary portrait mode if the device is held in its normal position and that position is in portrait, or if the normal position of the device is in landscape and the device held turned by 90° clockwise. The normal position is device dependant.

portrait-secondary - It represents the orientation of the screen when it is in its secondary portrait mode. A screen is considered in its secondary portrait mode if the device is held 180° from its normal position and that position is in portrait, or if the normal position of the device is in landscape and the device held is turned by 90° anticlockwise. The normal position is device dependant.

landscape-primary - It represents the orientation of the screen when it is in its primary landscape mode. A screen is considered in its primary landscape mode if the device is held in its normal position and that position is in landscape, or if the normal position of the device is in portrait and the device held is turned by 90° clockwise. The normal position is device dependant.

landscape-secondary - It represents the orientation of the screen when it is in its secondary landscape mode. A screen is considered in its secondary landscape mode if the device held is 180° from its normal position and that position is in landscape, or if the normal position of the device is in portrait and the device held is turned by 90° anticlockwise. The normal position is device dependant.

portrait - It represents both portrait-primary and portrait-secondary.

landscape - It represents both landscape-primary and landscape-secondary.

default - It represents either portrait-primary and landscape-primary depends on natural orientation of devices. For example, if the panel resolution is 1280800, default will make it landscape, if the resolution is 8001280, default will make it to portrait.

Mozilla recommends adding a lockOrientationUniversal to screen to make it more cross-browser compatible.

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

Go here for more info (deprecated API): https://developer.mozilla.org/en-US/docs/Web/API/Screen/lockOrientation


Modern API docs in MDN is here: https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation/lock

sarkiroka
  • 1,485
  • 20
  • 28
DemiImp
  • 968
  • 8
  • 18
22

In JavaScript-enabled browsers it should be easy to determine if the screen is in landscape or portrait mode and compensate using CSS. It may be helpful to give users the option to disable this or at least warn them that device rotation will not work properly.

Edit

The easiest way to detect the orientation of the browser is to check the width of the browser versus the height of the browser. This also has the advantage that you'll know if the game is being played on a device that is naturally oriented in landscape mode (as some mobile devices like the PSP are). This makes more sense than trying to disable device rotation.

Edit 2

Daz has shown how you can detect device orientation, but detecting orientation is only half of the solution. If want to reverse the automatic orientation change, you'll need to rotate everything either 90° or 270°/-90°, e.g.

$(window).bind('orientationchange resize', function(event){
  if (event.orientation) {
    if (event.orientation == 'landscape') {
      if (window.rotation == 90) {
        rotate(this, -90);
      } else {
        rotate(this, 90);
      }
    }
  }
});

function rotate(el, degs) {
  iedegs = degs/90;
  if (iedegs < 0) iedegs += 4;
  transform = 'rotate('+degs+'deg)';
  iefilter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+iedegs+')';
  styles = {
    transform: transform,
    '-webkit-transform': transform,
    '-moz-transform': transform,
    '-o-transform': transform,
    filter: iefilter,
    '-ms-filter': iefilter
  };
  $(el).css(styles);
}

Note: if you want to rotate in IE by an arbitrary angle (for other purposes), you'll need to use matrix transform, e.g.

rads = degs * Math.PI / 180;
m11 = m22 = Math.cos(rads);
m21 = Math.sin(rads);
m12 = -m21;
iefilter = "progid:DXImageTransform.Microsoft.Matrix("
  + "M11 = " + m11 + ", "
  + "M12 = " + m12 + ", "
  + "M21 = " + m21 + ", "
  + "M22 = " + m22 + ", sizingMethod = 'auto expand')";
styles['filter'] = styles['-ms-filter'] = iefilter;

—or use CSS Sandpaper. Also, this applies the rotation style to the window object, which I've never actually tested and don't know if works or not. You may need to apply the style to a document element instead.

Anyway, I would still recommend simply displaying a message that asks the user to play the game in portrait mode.

Michael
  • 9,639
  • 3
  • 64
  • 69
Lèse majesté
  • 7,923
  • 2
  • 33
  • 44
  • 2
    You missed a close bracket in `$(window).bind` function and have an extra bracket in the `rotation()` function – Raptor Jan 08 '14 at 03:20
  • " window.rotation == 90 " is it a machine specific code ? – N.K Aug 22 '17 at 05:06
  • @N.K I think the value is in fact different for different devices. And, in fact, it's not even called `window.rotation`. All I can find references to are `window.orientation`. I either made a typo, or the available API was different 7 years ago. Will have to mess around with this and revise the code when I get the free time. – Lèse majesté Aug 22 '17 at 11:55
  • I have a React App. I want to keep it in portrait view on mobile devices. Is it possible to get a straight answer on this? – MadHatter Sep 05 '21 at 12:28
17

seems weird that no one proposed the CSS media query solution:

@media screen and (orientation: portrait) {
  ...
}

and the option to use a specific style sheet:

<link rel="stylesheet" type="text/css" href="css/style_p.css" media="screen and (orientation: portrait)">

MDN: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries#orientation

fphilipe
  • 9,739
  • 1
  • 40
  • 52
Facundo Colombier
  • 3,487
  • 1
  • 34
  • 40
7

Simple Javascript code to make mobile browser display either in portrait or landscape..

(Even though you have to enter html code twice in the two DIVs (one for each mode), arguably this will load faster than using javascript to change the stylesheet...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Mobile Device</title>
<script type="text/javascript">
// Detect whether device supports orientationchange event, otherwise fall back to
// the resize event.
var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    if(window.orientation==0)
    {
      document.getElementById('portrait').style.display = '';
      document.getElementById('landscape').style.display = 'none';
    }
    else if(window.orientation==90)
    {
      document.getElementById('portrait').style.display = 'none';
      document.getElementById('landscape').style.display = '';
    }
}, false);
</script>
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no" />
</head>
<body>
<div id="portrait" style="width:100%;height:100%;font-size:20px;">Portrait</div>
<div id="landscape" style="width:100%;height:100%;font-size:20px;">Landscape</div>

<script type="text/javascript">
if(window.orientation==0)
{
  document.getElementById('portrait').style.display = '';
  document.getElementById('landscape').style.display = 'none';
}
else if(window.orientation==90)
{
  document.getElementById('portrait').style.display = 'none';
  document.getElementById('landscape').style.display = '';
}
</script>
</body>
</html>

Tested and works on Android HTC Sense and Apple iPad.

5

With the new CSS3 features, you could rotate the page the opposite orientation that they rotated. Sorry, no IE7- support. :(.

var rotate = 0 - window.orientation;
setAttribute("transform:rotate("+rotate+"deg);-ms-transform:rotate("+rotate+"deg);-webkit-transform:rotate("+rotate+"deg)", "style");
Qvcool
  • 460
  • 3
  • 10
1

This solution worked for me, which just rotates the entire page 90 degrees when it's in landscape (effectively locking the screen in portrait). I couldn't go with some of the other options here, because I needed to support Safari.

@media screen and (min-width: 320px) and (max-width: 767px) and (orientation: landscape) {
  html {
    transform: rotate(-90deg);
    transform-origin: left top;
    width: 100vh;
    overflow-x: hidden;
    position: absolute;
    top: 100%;
    left: 0;
  }
}

Found it here: https://css-tricks.com/snippets/css/orientation-lock/

David
  • 1,620
  • 3
  • 20
  • 39
0

You could use the screenSize.width and screenSize.height properties and detect when the width > height and then handle that situation, either by letting the user know or by adjusting your screen accordingly.

But the best solution is what @Doozer1979 says... Why would you override what the user prefers?

NinjaCat
  • 9,974
  • 9
  • 44
  • 64
  • 3
    User here: a lot of the time when my phone rotates from portrait to landscape it's unexpected and unwanted. I could probably come up with a list of sites where I never want to use landscape modes, and if those sites locked out rotation it would be a positive for me. – user1172763 Jun 21 '17 at 14:17
0

You can detect the orientation change, but I don't think you can prevent it.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Browsera
  • 199
  • 1
  • 3
0

#rotate-device {
    width: 100%;
    height: 100%;
    position: fixed;
    z-index: 9999;
    top: 0;
    left: 0;
    background-color: #000;
    background-image: url(/path to img/rotate.png);
    background-size: 100px 100px;
    background-position: center;
    background-repeat: no-repeat;
    display: none;
}

@media only screen and (max-device-width: 667px) and (min-device-width: 320px) and (orientation: landscape){
 #rotate-device {
  display: block;
 }
}
<div id="rotate-device"></div>
bhairava
  • 11
  • 3