14

Webkit のモバイル バージョン (具体的には、モバイル Safari としての iOS 5.1.1 上の Webkit 534.46、および現在は iOS 用 Chrome) で問題が発生していますが、これは私が見たどのデスクトップ ブラウザーでも発生しません。(つまり、以下のデモは Webkit のモバイル バージョンで表示する必要があります。)

これが問題の実例です。CSS のコアは非常に単純です。ページの左側にアルファベットのインデックスを配置します。

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

この問題は、要素がボディの上に固定されている場合に発生します。スクロールが変化し、入力の受け入れを停止するまで、完全に操作できます。スクロールを(手動で)1ピクセルでも揺らすと、再びアクティブになります。この例は可能な限り単純に保たれ、JavaScript は使用されていません。実際に叩いた後、要素がスクロールされていると認識しているように見えますが、視覚的には修正されていることがわかりました。つまり、「A」をクリックしてからもう一度「A」をクリックしようとすると、2 回目のクリックが表示されることがありますが、それはリストのさらに下になります。これは、CSS リフローの問題のように思えました。モバイル Webkit がリフローの数を減らそうとしていることは知っています。

回避策の実例を次に示します。

JS を使用して、スクロール時にドキュメント全体の CSS を強制的にリフローさせることができます (スクロール後 100 ミリ秒まで発生しないようにするスロットルを使用)。これは、単純な例でこの問題を回避するようです。残念ながら、これはこの問題の実際のバージョンには役立ちません。

これは問題ページと回避スクリプトのコードです。

私の質問は、ここで何が起こっているのか、私が見逃している CSS の回避策はありますか? 具体的には、クリックが固定要素の正しい場所にヒットするのを妨げているレイアウトの状況が何であるかをCSSの第一人者が理解できるかどうかに興味がありますか? より良い理解は、本当の修正を見つけるのに役立つかもしれません.

編集:この例では、ビューポートをウィンドウのサイズに明示的に強制していることを忘れていました。つまり、position:fixed は要素をウィンドウの左側に固定する必要があります。

更新 (2012-09-20):これは、iOS 6 のモバイル Safari (および UIWebView) で修正されたようです。回避策は、最初に iOS 6 未満であることを確認する必要があります。たとえば、CssUserAgentを使用すると、次のようになります。

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

6 に答える 6

9

私の特定の問題を実際に解決した答えは、@Paul Sweatteのリンクの1つにあるソリューションのバリエーションでした:

基本的に、ボディよりも高いプレーンな 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

私の iWebInspector のインストールは現在かなり壊れていますが、jsfiddle と iOS sim をいじった後、あなたの直感は正しいようです。

これは iOS Safari と同じ問題のように見えます: Anchors within a fixed position element only work once , これも純粋な CSS では解決されていません. また関連: iOS5 の Mobile Safari で 1 回だけクリックできる位置のナビゲーション バーを修正しました

接線的には、すでに気づいていると思いますが、左側をスクロールすることはできないため、iPhone ではインデックスに AM のみが表示されます。

于 2012-07-11T22:07:17.303 に答える
2

これは既知のバグのようです:

中心的な問題は、ページがプログラムによって移動した場合 (つまり、ユーザーがスクロールを引き起こさなかった場合)、fix 要素内の要素を使用できないことです。

絶対配置を使用するか、マークアップを変更するか、ハイブリッドな回避策のいずれかを使用してください。

于 2012-07-10T22:46:28.657 に答える
0

これはより良い方法であり、同じ効果を達成し、固定フッターでリンクをクリックできるようになると思います。どういうわけか、URLバーを非表示にすると、少しスクロールするまで固定フッターのリンクをクリックできなくなります。入力をフォーカスするときにもこれを確認しました。すべてのフォーカスイベントにイベントハンドラーをアタッチして、これも実行します。イベントを添付するために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 の回避策のバリエーションを次に示します。2 回のリフローを回避し、ちらつきを抑えることができます (アプリによって異なります)。

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