Can I change the viewport meta tag in mobile safari on the fly?
Asked Answered
A

4

102

I have an AJAX app built for mobile Safari browser that needs to display different types of content.

For some content, I need user-scalable=1 and for other ones, I need user-scalable=0.

Is there a way to modify the value of the content attribute without refreshing the page?

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
Andi answered 27/8, 2010 at 22:48 Comment(0)
U
158

I realize this is a little old, but, yes it can be done. Some javascript to get you started:

viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0');

Just change the parts you need and Mobile Safari will respect the new settings.

Update:

If you don't already have the meta viewport tag in the source, you can append it directly with something like this:

var metaTag=document.createElement('meta');
metaTag.name = "viewport"
metaTag.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
document.getElementsByTagName('head')[0].appendChild(metaTag);

Or if you're using jQuery:

$('head').append('<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">');
Ube answered 4/11, 2010 at 8:27 Comment(12)
Nice! Unfortunately, I can't seem to get it to work. My situation is a bit different: I'm working with a site that has a 980px width. The content goes right to the edge of the design, so on an iPad, it looks awkward. I thought I'd set the viewport to a width of 1020px to allow for a 20px margin on either side... but no luck: viewport = document.querySelector("meta[name=viewport]"); viewport.setAttribute('content', 'width=1020'); (Just for some context: I'm putting this in a somewhat locked down Drupal instance... so I don't have direct access to the head area and need to use Javascript)Lailaibach
Grumble grumble... I think I know why this isn't working for me. The above snippet would rewrite the value of the width of the meta viewport. That meta doesn't exist yet... can't change it if it's not there, right? Any way that I can add that meta with Javascript? (Damn this locked down Drupal instance! I think I'm screwed!)Lailaibach
This should be easy enough. Just write it in directly. If you're using jQuery it would be something like this: $('head').append('<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">'); or, without jQuery: document.getElementsByTagName('head')[0].appendChild( ... );Ube
For the content attributes, mobile safari's web inspector is throwing an error on the semicolons. This appears to be more valid: viewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0');Batfowl
Hi, I have actioned this on the fly jQuery: if(window.orientation == "0") { $("meta[name=viewport]").attr('content','width=device-width, initial-scale=0.5, maximum-scale=1.0, user-scalable=1'); } but the zoom does not update when the page is loaded in portrait mode. Does anyone know why? The initial scale was previously 0.3.Bullard
Great, this is exactly what I was looking for to dinamically add the target-densitydpi=device-dpi meta tag on small screens. Thanks!!Oblong
appendChild doesn't want a string: "Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'"Chartist
@Chartist You're right, appendChild expects a node, not a string. Updated. Thanks.Ube
Related Question: how could the javascript look like if you want to modify the viewport definition only on mobile devices, but NOT on tablets nor desktops? According the list (mydevice.io/devices/#sortSmartphones) we could use var w = screen.width; or something like that?Doddered
@basZero: You could use the user agent to check which device the script is running on before running the above code, but in general I think that's a bad idea. Try to generalize based on device features (or screen size if you must), not actual devices. For example, you can detect if the device supports touch events, etc. (i.e., with modernizr). Depends on what you're trying to do.Ube
@Ube yes, my goal was actually to be device agnostic, I don't want to care about user agents... Currently I have a workaround which works quite good. In my media query I set the breakpoint to max X px, and then in the javascript I test, whether the longer edge is below X px, if so, I change the viewport. This resulted in a near perfect solution.Doddered
From the beginning of 2017 Google marks pages, where there is no viewport tag in html, as "Your page is not mobile-friendly.", even when there is javascript what writes this and the page goes through Google "Mobile friendly test" without problems. To keep Google happy, always give a viewport meta tag in html. You can modify this later.Brave
L
8

in your <head>

<meta id="viewport"
      name="viewport"
      content="width=1024, height=768, initial-scale=0, minimum-scale=0.25" />

somewhere in your javascript

document.getElementById("viewport").setAttribute("content",
      "initial-scale=0.5; maximum-scale=1.0; user-scalable=0;");

... but good luck with tweaking it for your device, fiddling for hours... and i'm still not there!

source

Lamprey answered 5/5, 2011 at 18:58 Comment(0)
C
6

This has been answered for the most part, but I will expand...

Step 1

My goal was to enable zoom at certain times, and disable it at others.

// enable pinch zoom
var $viewport = $('head meta[name="viewport"]');    
$viewport.attr('content', 'width=device-width, initial-scale=1, maximum-scale=4');

// ...later...

// disable pinch zoom
$viewport.attr('content', 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no');

Step 2

The viewport tag would update, but pinch zoom was still active!! I had to find a way to get the page to pick up the changes...

It's a hack solution, but toggling the opacity of body did the trick. I'm sure there are other ways to accomplish this, but here's what worked for me.

// after updating viewport tag, force the page to pick up changes           
document.body.style.opacity = .9999;
setTimeout(function(){
    document.body.style.opacity = 1;
}, 1);

Step 3

My problem was mostly solved at this point, but not quite. I needed to know the current zoom level of the page so I could resize some elements to fit on the page (think of map markers).

// check zoom level during user interaction, or on animation frame
var currentZoom = $document.width() / window.innerWidth;

I hope this helps somebody. I spent several hours banging my mouse before finding a solution.

Claim answered 27/4, 2016 at 15:43 Comment(1)
This saved my life, but I have a little problem with it: assuming you displaying a picture in an overlay div at 100% and zoom into it on a mobile device, you will zoom using the native browser zoom implementation which usually simply scales the visible area without any re-rendering of the original file. On the other side, if I remove "width=device-width" for disabled zoom state, it renders the picture fine while zooming but I loose my last page position when the 100% div is closed...Coplanar
G
0

Try this

<script type="text/javascript">
    var scale=(screen.width/1080);
    document.write('<meta name="viewport" content="width=device-width, initial-scale='+scale+'">');
</script>
Graphite answered 24/1 at 21:47 Comment(2)
Welcome to StackOverflow! This is a very old question, and it already has accepted answers (albeit from the distant past). Can you please elaborate on your answer, and why do you think it's fitting? Does it apply to modern browsers? If not, is there a more modern approach?Olnek
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Seitz

© 2022 - 2024 — McMap. All rights reserved.