iOS Safari not scrolling to anchor in iframe

html, iframe, ios, mobile-safari

Solution

This is due to an iOS Safari bug whereby the iframe expands to the height of its content. You can verify this using Safari desktop debugger and running:

`document.querySelector('iframe').offsetHeight`

The solution is to reduce the height of the iframe body by placing your content into a `position: fixed` container and allowing it to scroll.

For example, place the contents of the body into a `<main>` tag and set the style as follows:

    <html>
     <head>
       <style>
          main {
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            padding: 10px;
            overflow-y: scroll;
            -webkit-overflow-scrolling: touch;
            z-index: 1;
          }
       </style>
     </head>
     <body>
       <main>
          <h1>Have some ipsum...</h1>
          <p>Lorem... (live example has much more here just to make the scrolling apparent)</p>
          <h1 style="color: red;">
            <a name="scrolltome" id="scrolltome">This is where I want to scroll</a>
          </h1>
          <p>
             Lorem...
          </p>
       </main>
     </body>
    </html>

This tells Safari the iframe body is the same height as the page that contains it, but its content is scrollable. Your anchors will now work.

Problem

I have an `HTML` page with an `iframe` whose contents I need to scroll to a certain location upon loading. My example works fine in most browsers except iOS Safari - which is the one I really need. It tends to work in iOS Safari on the first page load, but generally any refreshes after that presents the `iframe` content scrolled to the top. I've read about problems where redirects cause the `#anchorname` to be dropped, but that isn't what is going on in this case. The real `iframe` content and the main page are on different domains. I can influence the content of the `iframe`, but I don't have control over it. It is also used for other purposes, so I'd have limited ability to do anything custom that could interfere with that. Live link here: https://s3.amazonaws.com/ios-iframe-test/iframe_test.html Here is the parent content: ``` <!DOCTYPE html> <html> <head> <title>test</title> <meta content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0" name="viewport"> <style type="text/css"> #root { position: relative; } #wrapper { height: 300px; width: 300px; overflow-x: hidden; overflow-y: scroll; position: relative; -webkit-overflow-scrolling: touch; } iframe { width: 100%; height: 100%; } </style> </head> <body> <h1>Why won't this iframe scroll to where I want?</h1> <div id="root"> <div id="wrapper"> <iframe src="https://s3.amazonaws.com/ios-iframe-test/iframe_content.html#scrolltome"></iframe> </div> </div> </body> </html> ``` And here is the `iframe` content: ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <h1>Have some ipsum...</h1> <p> Lorem... (live example has much more here just to make the scrolling apparent) </p> <h1 style="color: red;"> <a name="scrolltome" id="scrolltome">This is where I want to scroll></a> </h1> <p> Lorem... </p> </html> ```

Original source