İmlecin dışındaki iOS 11 Safari bootstrap kalıcı metin alanı


85

İOS 11 safari ile giriş metin kutusu imleci, giriş metin kutusunun dışındadır. Neden bu sorunu yaşadığını anlamadık. Gördüğünüz gibi, odaklanmış metin kutum e-posta metin girişi, ancak imlecim bunun dışında. Bu yalnızca iOS 11 Safari'de olur

Sorun


1
Bu, Safari ile ilgili bir hatadır. Apple bunu dahili olarak düzeltti, ancak düzeltme henüz iOS'un genel (hatta beta) sürümünde değil. bugs.webkit.org/show_bug.cgi?id=176896
Beetle

Yanıtlar:


69

position:fixedBir modal açarken gövdeye ekleyerek sorunu çözdüm. Umarım bu sana yardımcı olur.


6
Aşağıdaki yanıtlar için not - Bootstrap, modal açık olduğunda gövdeye .modal-open ekler, böylece bu sınıfa sabit olarak position: fixed ekleyebilirsiniz.
timmyc

1
Ayrıca width:100%gövde genişliğini cihaz genişliğiyle sınırlandırmak için eklemeniz gerekebilir . Bazı durumlarda, mevcut işaretlemeye bağlı olarak bu bir sorun olabilir. Sorun olmadan diğer tarayıcıları cezalandırmamak için @gentleboy (aşağıda) çözümünü de seviyorum, çünkü gövdeyi sabit olarak ayarlarken vücudun en üste kaymasına neden oluyor, bu da biraz can sıkıcı.
Redtopia

Garip bir şekilde, meteor-cordova ile yapılan bir uygulama derlemesinde bu sorunu yaşadım. Görünüşe göre v11 + çalıştıran herhangi bir iOS cihazında bu sorun vardı. Benim durumumda position:fixed, başvurunun gövdesine zaten başvurmuştum. Bunun yerine onu element position:absoluteüzerinde değiştirdim htmlve sorunumu çözdü. Teşekkürler Jen!
Adam Ross Bowers

1
Bu bizim için modal formların sonu olabilir. Apple sorunu çözse bile, çalışma formunu görmek için cihazını güncellemek kullanıcıya kalacaktır. Bunu düzeltmenin daha kolay ve evrensel bir yolu yok mu? Poli dolguya ne dersiniz?
Reado

1
hayatımı kurtardın <3
Cristian B.

42

Kişisel olarak, position: fixed otomatik olarak en üste kaydırın . Oldukça can sıkıcı!

Diğer cihazların ve sürümlerin cezalandırılmasını önlemek için bu düzeltmeyi yalnızca uygun iOS sürümlerine uyguluyorum.


** SÜRÜM 1 - Tüm modlar düzeltildi **

Javascript / jQuery için

$(document).ready(function() {

    // Detect ios 11_x_x affected  
    // NEED TO BE UPDATED if new versions are affected
    var ua = navigator.userAgent,
    iOS = /iPad|iPhone|iPod/.test(ua),
    iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);

    // ios 11 bug caret position
    if ( iOS && iOS11 ) {

        // Add CSS class to body
        $("body").addClass("iosBugFixCaret");

    }

});

CSS için

/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }

** SÜRÜM 2 - Yalnızca belirli modlar **

İşlevi yalnızca bir sınıfa sahip seçili modlar için çalışacak şekilde değiştirdim .inputModal

Yukarı kaydırmayı önlemek için yalnızca girdileri olan modlar etkilenmelidir.

Javascript / jQuery için

$(document).ready(function() {

    // Detect ios 11_x_x affected
    // NEED TO BE UPDATED if new versions are affected 
    (function iOS_CaretBug() {

        var ua = navigator.userAgent,
        scrollTopPosition,
        iOS = /iPad|iPhone|iPod/.test(ua),
        iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);

        // ios 11 bug caret position
        if ( iOS && iOS11 ) {

            $(document.body).on('show.bs.modal', function(e) {
                if ( $(e.target).hasClass('inputModal') ) {
                    // Get scroll position before moving top
                    scrollTopPosition = $(document).scrollTop();

                    // Add CSS to body "position: fixed"
                    $("body").addClass("iosBugFixCaret");
                }
            });

            $(document.body).on('hide.bs.modal', function(e) {
                if ( $(e.target).hasClass('inputModal') ) {         
                    // Remove CSS to body "position: fixed"
                    $("body").removeClass("iosBugFixCaret");

                    //Go back to initial position in document
                    $(document).scrollTop(scrollTopPosition);
                }
            });

        }
    })();
});

CSS için

/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }

HTML için sınıf Ekle inputModal modal için

<div class="modal fade inputModal" tabindex="-1" role="dialog">
    ...
</div>

Dikkat edin JavaScript işlevi artık kendi kendini çağırıyor


