Search code examples
javascripthtmlcssresponsive-designlandscape-portrait

Make mobile view stick to Portrait mode while on landscape with +90 degrees


The issue:

  • I want the visitors to always see my site in portrait mode
  • I have gone through many links and have a working solution when mobile is turned to the landscape mode with -90 degrees
  • The issue I am facing is when mobile is turned +90 degrees. I cannot scroll the content at all when it's rotated +90 degrees. How do I make it so that the content is still scrollable even when it's rotated +90 degrees?

To see the issue:

  • Run the code snippet below (in full page) on any mobile turned to landscape mode (or on Developer Tools with mobile mode on while on landscape orientation)
  • You will see the issue I get with rotating by +90 degrees
  • To see the working version (-90 degrees), change the rotator-right class to rotator in my JS code below

The code I have:

(function() {

  function myFunction() {
    var wSH = window.screen.height;
    var wI = window.innerHeight;
    var dBC = document.body.clientHeight;
    var wO = window.orientation;
    document.getElementById("wSH").textContent = wSH;
    document.getElementById("wI").textContent = wI;
    document.getElementById("wO").textContent = wO;
    document.getElementById("dBC").textContent = dBC;

    var bodyDocument = document.body;
    var iosDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) &&
      !window.MSStream;
    if (window.matchMedia('(orientation: landscape)').matches &&
      (
        (window.screen.height < 425) /* for android */ ||
        (iosDevice && window.innerHeight < 425) /* for iOS */
      )
    ) {
      bodyDocument.classList.add('rotator-right');
    } else {
      bodyDocument.classList.remove('rotator-right');
    }

    document.getElementsByTagName('body')[0].style.display = 'none';
    setTimeout(function() {
      document.getElementsByTagName('body')[0].style.display = 'block';
    }, 200);

    setTimeout(function() {
      //console.log('inside rotator-right, with document.body.scrollHeight :', document.body.scrollHeight);
    }, 100);

  }
  window.addEventListener("resize", myFunction);
  myFunction();


})();
@media screen and (orientation:landscape) {
  .rotator {
    transform: scale(0.95) rotate(270deg);
    transform-origin: top right;
    position: relative;
    top: 0px;
    left: -100vh;
    height: 100vw;
    width: 100vh;
    overflow-y: hidden;
  }
  .rotator-right {
    transform: scale(0.93) rotate(90deg);
    transform-origin: top right;
    position: relative;
    width: 100vh;
    top: 50vw;
    left: 42vw;
    overflow-y: hidden;
  }
}
<body id='body'>
  <div class='container'>
    <p>Click the button to display this frame's height and width.</p>
    <p id="demo"></p>
    <p>window.scroll.height :
      <span id="wSH"></span>
    </p>
    <p>window.innerHeight :
      <span id="wI"></span>
    </p>
    <p>document.body.clientHeight :
      <span id="dBC"></span>
    </p>
    <p>window.orientation :
      <span id="wO"></span>
    </p>
    <button>Try it</button>
    <br />
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac magna nec nisi accumsan blandit. Quisque feugiat commodo sapien quis pharetra. Sed elit justo, volutpat ac eleifend eu, aliquet in orci. Proin fermentum purus nec ante molestie sodales.
      Cras malesuada nunc purus, id iaculis magna suscipit nec. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam pulvinar eu lectus eu sollicitudin. Integer mauris sem, posuere vel est a, eleifend pulvinar
      lectus. Duis sapien velit, tristique imperdiet purus nec, scelerisque porta massa. Proin commodo faucibus purus, in volutpat lectus maximus sed. Suspendisse potenti.
    </p>
    <p>
      Curabitur maximus elementum nibh, at rhoncus dolor auctor in. Donec ultrices enim ac est sollicitudin euismod. Mauris tempor eget dolor sit amet consequat. Suspendisse volutpat efficitur eros, vitae imperdiet tellus. Vestibulum aliquam nunc eget ante
      porta gravida. Aliquam cursus fermentum accumsan. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur condimentum tempus mollis. Suspendisse luctus posuere sapien, ut pharetra lacus eleifend ut.
    </p>
    <p>
      Morbi eu finibus quam. Morbi pharetra mollis diam id hendrerit. Etiam rhoncus, dolor quis hendrerit consectetur, est urna efficitur erat, in vestibulum nunc erat eget sapien. Curabitur ut massa semper, feugiat quam eu, rhoncus tortor. Ut quis convallis
      diam, et euismod sem. Cras volutpat libero id nulla varius, at egestas elit consectetur. Nulla posuere neque risus, eu mollis dolor vehicula ut. Donec a ipsum eu justo malesuada lacinia in porta nibh. Aenean risus erat, molestie elementum eros vitae,
      tempor porta lacus. Fusce et bibendum est. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas vel est ac justo vehicula commodo eget eget magna. Etiam vitae aliquet eros, rutrum porta ligula. Nulla at
      fringilla lacus, sed commodo justo. Aenean imperdiet maximus tortor sed volutpat. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </p>
    <p>
      Curabitur finibus dictum condimentum. Nulla scelerisque dui elit, sit amet lobortis tellus mollis ut. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque ac ex sapien. Maecenas ac pellentesque nisi, id mattis
      ligula. Sed lacinia feugiat ultricies. Sed ultrices facilisis efficitur. Vestibulum quis libero nec quam convallis mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam lacus neque, sodales sit amet facilisis eu, viverra vel nulla.
      Nullam nec dapibus metus. Aenean pulvinar molestie dolor. In hac habitasse platea dictumst.
    </p>
    <p>
      Nunc commodo magna id nisl ultricies porta. Nulla eget purus et mi malesuada hendrerit. Aenean euismod mauris placerat est dapibus, venenatis posuere lacus fermentum. Cras purus lorem, tristique non semper sit amet, pulvinar a ligula. Vestibulum ante
      ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse ultricies ultrices posuere. Nulla eu pellentesque ante. Curabitur consequat odio eget purus vestibulum, nec vestibulum lacus mollis. Etiam cursus, ipsum vehicula
      auctor rhoncus, diam massa fermentum nibh, ac tincidunt neque arcu et risus.</p>
    <hr />
    <p>--------- This is the last line ---------</p>
  </div>
