55

我知道移动 safari 有很多关于固定元素的错误,但在大多数情况下,我已经设法让我的布局正常工作,直到我在底部的固定导航中添加了非常需要的文本输入。现在,当用户专注于文本输入元素并出现虚拟键盘时,我的导航(否则总是固定在页面底部)跳到页面中间一个非常奇怪的位置。

在此处输入图像描述

我会在这篇文章中添加一些代码,但我不确定从哪里开始。该导航固定在底部并定位在左侧和底部 0 处,宽度为 100%。从那里,我不知道发生了什么,我只能假设这是一个移动 safari 错误。

它似乎也失去了它的固定位置并变得相对,只有在文本输入元素被聚焦并且虚拟键盘打开时。

4

11 回答 11

20

http://dansajin.com/2012/12/07/fix-position-fixed/这是提出的解决方案之一。似乎值得一试。

简而言之:当任何输入被编辑时设置fixed元素并在该元素为红色时重置它们position:absolutefocusblur

.header { 
    position: fixed; 
} 
.footer { 
    position: fixed; 
} 
.fixfixed .header, 
.fixfixed .footer { 
    position: absolute; 
} 

if ('ontouchstart' in window) {
    /* cache dom references */ 
    var $body = $('body'); 

    /* bind events */
    $(document)
    .on('focus', 'input', function() {
        $body.addClass('fixfixed');
    })
    .on('blur', 'input', function() {
        $body.removeClass('fixfixed');
    });
}
于 2013-04-23T14:46:33.020 回答
15

上面的解决方案是解决问题的一些方法,但我认为添加额外的 css 类或使用 moderniz 会使事情复杂化。

如果您想要一个更简单的解决方案,这里是一个非modernizr 非额外 css但纯jquery 解决方案,适用于所有设备和浏览器我在所有项目中都使用此修复

if ('ontouchstart' in window) {
    $(document).on('focus', 'textarea,input,select', function() {
        $('.navbar.navbar-fixed-top').css('position', 'absolute');
    }).on('blur', 'textarea,input,select', function() {
        $('.navbar.navbar-fixed-top').css('position', '');
    });
}
于 2014-12-10T19:33:26.303 回答
6

我有一个类似的问题,但我找到了一种解决方法,方法是在输入焦点上将以下 css 类添加到 body 元素,然后在 unfocus 上再次将其删除:

.u-oh {
    overflow: hidden;
    height: 100%;
    width: 100%;
    position: fixed;
}
于 2015-08-24T01:34:49.420 回答
4

从 sylowgreen 所做的事情来看,关键是body在进入input. 因此:

$("#myInput").on("focus", function () {
    $("body").css("position", "fixed");
});

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});
于 2016-01-16T00:38:55.937 回答
2

像这样添加javascript:

$(function() {
  var $body;
  if ('ontouchstart' in window) {
    $body = $("body");
    document.addEventListener('focusin', function() {
      return $body.addClass("fixfixed");
    });
    return document.addEventListener('focusout', function() {
      $body.removeClass("fixfixed");
      return setTimeout(function() {
        return $(window).scrollLeft(0);
      }, 20);
    });
  }
});

并添加这样的类:

.fixfixed header{ 
    position: absolute; 
} 

你可以参考这篇文章:http ://dansajin.com/2012/12/07/fix-position-fixed/

于 2013-12-17T09:30:19.293 回答
1

我真的很喜欢上面的解决方案。我将它打包成一个小的 jQuery 插件,这样我就可以:

  • 设置哪个父母获得班级
  • 设置适用于哪些元素(不要忘记“textarea”和“select”)。
  • 设置父类名是什么
  • 允许它被链接
  • 允许多次使用

代码示例:

$.fn.mobileFix = function (options) {
    var $parent = $(this),
    $fixedElements = $(options.fixedElements);

    $(document)
    .on('focus', options.inputElements, function(e) {
        $parent.addClass(options.addClass);
    })
    .on('blur', options.inputElements, function(e) {
        $parent.removeClass(options.addClass);

        // Fix for some scenarios where you need to start scrolling
        setTimeout(function() {
            $(document).scrollTop($(document).scrollTop())
        }, 1);
    });

    return this; // Allowing chaining
};

// Only on touch devices
if (Modernizr.touch) {
    $("body").mobileFix({ // Pass parent to apply to
        inputElements: "input,textarea,select", // Pass activation child elements
        addClass: "fixfixed" // Pass class name
    });
}
于 2013-11-19T11:06:08.887 回答
1

我使用这个 jQuery 脚本:

var focus = 0;
var yourInput = $(".yourInputClass");
yourInput.focusin(function(){
    if(!focus) {
        yourInput.blur();
        $("html, body").scrollTop($(document).height());
        focus = 1;
    }
    if(focus) {
        yourInput.focus();
        focus = 0;
    }
});

非常适合我。