** iOS 11.3 GÜNCELLEME - Hata düzeltildi 😃🎉 **

İOS 11.3'ten itibaren hata düzeltildi. İçin teste gerek yoktur OS 11_içindeiOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);

Ancak iOS 11.2 hala yaygın olarak kullanıldığından (Nisan 2018 itibarıyla) dikkatli olun . Görmek

stat 1

stat 2


2
Güzel tavsiye. Bu sorun bende yok ama sanırım bu yanıt olarak küresel olabilir.
Biralarımı

3
@gentleboy Herhangi bir OS 11 bulmak için neden bir REGEX kullanmıyorsunuz? Böylece her OS 11 güncellemesini kodunuza güncellemeniz gerekmez mi? bunun gibi bir şeyiOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
T. Evans


2
@ T.Evans o regex çalışmıyor. Doğru bir normal ifade şuna benzer bir şey olabilir:ios11 = /OS 11_(\d{1,2})/.test(ua);
İbrahim

2
Sabit konum, belgeyi / gövde kaydırmasını üste almaya devam eder. Modal kapandıktan sonra modal open ve readd scrollTop değerinde geçerli scrollTop konumunu almanızı öneririm. Bunun gibi jsfiddle.net/im4aLL/hmvget9x/1
HADI

15

Bu sorun Bootstrap'in ve Safari'nin ötesinde. Tüm tarayıcılarda ortaya çıkan iOS 11'de tam ekran hatasıdır. Yukarıdaki düzeltme, bu sorunu her durumda çözmez.

Hata burada ayrıntılı olarak rapor edilir:

https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8

İddiaya göre bunu zaten Apple'a bir hata olarak bildirdiler.


Bu benim için sorun gibi görünüyor, IOS 11'e güncellemeden önce iyi çalışıyordu. Android kullanıcıları sorun yaşamıyor.
hackingchemist

11

Sinir bozucu hata, tanımladığınız için teşekkürler. Aksi takdirde, iphone'umu veya kafamı duvara çarpıyor olurdum.

En basit düzeltme (1 satır kod değişikliği):

Aşağıdaki CSS'yi html'ye veya harici bir css dosyasına eklemeniz yeterlidir.

<style type="text/css">
.modal-open { position: fixed; }
</style>

İşte tam bir çalışma örneği:

.modal-open { position: fixed; }
<link href="https://getbootstrap.com/docs/3.3/dist/css/bootstrap.min.css" rel="stylesheet">

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@mdo">Open modal for @mdo</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@fat">Open modal for @fat</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@getbootstrap">Open modal for @getbootstrap</button>
...more buttons...

<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="exampleModalLabel">New message</h4>
      </div>
      <div class="modal-body">
        <form>
          <div class="form-group">
            <label for="recipient-name" class="control-label">Recipient:</label>
            <input type="text" class="form-control" id="recipient-name">
          </div>
          <div class="form-group">
            <label for="message-text" class="control-label">Message:</label>
            <textarea class="form-control" id="message-text"></textarea>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Send message</button>
      </div>
    </div>
  </div>
</div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://getbootstrap.com/docs/3.3/dist/js/bootstrap.min.js"></script>

Burada bir sorun gönderdim: https://github.com/twbs/bootstrap/issues/24059


Cevap bu olmalı. Bootstrap, bir modal göründüğünde gövdeye modal-open sınıfını ekler. Sadece o sınıfı hedeflemeniz gerekiyor.
lfkwtz

1
Bir süredir bu konuyla uğraşıyorum. Sabit pozisyon eklemek sayfayı yukarı kaydırdığı için bu çözüm benim için yetersiz. Dolayısıyla kullanıcı modeli kapattığında farklı bir kaydırma konumundadır. Bu korkunç bir kullanıcı deneyimine yol açar
Nearpoint

Bu düzeltme, mobil cihazlarda Chrome kullanırken benim için çalıştı. .Modal-open modal html'de görünmediği için ilk başta kafam karıştı, ancak yine de başlığıma CSS olarak ekledim ve çalıştı.
David

4

En kolay / en temiz çözüm:

body.modal-open { position: fixed; width: 100%; }

1
Bu en kolay çözüm ve işe yarıyor, ancak tek sorun imlecin tamamen kaybolması. İlk durum kadar kötü değil ama bir kullanılabilirlik sorunu var.
tmo256

Tuhaf, yok olan bir imleçle karşılaşmadım
lfkwtz

1
Ayrıca kaybolan imleci de deneyimledim, bunun neden olabileceğine dair herhangi bir düşüncem var mı?
Alex Burgos

4
Evet, ayrıca sadece ilk odaklanma olayı için kaybolan bir imleç görüyorum. Sonraki giriş odaklarında imleç görünür. Çok ilginç. Bu yalnızca iOS'taki Safari'de oluyor.
Devin Walker