</body>


Solution

  • What went wrong?

    I figured out what was wrong. When you're rotating to the left by 90 degrees (-90 degrees) with a transform-origin: top right, the box extends the containing html to the right, thus causing it to be scrollable to the right.

    However, when you're rotating to the right by 90 degrees (+90 degrees) with a transform-origin: top left, the box extends the containing html to the left and this does not cause it to be scrollable to the left. There has been a discussion about this particular scenario here at SO. Do try reading it.


    Workaround

    Knowing that, we can instead manipulate the transform-origin to bottom left so that the box rotates in such a way that it extends the containing html to the right and causes the scrollbar to appear. However, doing this, we need to adjust it so that the position is correct. To do that, we can use another transform function, which is translate. I changed your .rotator and .rotator-right classes to utilize translateX and translateY before rotating so that the position after rotation is correct.

    (I recommend playing with transform function. Try making one item that applies rotate before translate and one item that applies translate before rotate. The results are different! You'll learn something new.)


    I advise trying to adjust transform and overflow-y values to see what I mean by the box extending the containing html to the right and left on both .rotator and .rotator-right class.

    Here's a working solution. I added configured your CSS part on .rotator-right and .rotator. You're not using left or top anymore to adjust the position, you're giving that control to transform function wholly. Try running it on full-screen and enable mobile mode on your browser.

    function myFunction() {
      var wSH = window.screen.height
      var wI = window.innerHeight
      var dBC = document.body.clientHeight
      var wO = window.screen.orientation.type
      document.getElementById("wSH").textContent = wSH
      document.getElementById("wI").textContent = wI
      document.getElementById("wO").textContent = wO
      document.getElementById("dBC").textContent = dBC
    
      var bodyDocument = document.body;
      var iosDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) &&
        !window.MSStream;
      if (window.matchMedia('(orientation: landscape)').matches &&
        (
          (window.screen.height < 425) /* for android */ ||
          (iosDevice && window.innerHeight < 425) /* for iOS */
        )
      ) {
        bodyDocument.classList.add('rotator-right')
      } else {
        bodyDocument.classList.remove('rotator-right')
      }
    
      document.getElementsByTagName('body')[0].style.display = 'none';
      setTimeout(function() {
        document.getElementsByTagName('body')[0].style.display = 'block';
     if (bodyDocument.classList.contains('rotator-right')) window.scrollTo(bodyDocument.getBoundingClientRect().width, 0)
      }, 200);
    }
    window.addEventListener("resize", myFunction);
    myFunction();
    * {
      box-sizing: border-box;
    }
    
    body,
    html {
      margin: 0;
    }
    
    p {
      margin: 0;
      padding: 16px 0;
    }
    
    @media screen and (orientation:landscape) {
      .rotator {    
        transform-origin: top right;
        width: 100vh;
        
        /* Try playing with these properties to see the transformation */
        /* Use scale at the very end of transform if needed */
        transform: translateX(-100%) rotate(-90deg);
        transition: all .5s ease;
        overflow-y: hidden;
      }
      .rotator-right {
        transform-origin: bottom left;
        width: 100vh;
        
        /* Try playing with these properties to see the transformation */
        /* Use scale at the very end of transform if needed */
        transform: translateY(-100%) rotate(90deg) scale(0.85);
        transition: all .5s ease;
        overflow-y: hidden;
      }
    }
    <body id='body'>
      <div class='container'>
        <p>Click the button to display this frame's height and width.</p>
        <p id="demo"></p>
        <p>window.scroll.height :
          <span id="wSH"></span>
        </p>
        <p>window.innerHeight :
          <span id="wI"></span>
        </p>
        <p>document.body.clientHeight :
          <span id="dBC"></span>
        </p>
        <p>window.orientation :
          <span id="wO"></span>
        </p>
        <button>Try it</button>
        <br />
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac magna nec nisi accumsan blandit. Quisque feugiat commodo sapien quis pharetra. Sed elit justo, volutpat ac eleifend eu, aliquet in orci. Proin fermentum purus nec ante molestie sodales.
          Cras malesuada nunc purus, id iaculis magna suscipit nec. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam pulvinar eu lectus eu sollicitudin. Integer mauris sem, posuere vel est a, eleifend pulvinar
          lectus. Duis sapien velit, tristique imperdiet purus nec, scelerisque porta massa. Proin commodo faucibus purus, in volutpat lectus maximus sed. Suspendisse potenti.
        </p>
        <p>
          Curabitur maximus elementum nibh, at rhoncus dolor auctor in. Donec ultrices enim ac est sollicitudin euismod. Mauris tempor eget dolor sit amet consequat. Suspendisse volutpat efficitur eros, vitae imperdiet tellus. Vestibulum aliquam nunc eget ante
          porta gravida. Aliquam cursus fermentum accumsan. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur condimentum tempus mollis. Suspendisse luctus posuere sapien, ut pharetra lacus eleifend ut.
        </p>
        <p>
          Morbi eu finibus quam. Morbi pharetra mollis diam id hendrerit. Etiam rhoncus, dolor quis hendrerit consectetur, est urna efficitur erat, in vestibulum nunc erat eget sapien. Curabitur ut massa semper, feugiat quam eu, rhoncus tortor. Ut quis convallis
          diam, et euismod sem. Cras volutpat libero id nulla varius, at egestas elit consectetur. Nulla posuere neque risus, eu mollis dolor vehicula ut. Donec a ipsum eu justo malesuada lacinia in porta nibh. Aenean risus erat, molestie elementum eros vitae,
          tempor porta lacus. Fusce et bibendum est. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas vel est ac justo vehicula commodo eget eget magna. Etiam vitae aliquet eros, rutrum porta ligula. Nulla at
          fringilla lacus, sed commodo justo. Aenean imperdiet maximus tortor sed volutpat. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        </p>
        <p>
          Curabitur finibus dictum condimentum. Nulla scelerisque dui elit, sit amet lobortis tellus mollis ut. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque ac ex sapien. Maecenas ac pellentesque nisi, id mattis
          ligula. Sed lacinia feugiat ultricies. Sed ultrices facilisis efficitur. Vestibulum quis libero nec quam convallis mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam lacus neque, sodales sit amet facilisis eu, viverra vel nulla.
          Nullam nec dapibus metus. Aenean pulvinar molestie dolor. In hac habitasse platea dictumst.
        </p>
        <p>
          Nunc commodo magna id nisl ultricies porta. Nulla eget purus et mi malesuada hendrerit. Aenean euismod mauris placerat est dapibus, venenatis posuere lacus fermentum. Cras purus lorem, tristique non semper sit amet, pulvinar a ligula. Vestibulum ante
          ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse ultricies ultrices posuere. Nulla eu pellentesque ante. Curabitur consequat odio eget purus vestibulum, nec vestibulum lacus mollis. Etiam cursus, ipsum vehicula
          auctor rhoncus, diam massa fermentum nibh, ac tincidunt neque arcu et risus.</p>
        <hr />
        <p>--------- This is the last line ---------</p>
      </div>
    </body>

    One unrelated concern of mine: you used this code to detect if a device is iOS: /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;. I can't seem to find a proper documentation on that so it may be inaccurate code. Furthermore, from MDN about user agent sniffing:

    It's worth re-iterating: it's very rarely a good idea to use user agent sniffing. You can almost always find a better, more broadly compatible way to solve your problem!

    Also, it seems like Safari (iOS) also supports window.screen.height.