于 2015-03-22T20:51:09.120 回答
1

focusinandfocusout事件似乎比 and 事件更适合这个问题,focus因为blur前者冒泡到根元素。在 SO 上看到这个答案。

我个人使用AngularJS,所以我是这样实现的:

$window.document.body.addEventListener('focusin', function(event) {
    var element = event.target;
    var tagName = element.tagName.toLowerCase();
    if(!$rootScope.inputOverlay && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
        $rootScope.$apply(function() {
            $rootScope.inputOverlay = true;
        });
    }
});
$window.document.body.addEventListener('focusout', function() {
    if($rootScope.inputOverlay) {
        $rootScope.$apply(function() {
            $rootScope.inputOverlay = false;
        });
    }
});

注意:如果这是移动 Safari,我将有条件地运行此脚本。

我在导航栏上放了一个ng-class属性:

<div class="navbar navbar-default navbar-fixed-top" ng-class="{'navbar-absolute': inputOverlay}">

使用以下 CSS:

.navbar-absolute {
    position: absolute !important;
}

focusin 您可以在此处focusout 此处阅读更多信息。

于 2015-10-06T09:12:55.540 回答
0

这些解决方案都不适合我,因为我的 DOM 很复杂,而且我有动态无限滚动页面,所以我必须创建自己的。

背景:我正在使用一个固定的标题和一个更向下的元素,一旦用户向下滚动那么远,它就会粘在它下面。该元素有一个搜索输入字段。此外,我在向前和向后滚动期间添加了动态页面。

问题:在 iOS 中,只要用户单击固定元素中的输入,浏览器就会一直滚动到页面顶部。这不仅导致了不良行为,还触发了我在页面顶部添加动态页面。

预期的解决方案:当用户单击粘性元素中的输入时,iOS 中没有滚动(根本没有)。

解决方案:

     /*Returns a function, that, as long as it continues to be invoked, will not
    be triggered. The function will be called after it stops being called for
    N milliseconds. If `immediate` is passed, trigger the function on the
    leading edge, instead of the trailing.*/
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };

     function is_iOS() {
        var iDevices = [
          'iPad Simulator',
          'iPhone Simulator',
          'iPod Simulator',
          'iPad',
          'iPhone',
          'iPod'
        ];
        while (iDevices.length) {
            if (navigator.platform === iDevices.pop()) { return true; }
        }
        return false;
    }

    $(document).on("scrollstop", debounce(function () {
        //console.log("Stopped scrolling!");
        if (is_iOS()) {
            var yScrollPos = $(document).scrollTop();
            if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
                $('#searchBarDiv').css('position', 'absolute');
                $('#searchBarDiv').css('top', yScrollPos + 50 + 'px'); //50 for fixed header
            }
            else {
                $('#searchBarDiv').css('position', 'inherit');
            }
        }
    },250,true));

    $(document).on("scrollstart", debounce(function () {
        //console.log("Started scrolling!");
        if (is_iOS()) {
            var yScrollPos = $(document).scrollTop();
            if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
                $('#searchBarDiv').css('position', 'fixed');
                $('#searchBarDiv').css('width', '100%');
                $('#searchBarDiv').css('top', '50px'); //50 for fixed header
            }
        }
    },250,true));

要求:需要 JQuery mobile 才能使startsroll 和stopscroll 功能正常工作。

包含去抖动以消除粘性元素产生的任何滞后。

在 iOS10 中测试。

于 2016-11-30T00:19:06.983 回答
0

测试这个。有用。我只是测试一下。

$(document).on('focus','input', function() {
    setTimeout(function() {
        $('#footer1').css('position', 'absolute');
        $('#header1').css('position', 'absolute');
    }, 0);
});
$(document).on('blur','input', function() {
    setTimeout(function() {
        $('#footer1').css('position', 'fixed');
        $('#header1').css('position', 'fixed');
    }, 800);
});
于 2015-10-27T18:51:08.810 回答
-1

我对 Dan Sajin 提出的解决方案没有任何运气。也许自从他写了那篇博文后这个 bug 已经改变了,但是在 iOS 7.1 上,当输入模糊后位置变回固定时,这个 bug 总是会出现,即使你延迟到软件键盘完全隐藏。我提出的解决方案涉及等待touchstart事件而不是blur事件,因为当页面滚动时,固定元素总是会重新回到正确的位置。

if (Modernizr.touch) {
  var $el, focused;
  $el = $('body');
  focused = false;
  $(document).on('focus', 'input, textarea, select', function() {
    focused = true;
    $el.addClass('u-fixedFix');
  }).on('touchstart', 'input, textarea, select', function() {
    // always execute this function after the `focus` handler:
    setTimeout(function() {
      if (focused) {
        return $el.removeClass('u-fixedFix');
      }
    }, 1);
  });
}

高温高压

于 2014-05-19T15:12:40.833 回答