iPhone Safari Web App opens links in new window
Solution 1
I found JavaScript solution in iWebKit framework:
var a=document.getElementsByTagName("a");
for(var i=0;i<a.length;i++)
{
a[i].onclick=function()
{
window.location=this.getAttribute("href");
return false
}
}
Solution 2
The other solutions here either don't account for external links (that you probably want to open externally in Safari) or don't account for relative links (without the domain in them).
The html5 mobile-boilerplate project links to this gist which has a good discussion on the topic: https://gist.github.com/1042026
Here's the final code they came up with:
<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>
Solution 3
If you are using jQuery, you can do:
$("a").click(function (event) {
event.preventDefault();
window.location = $(this).attr("href");
});
Solution 4
This is working for me on iOS 6.1 and with Bootstrap JS links (i.e dropdown menus etc)
$(document).ready(function(){
if (("standalone" in window.navigator) && window.navigator.standalone) {
// For iOS Apps
$('a').on('click', function(e){
e.preventDefault();
var new_location = $(this).attr('href');
if (new_location != undefined && new_location.substr(0, 1) != '#' && $(this).attr('data-method') == undefined){
window.location = new_location;
}
});
}
});
Solution 5
This is an old question and many of the solutions here are using javascript. Since then, iOS 11.3 has been released and you can now use the scope member. The scope member is a URL like "/"
where all paths under that scope will not open a new page.
The scope member is a string that represents the navigation scope of this web application's application context.
Here is my example:
{
"name": "Test",
"short_name": "Test",
"lang": "en-US",
"start_url": "/",
"scope": "/",
...
}
You can also read more about it here. I also recommend using the generator which will provide this functionality.
If you specify the scope, everything works as expected similar to Android, destinations out of the scope will open in Safari — with a back button (the small one in the status bar) to your PWA.
Related videos on Youtube
Pavel Linkesch
Frontend engineer engineering frontend at Maker. JavaScript, ReasonML, React, web components.
Updated on August 29, 2020Comments
-
Pavel Linkesch almost 4 years
I have problem with web after adding icon to Home Screen. If the web is launched from Home Screen, all links will open in new window in Safari (and lose full screen functionality). How can I prevent it? I couldn't find any help, only the same unanswered question.
-
Amir Raminfar about 6 yearsYou can now use the
scope
parameter inmanifest.json
. See my answer for more details. I have tested it in iOS 11.3 and it does work. -
Chris Haines about 6 yearsTo reiterate, for anyone struggling with iOS 11.3 opening Safari, please see @AmirRaminfar's answer here: stackoverflow.com/a/49604315/32055
-
-
Alex over 13 yearsThis was a GODSEND! Thank you so much!
-
ajcw almost 13 yearsPlease explain why .live() might be better?
-
msaspence almost 13 yearslive will bind the event to all links including those that don't exist yet, click will only bind to ones that currently exist
-
Steve almost 13 yearsthanks! lifesaver. I just spent hours trying to figure out why safari was loading all the time.
-
Oskar Austegard almost 13 yearsTo state the obvious and make this explicit: iOS treats links in Web Apps as something that should be opened in Safari, and javascript location changes as an in-app action that is allowed to saty in the web-app. The code above works because it prevents the default link behavior, replacing it with a js nav call.
-
Clay over 12 yearsFor Rails 3.1 apps, this seems to break traditional delete links and redirects them to the show action instead.
-
Max888 over 12 yearsIs there an example of the opposite? Forcing an iPhone web app to open a page in Safari eventhough it's a javascript location change?
-
cmplieger over 12 years@Pavel thank you for mentioning iwebkit :). Helps to get some traffic :D
-
Matt White over 12 yearsI found this script didn't work for iOS5. This solution did work though: stackoverflow.com/a/8173161/449330
-
Jonathan about 12 yearsThis works great except for one page, the "Contact us" page for our company. Instead of showing the page, it opens the application "Maps" and pinpoints our office. What could be causing this, and how can we fix it?
-
rmarscher about 12 years@Jonathan I'm not sure. Does it not happen if you remove this script? Maybe post a link to your site? Or open a new question, that might be better.
-
Jonathan about 12 years@rmarscher This only happens when running the code you provided and not without it. I'm a web developer myself and I don't understand why it would handle the link this way. I don't have a page URL because it's currently not running the code so you won't notice it. Also, it affects the regular Safari as well, and not only standalone. Thanks for your answer!
-
Ian about 12 yearsGood addition to the above solutions. Needed a domain check to keep people from opening outside sites in the app. Also, works on iOS 5.
-
drusepth about 12 yearsIf you're doing javascript-y things and have href="#", you might want the following modification if this script is breaking their functionality: thunked.org/p/view/pub/uccr0k3sr
-
Chim Kan about 12 yearsThanks a lot! This is the only code that worked for iOS5 w/ Twitter Bootstrap. It doesn't work on production though.
-
daformat about 12 yearsMmm not so sure why it would not work in production but I think it's something else. Do let me know!
-
user3167101 about 12 years
[].forEach.call(document.links, function(link) { link.addEventListener("click", function(event) { event.preventDefault(); window.location = this.href; }) });
-
Lukasz Korzybski almost 12 yearsworks on iOS 5 for me too. The problem sometimes might be with the cache. While testing different approaches I was unable to force iOS to invalidate its cache and retrieve new version of JS files (Safari did pick up the changes but no more after adding app to Home Screen). Changing port of my dev server helped. If you have max-age=0 set (or equivalent) then this probably won't affect you.
-
Fenton over 11 years+1 from me - used
this.href
rather than casting to a jQuery object, but thanks for this answer. Works on iOS6. -
sradforth over 11 yearsThis should be the accepted answer and worked a charm on my iPad1 fullscreen client made with PHPRunner by placing the code in the header. Not sure why it's so obfuscated as it seems quite concise bit of code that could be written legibly without much BW overhead... that's just being picky though and generally really want to say thanks.
-
Sean over 11 yearsThis breaks Bootstrappy things such as href="#" links that are used by js functions
-
Sean over 11 yearsLuckily my workmate had some code lying around. i will add an answer
-
Tom Davies over 11 years.live() is deprecated as of jQuery 1.7, and removed as of 1.9. Use $(document).on('click', 'a', function(){...}) instead.
-
pingu about 11 yearsDoes this have any side effects?
-
saulob about 10 yearsPerfect, you saved me :)
-
Trolley about 10 years+1. This actually checks whether you're using a webapp before fixing the links.
-
Joel Murphy over 9 yearsWorks in iOS 8.0.2! Thanks
-
nematoth almost 9 years@sean I have another webapp running in an iPad which is using an image map as href and this code doesn't work..It works fine for all other links. Any ideas how to make this code work with image maps? I have tried copying the whole chunk and replacing
$('a').on('click'
, function(e){` with$('area').on('click'
, function(e){` but that doesn't seem to work either. Any ideas? -
paulalexandru over 8 yearsThis works perfectly if you use it like this. If I tried to include this code from a js file it did not worked anymore. (just wanted to tell everybody no to do this because i waisted a lot of time finding out this)
-
user1788736 over 8 years@Pavel Linkesch May I know how should run the above code once user click on a hyperlink ?
-
Jerrybibo almost 8 yearsFor some reason I think this is the easiest to comprehend.
-
cjk over 7 yearsIn case you already have click functions defined on
a
withhref="#"
then you can be more specific on the jquery selector, e.g.$('a[href!="#"]')
-
bhollis about 6 yearsUnfortunately, I don't believe that you can include other websites (such as OAuth logins on another domain) in the scope.