3

Is is possible to change the layout on orientation change reliably and cross browser only using CSS/media queries? I don't think it is even in the latest browsers, is it?

Looking at the many questions with people trying to reliably determine portrait and landscape orientation cross browser with CSS only and device-height and device-width being deprecated I think I am better advised to do this with JavaScript, right?

Similar to this question I am trying to change the layout of the navigation according to portrait and landscape orientation.

Portrait

Portrait

Landscape

Landscape

Here is my approach with JavaScript and VergeJS (because it reliably detects viewport height and width), following that I would apply classes to the li elements to position them as desired checking if the body has either the portrait or landscape class assigned and then checking for the viewport height when in landscape orientation.

// Cross browser portrait landscape detection

// Get viewport width and height values
// http://stackoverflow.com/q/40672125/1010918
function getVergeValues(){
  viewportWidth  = verge.viewportW()
  viewportHeight = verge.viewportH()
  console.log('viewportWidth = '+viewportWidth);
  console.log('viewportHeight = '+viewportHeight);
};
getVergeValues();
window.addEventListener('resize', getVergeValues);

// http://pioul.fr/cross-device-cross-browser-portrait-landscape-detection
function portraitLandscape(){
  screenOrientation = (viewportWidth > viewportHeight)? 90 : 0;
  console.log('screenOrientation = '+screenOrientation);
  if (screenOrientation == 0) {
    body.classList.add('portrait');
    body.classList.remove('landscape');
  }
  else if (screenOrientation == 90) {
    body.classList.remove('portrait');
    body.classList.add('landscape');
  }
};
portraitLandscape();
window.addEventListener('resize', portraitLandscape);

The CSS/SCSS would look something like this.

// Landscape layout for navigation on mobile
ul{
  li{
// depending on number of li elements I would also
// have to change the width values, assigning a grid of some sort.
// again I assume this can ONLY be done with JS reliably??
    width: 33.3333333333%; 
    display: inline-block;
    float: left;
    a{
      border-right: 1px solid black;
    }
  }
  li:last-child a {
    border-right: none;
  }
}

// Portrait layout for navigation on mobile
ul {
  padding: 0;
  li {
    list-style: none;
    display: block;
    margin: 0;
    float: none;
    width: 100%;    
    a {
      display: block;      
    }
  }
}

Why all this?
The navigation is fixed and top:0 and upon tap/click on the menu button the li elements slide down, these are also fixed.

I want to avoid that in landscape orientation li elements are not reachable because they stretch beyond the viewport height. Note the number of li elements also varies so is not set and because they are all fixed one could possibly never reach them in landscape orientation if there are many of them. I don't want the user to have to turn the device to be able to see all li elements and entirely leave the choice of how the site is browsed to the user.

As an alternative with much less code and possibly much easier to do, should I just position the navigation and li elements static if the viewport height in landscape orientation is less than then height of the navigation including all li elements?

Yes, I am sort of and very kindly not only asking if this can be done in CSS only but also asking your if the approach with either A) making a grid for the li elements and keeping them fixedor B) positioning the navigation and li elements static if, there are many of them, is preferred.

lowtechsun
  • 1,915
  • 5
  • 27
  • 55
  • Here is the [UX](https://ux.stackexchange.com/questions/107462/navigation-layout-vertical-or-horizontal-in-landscape-orientation-of-mobile-devi) part of this. – lowtechsun Apr 26 '17 at 22:56

1 Answers1

0

CSS media query's can also detect landscape or portrait orientation without the need for the JavaScript overhead.

@media only screen and (orientation: landscape) {
    .class-name {
        declaration: value;
    }
}    

@media only screen and (orientation: portrait) {
    .class-name {
        declaration: value;
    }
}

Using the media queries you will write a lot less code and the browser will do the leg work to re-render your page when the orientation changes.

Jamie Clark
  • 252
  • 1
  • 13
  • I don't think [this](https://jsfiddle.net/5rvL0jfk/) would work because of [this](http://pioul.fr/cross-device-cross-browser-portrait-landscape-detection). Unfortunately mobile devices have `portrait` and `landscape` assigned per vendor/make instead of per specification I believe. **Or** are you saying any browser does actually calculate the orientation given per MDN for orientation: _Indicates whether the viewport is in landscape (the display is wider than it is tall) or portrait (the display is square or taller than it is wide) mode._ ? – lowtechsun Apr 26 '17 at 14:19