Link to home
Start Free TrialLog in
Avatar of egoselfaxis
egoselfaxis

asked on

Detecting the viewport width using PHP in a custom WordPress theme?

I've been researching this topic online for a couple of hours now, and it appears that there is no reliable way to detect the screen width in a WordPress theme using PHP (ie: wp_is_mobile() is apparently now regarded as completely unreliable and has been rendered obsolete).    

I'm already aware of the fact that I can use CSS media queries to hide and display different elements based on the width of the viewport.  The problem with this, however, is that it requires that I duplicate certain elements (ie: search boxes, navigation menus, etc) .. which results in a slightly larger page weight as well as duplicate ID attributes, ... and hence invalid HTML that doesn't validate.  So I feel that this technique isn't ideal.

I'm also aware of the existence of WordPress plugins that detect the user agent, and that allow you to place similar looking conditional logic in your theme files. However, the research I've done suggest that the detecting of the user agent is also very unreliable, as it can easily be spoofed .. and it complicates development besides, since you can't just re-size your desktop browser to see the viewport based layout adjustments (you have to test using actual mobile devices).

The reason I'm asking is because I'm trying to adapt a custom design for a WordPress theme so that it displays a specific and very different layout on mobile, and it seems that the best way that I'd be able to accomplish this is by somehow detecting the width of the current viewport and to serve up different HTML using some kind of conditional logic:

if ($viewport-width <= 992 ) {
   echo '<h1>Mobile</h1>';
} else {
   echo '<h1>Desktop</h1>;
}

Open in new window


Is it really still impossible to achieve something like this using PHP?  If not, .. then how might I accomplish something like this?

Thanks,
- Yvan
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

Detecting the viewport is going to be something to do on the front end. This means using javascript or media queries. You are close though. You mentioned, "CSS media queries to hide and display different elements based on the width of the viewport.  The problem with this, however, is that it requires that I duplicate certain elements.... ... duplicate ID attributes.."

You never really want to use ID's for style. That should be left to the class.  

You could do something like this and use media queries to show/hide.
<h2 id="test1" class="showMobile hideDesktop">Mobile Content</h2>
<h2 id="test2" class="showDesktop hideMobile>Desktop Content</h2>

Open in new window

However, you have a point about adding multiple heading tags for what will really be one.  Instead, you can use javascript to detect the width https://developer.mozilla.org/en-US/docs/Web/API/window/innerWidth and just use
<h2 id="test1" >Default Content</h2>

Open in new window

and use your javascript to place the content inside the tag.

With that said, some themes in WP are better then others for dealing with this. There are themes that use bootstrap for instance or builders such as elementor https://docs.elementor.com/article/68-mobile-editing or beaver builder https://www.wpbeaverbuilder.com/build-responsive-website/ that will make this function easier.
ASKER CERTIFIED SOLUTION
Avatar of Terry Woods
Terry Woods
Flag of New Zealand image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Here is a CSS trick you can use.
CSS
h1 span:after {
  content: "Mobile"
}
@media screen and (min-width: 768px) {
  h1 span:after {
     content: "Desktop";
  }
}

Open in new window

HTML
<h1><span></span></h1>

Open in new window


What we are doing here is using an empty <h1> with an empty <span> with CSS to set the content ::after the span. This allows us to change the content based on a media query.
You can see it working here
Avatar of egoselfaxis
egoselfaxis

ASKER

Scott - I don't really have control over the duplicate ID attributes. WordPress is the one assigning those, and the mere fact that I'd have to duplicate the single, dynamically generated WordPress menu is what would result in the duplicates.

Julian - I see how what you're suggesting would work well for situations where I just want to output text-based content.  But in my case, I'd need to output different large blocks of HTML, so I don't think using content would work in my situation.  

I might be out of luck in this situation.  Or are there any other suggestions, perhaps?

- Yvan
I don't see what is wrong with Scotts suggestion.
echo <<< HTML
 <div class="hide-desktop">
   Uber MOBILE content here
</div>
<div class="hide-mobile">
   Uber DESKTOP content here
</div>
HTML;

Open in new window

CSS
.hide-mobile {
   display: none;
}
@media screen and (min-width: 992px) {
   .hide-mobile {
      display: initial!important;
   }
   .hide-desktop {
       display: none!important;
   }
}

Open in new window

Working sample here
What theme and plug ins are you using?
I'm using the Understrap theme development framework, and have created custom child theme using it.  The header and footer are custom template files (ie: header.php / footer.php), ... and the innards of the site will be created using WPBakery plugin.

https://understrap.com/

https://wpbakery.com/

- yg
...custom design for a WordPress theme ... that it displays a specific and very different layout on mobile,....
There are a couple of ways to go about this. One is detecting the device and the other is creating a responsive site.

There was a time when detecting the device was more readily used. Ask anybody that used a tablet how good that experience was when their device was detected as a mobile phone and it will not be good. This method does still exist and I think wix uses this method.

Most of us here I believe are using responsive sites.  Making a page responsive his harder to create because you are marking up your page for two or more major breakpoints (media queries). Using a framework like bootstrap or foundation makes the process a lot easier once you wrap your head around everything.  For the most part, you are creating rows of content and each row may have multiple columns. As the screen gets smaller, some of those columns may convert to another row or disappear.  Using one of the mentioned frameworks, it is a matter of adding one or multiple classes to an element.

The theme you are using is built with the basics that includes bootstrap. But it is meant for making custom templates. When you use this in WP, all you should have to enter is the main text.  When you pair this with a builder like WP Bakery, you are adding more 'weight' to your theme than needed because WP Bakery already has responsive properties that are similar to Bootstrap but not the same. Depending on what you are doing, you may be fine with just using the underscores theme and just use WP Bakery for your responsive items.
https://wpbakery.com/video-academy/add-row-column-wpbakery-page-builder-wordpress/
https://wpbakery.com/video-academy/responsive-column-control-width-offset-param-usage-explained/
https://wpbakery.com/video-academy/control-elements-different-devices-responsive-column-controls/
https://wpbakery.com/video-academy/check-responsive-design-wpbakery-page-builder-wordpress/
https://wpbakery.com/video-academy/control-responsiveness-wpbakery-page-builder-wordpress/
https://wpbakery.com/video-academy/control-elements-different-devices-responsive-column-controls/

It looks like what you want to do is already in WP Bakery (https://www.wpbeaverbuilder.com/ and https://elementor.com/ work in a very similar fashion).  I have some sites I elementor and I will confess it was not easy at first to allow the tools built in to do the work where I know I could have just coded it on my own.

If you do want to display specific content for a specific device, there is a plug in https://wordpress.org/plugins/wonderplugin-conditional-display/ and if you look at the code it uses $_SERVER['HTTP_USER_AGENT']. On your own, you can create a test page with
echo $_SERVER['HTTP_USER_AGENT'];
and see for yourself what you get using different browsers and devices. While that can be spoofed, most (probably almost all) are not going to be doing this. You may have home made scrapers that spoof a user agent and if that is what you are trying to get rid of, I found a honypot was the best method.
I ended up convincing the designer to modify the mobile design slightly, which allowed me to avoid having to duplicate the navigation menu (which was my greatest concern).  You can see my updated work in progress here:

http://dev.movingpicture.com/

Still -- thanks for your help guys.

Cheers,
- Yvan