@DevinWalker kaybolan imleç sorununu hiç çözdünüz mü?
hibe

3

Apple cihazlarınızı iOS 11.3'e güncelledikten sonra bu sorun artık tekrarlanamaz


Ne demek Apple tamir etti?
Starscream

1
@Starscream evet bu yazılım sürümü ile elma tarafından (iOS 11.3) düzeltilenekadar
Eashan

2

Ekle position: fixed;için bodykalıcı açıkken.

$(document).ready(function($){
    $("#myBtn").click(function(){
        $("#myModal").modal("show");
    });
    $("#myModal").on('show.bs.modal', function () {
        $('body').addClass('body-fixed');
    });
    $("#myModal").on('hide.bs.modal', function () {
        $('body').removeClass('body-fixed');
    });
});
.body-fixed {
    position: fixed;
    width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>

<button type="button" class="btn btn-info btn-lg" id="myBtn">Open Modal</button>

<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
	<div class="modal-dialog">
		<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal">&times;</button>
				<h4 class="modal-title">Form</h4>
			</div>
			<div class="modal-body">
				<div class="form-group">
					<label class="control-label">Input #1</label>
					<input type="text" class="form-control">
				</div>
				<div class="form-group">
					<label class="control-label">Input #2</label>
					<input type="text" class="form-control">
				</div>
				<div class="form-group">
					<label class="control-label">Input #3</label>
					<input type="text" class="form-control">
				</div>
				<div class="form-group">
					<label class="control-label">Input #4</label>
					<input type="text" class="form-control">
				</div>
			</div>
			<div class="modal-footer">
				<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
			</div>
		</div>
	</div>
</div>


1
Bu konudaki diğer çözümlere benzer şekilde, modal kapandığında - tekrar zirveye geri dönersiniz. Örneğin: kullanıcı, öğe ızgarasında
gezinir, ayrıntıları bir modelde

2
iPhone 7 plus cihazımda bu düzeltme
imlecimin

1

Çalışmaya position: fixeddayalı ve konum düzeltmeyi kullanan bu çözümler scrollTopgerçekten iyi, ancak bazı insanlar (ben dahil) başka bir sorunla karşılaştı: klavye imleci / imleç girdiler odaklandığında görünmüyor.

Ben ne zaman o şapka / imleç çalışır gözlenen YAPMAYIN kullanmak position: fixedvücut üzerinde. Yani bazı şeyleri denedikten sonra, ben bu yaklaşımı kullanarak vazgeçti ve kullanım kararı position: relativeüzerine bodyve kullanım scrollTopdoğru için modal olarak en üst konuma yerine.

Aşağıdaki koda bakın:

var iosScrollPosition = 0;

function isIOS() {
   // use any implementation to return true if device is iOS
}

function initModalFixIOS() {
    if (isIOS()) {
        // Bootstrap's fade animation does not work with this approach
        // iOS users won't benefit from animation but everything else should work
        jQuery('#myModal').removeClass('fade');
    }
}

function onShowModalFixIOS() {
    if (isIOS()) {
        iosScrollPosition = jQuery(window).scrollTop();
        jQuery('body').css({
            'position': 'relative', // body is now relative
            'top': 0
        });
        jQuery('#myModal').css({
            'position': 'absolute', // modal is now absolute
            'height': '100%',
            'top': iosScrollPosition // modal position correction
        });
        jQuery('html, body').css('overflow', 'hidden'); // prevent page scroll
    }
}

function onHideModalFixIOS() {
    // Restore everything
    if (isIOS()) {
        jQuery('body').css({
            'position': '',
            'top': ''
        });
        jQuery('html, body').scrollTop(iosScrollPosition);
        jQuery('html, body').css('overflow', '');
    }
}

jQuery(document).ready(function() {
    initModalFixIOS();
    jQuery('#myModal')
        .on('show.bs.modal', onShowModalFixIOS)
        .on('hide.bs.modal', onHideModalFixIOS);
});

0

Daha önce belirtildiği gibi: ayar style.position propertyarasında bodyhiç fixedçözer iOS cursor misplacementsorunu.

Ancak, bu kazanç, zorla sayfanın üst kısmına kaydırılma pahasına gelir.

Neyse ki, bu yeni UXsorun yararlanarak tarafından çok yükü olmadan etkisiz duruma gelir HTMLElement.styleve window.scrollTo().

Temel özü karşı koymak olduğunu scroll to topmanipüle ederek bodyeleman 's style.topzaman mounting. Bu, değişken YOffsettarafından yakalanan değer kullanılarak yapılır ygap.

Oradan sadece sıfırlama meselesi body's style.topiçin 0ve kullanarak kullanıcının görünümü reframing window.scrollTo(0, ygap)zaman dismounting.

Pratik bir örnek için aşağıya bakın.

// Global Variables (Manage Globally In Scope).
const body = document.querySelector('body') // Body.
let ygap = 0 // Y Offset.


// On Mount (Call When Mounting).
const onModalMount = () => {

  // Y Gap.
  ygap = window.pageYOffset || document.documentElement.scrollTop

  // Fix Body.
  body.style.position = 'fixed'

  // Apply Y Offset To Body Top.
  body.style.top = `${-ygap}px`

}


// On Dismount (Call When Dismounting).
const onModalDismount = () => {

  // Unfix Body.
  body.style.position = 'relative'

  // Reset Top Offset.
  body.style.top = '0'

  // Reset Scroll.
  window.scrollTo(0, ygap)

}

Bunun için daha detaylı bir örneğiniz var mı? Modal açıldığında çağrılan bir fonksiyonda Mount'a sahip olacağımı tahmin ediyorum ve ardından Dismount'u bir fonksiyona koyup modal kapatıldığında bunu çağırıyorum.
Neal Jones

Aahh evet. Ne demek istediğini anlıyorum. Revize edilmiş bir çözüm için lütfen yukarıya bakın. Ayrıca; evet, niyetiniz onları functionsne zaman mountingve ne zaman çağırmanızdır dismounting. Teşekkürler.
Arman Charan

-1

IOS> 11.2 üzerinde çalışan ve herhangi bir ek CSS gerektirmeyen vanilla js'de herhangi bir düzeltme arıyor olabilir:

(function() {
    if (!/(iPhone|iPad|iPod).*(OS 11_[0-2]_[0-5])/.test(navigator.userAgent)) return

    document.addEventListener('focusin', function(e) {
        if (!e.target.tagName == 'INPUT' && !e.target.tagName != 'TEXTAREA') return
        var container = getFixedContainer(e.target)
        if (!container) return
        var org_styles = {};
        ['position', 'top', 'height'].forEach(function(key) {
            org_styles[key] = container.style[key]
        })
        toAbsolute(container)
        e.target.addEventListener('blur', function(v) {
            restoreStyles(container, org_styles)
            v.target.removeEventListener(v.type, arguments.callee)
        })
    })

    function toAbsolute(modal) {
        var rect = modal.getBoundingClientRect()
        modal.style.position = 'absolute'
        modal.style.top = (document.body.scrollTop + rect.y) + 'px'
        modal.style.height = (rect.height) + 'px'
    }

    function restoreStyles(modal, styles) {
        for (var key in styles) {
            modal.style[key] = styles[key]
        }
    }

    function getFixedContainer(elem) {
        for (; elem && elem !== document; elem = elem.parentNode) {
            if (window.getComputedStyle(elem).getPropertyValue('position') === 'fixed') return elem
        }
        return null
    }
})()

Bu ne yapar:

  1. Tarayıcının iOS 11.0.0 - 11.2.5'te Safari olup olmadığını kontrol edin
  2. focusinSayfadaki herhangi bir etkinliği dinleyin
  3. Odaklanılan öğe bir inputveya a ise textareave fixedkonumu olan bir öğe içinde yer alıyorsa, konteyner konumunu absolutewhile ile ilgili scrollTopve kapların orijinal boyutları olarak değiştirin.
  4. Bulanıklaştırıldığında, kabın konumunu konumuna geri yükleyin fixed.

-1

Bu çözüm benim için çalıştı ve iOS'taki tüm tarayıcılarda iyi çalışıyor.

.safari-nav-force{
/* Allows content to fill the viewport and go beyond the bottom */
height: 100%;
overflow-y: scroll;
/* To smooth any scrolling behavior */
-webkit-overflow-scrolling: touch;
}

JavsScript

var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
$('.modal').on('shown.bs.modal', function () {
    if (iOS && $('.modal').hasClass('in')){
        $('html,body').addClass('safari-nav-force');
    }
});
$('.modal').on('hidden.bs.modal', function () {
    if (iOS && !$('.modal').hasClass('in')){
        $('html,body').removeClass('safari-nav-force');
    }
});


-2

Modal css geçersiz kıl ve olarak değiştirebilmektedir positiongelen fixedetmekabsolute

.modal {
position: absolute !important;
}

1
Benim senaryomda işe yaramadı. Sabit olarak mutlak olarak değiştirmenin BİRÇOK çarpma etkisi olabilir
Steve D

@SteveD - çalışmasını sağlamak için modalınızı <body> öğesine eklemelisiniz. Ve <body>, - position: relative şeklinde olmalıdır. Ve ne zaman çalışması gerekir :)
Dan

-3

#modal konuma ekleyin: mutlak konumla ilgili gelecekteki sorunları düzeltir: düzeltildi


Cevabınız birebir aynı. Lütfen yinelenen yanıtlar göndermediğinizden emin olun.
MechMK1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.