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

110,463

Solution 1

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">');

Solution 2

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

Solution 3

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.

Share:
110,463

Related videos on Youtube

Pepper
Author by

Pepper

Web developer and Creator of Feedingo

Updated on May 13, 2020

Comments

  • Pepper
    Pepper about 4 years

    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;" />
    
  • Sam
    Sam over 13 years
    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)
  • Sam
    Sam over 13 years
    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!)
  • markquezada
    markquezada over 13 years
    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( ... );
  • jfroom
    jfroom over 11 years
    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');
  • daniel blythe
    daniel blythe almost 11 years
    Hi, I have actioned this on the fly jQuery: if(window.orientation == "0") { $("meta[name=viewport]").attr('content','width=device-widt‌​h, 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.
  • andreszs
    andreszs over 9 years
    Great, this is exactly what I was looking for to dinamically add the target-densitydpi=device-dpi meta tag on small screens. Thanks!!
  • the_nuts
    the_nuts about 9 years
    appendChild doesn't want a string: "Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'"
  • markquezada
    markquezada about 9 years
    @the_nuts You're right, appendChild expects a node, not a string. Updated. Thanks.
  • basZero
    basZero almost 9 years
    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?
  • markquezada
    markquezada almost 9 years
    @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.
  • basZero
    basZero almost 9 years
    @markquezada 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.
  • Rauli Rajande
    Rauli Rajande over 7 years
    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.
  • Stefan Müller
    Stefan Müller over 7 years
    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...