DrDoom
DrDoom

Reputation: 325

How to accurately detect if mobile phone via screen.availWidth (and not tablet, laptop etc)

I'm working on a gallery. I would like to show portrait oriented picutres to mobile phone users and landscape oriented pictures to everyone else (tablets, laptops etc).

What I currently have is:

var maxW = window.screen.availWidth * window.devicePixelRatio;

if (maxW <= 767){
    galleryImages = portraitImages;
}else{
    galleryImages = landscapeImages;
};

var portraitImages = [  'https://static.photocdn.pt/images/articles/2016-7/landscape-comp/iStock_000058793850_Medium.jpg',
 'https://keyassets.timeincuk.net/inspirewp/live/wp-content/uploads/sites/12/2016/05/AP_Portrait_Landscapes_Stu_Meech-5.jpg',
 'https://keyassets.timeincuk.net/inspirewp/live/wp-content/uploads/sites/12/2016/05/AP_Portrait_Landscapes_Stu_Meech-16.jpg', 
'https://static.photocdn.pt/images/articles/2016-7/landscape-comp/iStock_000062009934_Medium.jpg']

var landscapeImages = ['https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjM3Njd9&w=1000&q=80', 
'https://images.unsplash.com/photo-1506260408121-e353d10b87c7?ixlib=rb-1.2.1&w=1000&q=80', 
'https://www.tom-archer.com/wp-content/uploads/2017/03/landscape-photography-tom-archer-4.jpg', 
'https://s.yimg.com/uu/api/res/1.2/DdytqdFTgtQuxVrHLDdmjQ--~B/aD03MTY7dz0xMDgwO3NtPTE7YXBwaWQ9eXRhY2h5b24-/https://media-mbst-pub-ue1.s3.amazonaws.com/creatr-uploaded-images/2019-11/7b5b5330-112b-11ea-a77f-7c019be7ecae', 
'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/hbx030117buzz14-1550595844.jpg']

Now, lets say, the smallest "resolution" for tablets is 768x1024. When I go to Dev Tools, input 768x1024 in resolution and call alert("MaxW: " + maxW + ",\nMaxH : " + maxH); I get MaxW: 1536, MaxH: 2048 which is caused by the device-pixel ratio.

So, my question, how would I calculate the max screen size for a mobile phone, taking into consideration the device-pixel ratio.

I can't very well say "show picture gallery if max-device width is 2048", since some computer monitors have worse resolution.

I hope I'm getting my meaning across. If I can provide any additional information / explenation, let me know.

Thank you for the help.

Upvotes: 0

Views: 1041

Answers (2)

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20954

With the innerWidth and innerHeight properties of the window you can calculate the width and height of your screen in pixels. On my 2560x1600 screen it returns the dimensions 1280x800, accounting for the device-pixel ratio.

function getWindowDimensions() {
  const width = window.innerWidth;
  const height = window.innerHeight;
  const ratio = (width / height) * 100;
  return { width, height, ratio };
}

const { width } = getWindowDimensions();

if (width < 768) {
    galleryImages = portraitImages;
} else {
    galleryImages = landscapeImages;
}

Also, instead of selecting your images in JavaScript you could also use the <picture> element and use the srcset attribute. With the <picture> element you can add media queries for showing images based on the condition in that query. This would give you the ability to add both your image sets to the HTML and the browser then decides which image to show based on your query.

<picture>
  <source media="(max-width: 767px)" srcset="portrait.jpg">
  <source media="(min-width: 768px)" srcset="landscape.jpg">
  <img src="landscape.jpg" alt="Your image description">
</picture>

I'd suggest that you create pairs for your images to add the to the picture element. For example in an array of objects with the keys portrait and landscape. Loop over the array and create a <picture> element for each of those pairs with the <source> tags specified to the media query and its corresponding srcset value.

const images = [
  {
    portrait: './portrait-image-1.jpg',
    landscape: './landscape-image-1.jpg'
  },
  {
    portrait: './portrait-image-2.jpg',
    landscape: './landscape-image-2.jpg'
  },
  {
    portrait: './portrait-image-3.jpg',
    landscape: './landscape-image-3.jpg'
  }
];

for (const { portrait, landscape } of images) {

  const picture = document.createElement('picture');
  const sourcePortrait = document.createElement('source');
  const sourceLandscape = document.createElement('source');
  const image = document.createElement('img');

  sourcePortrait.media = '(max-width: 767px)';
  sourcePortrait.srcset = portrait;
  sourceLandscape.media = '(min-width: 768px)';
  sourceLandscape.srcset = landscape;
  image.src = landscape;

  picture.append(sourcePortrait, sourceLandscape, image);
  document.body.append(picture);

}

Otherwise to detect the device that someone is using, like a mobile phone, then check the userAgent for keywords that are recognized as phones. For detecting devices this is good, but for responsive web development, not so much as many other devices and new browser could be added and could break in the future.

Upvotes: 2

RAC
RAC

Reputation: 156

Why are you assuming that portrait=phone and landscape=tablet? I could (and probably would for a gallery) be using my phone in landscape.

Rather than making assumptions about the type of device, check for what the screen is actually doing now, ie is the screen landscape or portrait, and then configure your software accordingly.

Then it will work no matter what device and no matter what orientation.

Upvotes: -1

Related Questions