14

我在 webkit 的移动版本中遇到了一个问题(特别是 iOS 5.1.1 上的 Webkit 534.46 作为移动 Safari,现在是 iOS 版 Chrome),这在我见过的任何桌面浏览器上都没有发生。(即下面的演示应该在 webkit 的移动版本上查看。)

这是这个问题的一个活生生的例子。CSS 的核心非常简单。它在页面左侧放置一个字母索引:

#index {
    left:0; margin:0; padding:0; position:fixed; top:0; width:3em;
}

当元素固定在主体顶部上方时,就会出现此问题。它完全能够与之交互,直到滚动发生变化,然后它停止接受输入。如果我(手动)摇动滚动甚至一个像素,那么它会再次变为活动状态。该示例尽可能简单,不使用任何 JavaScript。在真正敲定它之后,我发现该元素似乎认为它是滚动的,但在视觉上是固定的。换句话说,如果您单击“A”然后尝试再次单击“A”,有时您会再次单击,但它会在列表的下方。这对我来说似乎是一个 CSS 重排问题。我知道移动 webkit 试图减少回流的次数。

这是解决方法的一个实时示例。

我可以使用 JS 强制整个文档的 CSS 在滚动时重排(使用一个油门防止它在滚动后 100 毫秒内发生),这在简单示例中似乎解决了这个问题。不幸的是,这对这个问题的真实世界版本没有帮助。

这是问题页面和解决方法脚本的代码。

我的问题是这里发生了什么,是否有我缺少的 CSS 解决方法?具体来说,我很好奇是否有任何 CSS 专家可以弄清楚阻止点击点击固定元素上正确位置的布局情况是什么?更好的理解可能有助于找到真正的解决方法。

编辑:我忘了提到该示例明确地将视口强制为窗口大小。所以用户不能放大/缩小,这意味着 position:fixed 应该将元素锚定到窗口的左侧。

更新 (2012-09-20):这似乎已在 iOS 6 上的 Mobile Safari(以及 UIWebView)中得到修复。任何解决方法都应首先检查以确保它在 iOS < 6 上。例如,使用CssUserAgent这将如下所示:

if (parseFloat(cssua.ua.ios) < 6) { /* ... */ }
4

6 回答 6

9

实际上解决了我的特定问题的答案是在@Paul Sweatte 的链接之一中找到的解决方案的变体:

本质上,添加了一个比身体高的普通 div。当它被移除时,它会导致正文有效地滚动或重排。将添加/删除之间的延迟设置为 0 毫秒就足以让 DOM 重新计算而不会导致任何闪烁。这是我能找到的最小脚本,它完全解决了我这个问题的特定实例中所有position:fixed元素的问题。

var hack = document.createElement("div");
hack.style.height = "101%";
document.body.appendChild(hack);
setTimeout(function(){
    document.body.removeChild(hack);
    hack = null;
}, 0);
于 2012-07-13T21:51:46.013 回答
6

具有讽刺意味的是,我最初的回流修复(链接到问题中)现在也在我的真实应用程序中工作。将它的变体放在这里以防万一对其他人有用。它可以在任何容器元素上调用,或者如果没有传递任何内容,它会重排整个文档。

var forceReflow = function(elem){
    elem = elem || document.documentElement;

    // force a reflow by increasing size 1px
    var width = elem.style.width,
        px = elem.offsetWidth+1;

    elem.style.width = px+'px';

    setTimeout(function(){
        // undo resize, unfortunately forces another reflow
        elem.style.width = width;
        elem = null;
    }, 0);
};

这样做的好处是它不需要创建/添加/删除元素,只需调整容器即可。

于 2012-07-13T22:20:46.000 回答
2

看起来这是一个已知的错误

核心问题是:如果页面以编程方式移动(即用户没有导致滚动),则修复元素内的元素不可用。

使用绝对定位、更改标记或使用混合解决方法之一。

于 2012-07-10T22:46:28.657 回答
2

我的 iWebInspector 安装现在非常失败,但是在弄乱了 jsfiddle 和 iOS sim 之后,你的预感似乎是正确的——尽管位置:固定,浏览器认为页面已经滚动,并搞砸了点击目标。

看起来这与iOS Safari 的问题很相似:固定定位元素内的锚点只能工作一次,这也没有用纯 CSS 解决。还相关:固定位置导航栏只能在 iOS5 上的 Mobile Safari 中单击一次

切线,我确信它已经被注意到了,不可能滚动左侧,所以在 iPhone 上,索引只显示 AM。

于 2012-07-11T22:07:17.303 回答
0

我相信这会更好,并且可以达到相同的效果,允许在固定页脚中单击链接。不知何故,隐藏 urlbar 会导致固定页脚中的链接无法点击,直到您滚动一点。我在聚焦输入时也看到了这一点,并且我将一个事件处理程序附加到所有聚焦事件以触发它。我使用 dojo 执行此操作以附加事件。

        if(navigator.userAgent.match(/iPhone/i)){
        /* The famous iOS can't-click-links until touch fix, I attach onfocus */
            query('input,textarea,select', this.domNode).on('focus', function(el){
                document.documentElement.style.paddingRight = '1px';
                setTimeout(function () {
                document.documentElement.style.paddingRight = '';
                }, 0);
            });
        }
于 2012-08-27T19:15:26.587 回答
0

这是 McKamey 解决方法的一种变体。它避免了两次回流,并且可能有助于闪烁(取决于您的应用程序):

setTimeout(function(){
    document.body.style.borderBottom = 
        document.body.style.borderBottom === 'none' ? '1px solid white' : 'none';
}, 0);
于 2012-09-10T09:16:24.723 回答