移动端内容显示在一页时,虚拟键盘输入与position:fixed的冲突解决

本文介绍了两种在移动端网页设计中保持底部元素如联系信息始终固定在屏幕底部的方法,并对比了固定定位等常见但存在缺陷的技术方案。

一、正确做法1(适用于内容全部显示在一页):
1、代码片段:

...
<style>
    *{
        margin:0;
        padding:0;
    }
    html{
        height:100%;/*关键代码*/
    }
    body{
        background-color:#fff;
        font-size:14px;
        color:#222;
        width:100%;
        height:100%;/*关键代码*/
    }
    li{
        list-style-type:none;
    }
    a:link,a:visited,a:hover,a:active{
        text-decoration:none;
    }
    /*导航栏*/
    nav{
        width:100%;
        height:44px;
        background-color:#ff9137;
        color:#fff;
        line-height:44px;
        font-size:18px;
        text-align:center;
        padding-left:10px;
        padding-right:30px;
    }
    nav a{
        float:left;
    }
    nav img{
        width:20px;
        height:20px;
        vertical-align:middle;
    }
    /*主体内容*/
    :-moz-placeholder{
        color:#999; /*mozilla ff 4-18*/
    }
    ::-moz-placeholder{
        color:#999; /*mozilla ff 19+*/
    }
    :-ms-input-placeholder{
        color:#999; /*ie 10+*/
    }
    ::-webkit-input-placeholder{
        color:#999; /*webkit browsers*/
    }
    input[type=text],select,input[type=password]{
        border:none;
        outline:none;
        background-color:#fff;
        color:#999;
        appearance: none;
        -moz-appearance:none;
        -webkit-appearance: none;
        padding-left:1px;
        text-align:left;
        height:26px;
        width:100%;
    }
    select::-ms-expand{
        display:none;
    }
    .logo{
        text-align:center;
        padding-top:15px;
        padding-bottom:33px;
    }
    .logo img{
        width:80px;
        height:80px;
    }
    .loginContent{
        margin-left:50px;
        margin-right:50px;
    }
    .userName,.psd{
        border-bottom:1px solid #999;
        padding-left:28px;
    }
    .userName{
        background:url(../img/user-yellow.png) no-repeat;
        background-size:24px 24px;
        padding-bottom:5px;
        margin-bottom:18px;
    }
    .psd{
        background:url(../img/password-yellow.png) no-repeat;
        background-size:24px 24px;
        padding-bottom:5px;
        margin-bottom:28px;
    }
    .forgetPsd a{
        border-bottom:1px solid #999;
        color:#999;
        font-size:12px;
        padding-bottom:2px;
    }
    button{
        width:100%;
        padding-top:10px;
        padding-bottom:10px;
        border:none;
    }
    .btn1{
        background-color:#ff9137;
        color:#fff;
        border-radius: 6px;
        outline:none;
        margin-bottom:16px;
        font-size:15px;
    }
    .btn2{
        background-color:#fff;
        color:#ff9137;
        outline:none;
        font-size:15px;
    }
    .contact{
        text-align:center;
        color:#999;
        font-size:12px;
    }
    .error{
        font-size:12px;
        color:#ff9037;
    }
</style>
</head>
<body>
    <div class="content">
        <!--导航栏-->
        <nav>
            <a href="#"><img src="../img/back.png"></a>
            登录
        </nav>
        <!--主体内容-->
        <div class="logo">
            <img src="../img/logo-yellow.png">
        </div>
        <div class="loginContent">
            <form id="frmLogin" autocomplete="off">
                <div class="userName">
                    <input type="text" name="userName" placeholder="请输入账号">
                </div>
                <div class="psd">
                    <input type="password" name="psd" placeholder="请输入密码">
                </div>
                <div>
                    <button class="btn1">登录</button>
                </div>
            </form>
            <div>
                <a href="inc.html"><button class="btn2">注册</button></a>
            </div>
        </div>
    </div>
    <div class="contact">
        <p>忘记账号、忘记密码等账号相关问题请联系我们</p>
        <p>联系电话:82624787</p>
    </div>
<script src="../js/jquery-2.2.3.min.js"></script>
<script src="../js/jquery.validate.js"></script>
<script>
    //  密码验证:在6位数以上
    $(function(){
        $("#frmLogin").validate({
            rules:{
                userName:{
                    required:true
                },
                psd:{
                    required:true,
                    minlength:6
                }
            },
            messages:{
                userName:{
                    required:"请输入账号"
                },
                psd:{
                    required:"请输入密码",
                    minlength:"请输入6位以上密码"
                }
            }
        });

        /*让最下方的联系我们这个div距离下底边26px*/   /*关键代码*/
        var wContact=$('body').height()-$('.content').outerHeight();
        var w=wContact-80;
        $('.contact').css('margin-top',w);
    });
</script>
...

2、呈现效果:
(1)iphone5
(2)iphone6p
3、备注:
(1)jquery中的这段代码起决定作用:

    /*让最下方的联系我们这个div距离下底边26px*/
    var wContact=$('body').height()-$('.content').outerHeight();
    var w=wContact-80;
    $('.contact').css('margin-top',w);

步骤:①设置html、body的高度为100%,目的是可以得到屏幕高度
var wContact=$('body').height()-$('.content').outerHeight();得到注册下面的所有空间的高度
var w=wContact-80; 80其实是给忘记密码和下面的空白留的高度
$('.contact').css('margin-top',w);将‘.contact’上的空白设置成动态的,给‘.contact’以及下面的空白留一定高度,这样就能实现移动端,忘记密码等内容距离底端一定距离,而且在不同手机都有这样的效果。
(2)’.contact’以上的内容还是比较挤的,实际是为了让iphone4这样的小手机也显示在一页中,所以给他们的高度就比较少。
(3)$('.contact').css('margin-top',w)设置时w不要加”,也可以写成$('.contact').css('margin-top',w+'px')
4、其实还可以在’.contact’上增加一个div,然后动态设置这个div的高度,就不设置’.contact’的margin-top,其实是一样的效果,但是这样会增加冗余的代码,因为添加了一个空白的div,所以还是比较提倡设置margin-top.

二、正确做法2(内容不在一个页面时,可以用。但是不管内容是否在一个页面,都会有小bug,下面会提到):
1、代码片段:
(1)增加css

.contact{
        background-color:#f00; 
        position:fixed;
        left:0;
        right:0;
        bottom:0;
    }

(2)修改script

        /*方法1:输入框获得焦点时,让固定定位的内容变成正常的static定位,失去焦点后变成固定定位*/
        $('input').focus(function(){
            $('.contact').css('position','static');
        }).blur(function(){
            $('.contact').css('position','fixed');
        });
        /*方法2:输入框获得焦点时,让固定定位的内容消失,失去焦点后正常*/
        $('input').focus(function(){
            $('.contact').hide();
        }).blur(function(){
            $('.contact').show();
        });

2、呈现的效果大家都能想到,便不再截图。
3、备注:
(1)以上2种方法效果基本能正常,在输入框获得焦点时,内容不会浮到正常流中。
(2)bug:
①就方法2来说(方法1同理),在键盘获取焦点事件发生后,“键盘弹出”会先于“’.contact’消失”发生,所以’.contact’的内容会先浮到正常流中,然后再消失。在键盘失去焦点事件发生后,“‘.contact’出现”会先于“键盘弹出”发生,所以‘.contact’的内容会先浮到正常流中,然后再随键盘的消失而恢复到固定定位的地方。即在获取焦点事件发生后几秒钟和失去焦点事件发生后几秒钟,还是会发生以下情况(为了效果明显,将固定定位的内容颜色改成红色):
sumsung
sumsung
方法2来说(方法1同理),画红色圈圈的地方点击后,键盘会消失,但是并没有引发焦点失去事件,这时’.contact’的内容还是处于消失状态。

三、错误示范1
1、代码片段:
(1)增加css

.contact{
        margin-top:50px;
    }

(2)删除script
即删除对margin-top的动态设置
2、呈现效果:
(1)iphone4
(2)iphone6p
3、备注:
(1)很明显,‘.contact’距离上边的距离不会动,在iphone4中做到和正确做法1一样的效果,但是在iphone6p中就不行了。所以固定margin-top不能使底部内容随手机屏幕大小而固定在距离底部一定距离。

四、错误示范2
1、代码片段:
(1)增加css:利用固定定位

.contact{
        width:100%;
        position:fixed;
        left:0;
        bottom:20px;
    }

(2)删除script
即删除对margin-top的动态设置
2、呈现效果:
(1)不输入内容是都正常,效果和正确做法的效果一样。
(2)聚焦开始输入内容时,效果如下:
sumsung
3、备注:
(1)不管是固定定位还是绝对定位,都会产生和上图一样的效果。
(2)只要有开始输入内容,弹出键盘时,就默认键盘顶端的线是窗口的底端,’.contact’就会距离键盘顶端20px,这样就会和其他内容重叠。
四、总结:
如果不需要输入内容时,要呈现像正确做法1一样的效果的话,可以用固定定位,这样比较方便,但是如果要输入内容的话,还是用正确做法1这样做。

<think>我们正在解决一个具体问题:使用`position: fixed`的div在滚动底部显示不全(被截断)。根据引用[1]和[2],fixed定位是相对于浏览器窗口(视觉视口)进行定位的。因此,理论上设置`bottom:0`应该让元素紧贴窗口底部。但实际中可能出现显示不全,特别是在移动端。 结合之前的回答和引用,问题可能出现在: 1. 移动端浏览器在滚动视口高度变化(如地址栏的隐藏/显示)导致固定定位元素的位置计算不准确。 2. 固定定位元素内部内容过多,而元素高度设置不当,导致内容溢出被裁剪。 3. 父容器有`overflow: hidden`等设置,导致固定定位元素被裁剪(虽然fixed是相对于视口,但某些情况下也可能受包含块影响?注意:fixed的包含块是视口,但根据引用[4],绝对定位元素会被overflow裁剪,而fixed定位元素通常不会被视口裁剪,但可能被某些浏览器特性影响)。 4. iOS的安全区域(Safe Area)问题,底部内容被Home指示条遮挡。 解决方案: 1. 使用动态视口高度单位(dvh)来设置元素的最大高度,确保在移动端视口变化自适应。 2. 为固定定位元素设置内部滚动(overflow-y: auto),当内容过多可以在元素内部滚动。 3. 处理iOS安全区域,使用env(safe-area-inset-bottom)为底部增加内边距。 4. 确保页面主体内容有足够的下内边距,避免内容被固定定位元素遮挡(同也能让固定定位元素完全显示)。 根据引用[3]中提到的滚动事件监听,我们也可以考虑用JavaScript动态调整高度,但现代CSS已经提供了更好的解决方案(如dvh单位),所以优先使用CSS方案。 具体步骤: 步骤1:设置固定定位元素的基本样式 ```css .fixed-bottom-div { position: fixed; bottom: 0; left: 0; right: 0; /* 或者 width: 100% */ /* 使用max-height而不是height,以便内容自适应,内容滚动 */ max-height: 50vh; /* 初始设置,但建议使用dvh */ /* 改为动态视口高度 */ max-height: 50dvh; overflow-y: auto; /* 允许内部滚动 */ box-sizing: border-box; /* 确保内边距和边框不增加总高度 */ background: #fff; /* 背景色 */ z-index: 1000; /* 确保不被其他元素覆盖 */ /* 处理iOS安全区域 */ padding-bottom: env(safe-area-inset-bottom, 0); } ``` 步骤2:为页面主体内容设置底部内边距,避免被固定元素遮挡 ```css body { padding-bottom: calc(50dvh + 20px); /* 20px作为额外缓冲,确保固定元素完全展开也不遮挡 */ } ``` 注意:这里设置body的padding-bottom值应该大于或等于固定定位元素的最大高度(50dvh)加上可能的安全区域值,以确保页面滚动到底部,固定元素不会覆盖页面内容。 步骤3:考虑移动端视口变化 在移动端,当用户滚动页面,浏览器工具栏(地址栏)可能会收缩,导致视口高度变化。使用`dvh`(dynamic viewport height)可以自动适应这种变化。 步骤4:测试 在移动设备上测试,注意观察滚动过程中固定定位元素的高度是否随视口高度变化而调整,以及底部安全区域是否被正确应用。 如果仍然出现问题,可以使用JavaScript辅助(如引用[3]中的方法监听滚动和调整): ```javascript window.addEventListener('resize', adjustFixedDiv); window.addEventListener('scroll', adjustFixedDiv); // 移动端滚动视口大小变化 function adjustFixedDiv() { const fixedDiv = document.querySelector('.fixed-bottom-div'); // 设置最大高度为当前视口高度的一半(或根据需要) fixedDiv.style.maxHeight = (window.innerHeight * 0.5) + 'px'; } ``` 但是,注意频繁的滚动事件可能会引起性能问题,所以建议使用CSS的dvh单位作为首选方案。 另外,引用[4]提到绝对定位元素会被overflow裁剪,但固定定位元素通常不会,因为其包含块是视口。不过,如果固定定位元素被包裹在一个设置了`transform`、`perspective`或`filter`样式(不为none)的祖先元素内,则该祖先元素会创建一个新的包含块,从而影响固定定位(使其相对于该祖先而不是视口)。所以,请确保固定定位元素没有这样的祖先。 总结代码示例: HTML: ```html <body> <div class="content"> <!-- 长内容 --> </div> <div class="fixed-bottom-div"> <!-- 固定底部的内容,可能很长 --> </div> </body> ``` CSS: ```css body { margin: 0; padding-bottom: 60vh; /* 根据固定元素的最大高度调整,例如固定元素最大高度为50dvh,则这里设置大于50dvh的值 */ /* 注意:如果固定元素高度是动态的,可以设置一个足够大的值 */ } .fixed-bottom-div { position: fixed; bottom: 0; left: 0; width: 100%; max-height: 50dvh; /* 使用动态视口高度 */ overflow-y: auto; /* 内部滚动 */ box-sizing: border-box; background: white; border-top: 1px solid #ddd; padding: 10px; padding-bottom: calc(10px + env(safe-area-inset-bottom)); /* 叠加安全区域 */ z-index: 1000; } ``` 这样,固定定位元素将始终位于底部,当内容超过最大高度,内部会出现滚动条。同,页面主体内容底部有足够的padding,确保不会被遮挡。 如果问题仍然存在,请检查是否有其他CSS样式覆盖,或者祖先元素创建了新的包含块。 相关问题: 1. 如何解决移动端滚动固定定位元素位置跳动的问题? 2. `position: sticky` 和 `position: fixed` 在底部定位有何本质区别? 3. iOS Safari 中固定定位元素有哪些特殊行为需要处理? 4. 如何实现固定定位元素在视口变化的平滑高度过渡效果? 5. CSS 中的 `dvh`、`svh` 和 `lvh` 单位有何区别?如何选择?</think>针对 `position: fixed` 的 div 在滚动底部显示不全的问题,以下是系统性的解决方案和最佳实践: ### 🔧 核心解决方案 ```css .fixed-bottom-div { position: fixed; bottom: 0; left: 0; width: 100%; /* 关键设置 */ max-height: 100dvh; /* 使用动态视口单位 */ overflow-y: auto; /* 允许内容滚动 */ box-sizing: border-box; /* 包含内边距 */ z-index: 1000; /* 确保在最上层 */ /* 处理移动端安全区域 */ padding-bottom: env(safe-area-inset-bottom); } /* 防止内容被遮挡 */ body { padding-bottom: 60px; /* 大于固定div高度 */ } ``` ### 📌 五大问题及解决方案 #### 1. **移动端视口高度变化**(最常见问题)[^1][^2] - **问题**:移动端浏览器滚动地址栏/工具栏收缩导致视口高度变化 - **修复**: ```css .fixed-bottom-div { max-height: 100dvh; /* 使用动态视口单位 */ height: auto; /* 高度自适应 */ } ``` #### 2. **内容溢出容器** - **问题**:div 内部内容高度超过视口高度 - **修复**: ```css .fixed-bottom-div { overflow-y: auto; /* 添加内部滚动 */ } ``` #### 3. **层级冲突** - **问题**:其他元素覆盖固定定位 div - **修复**: ```css .fixed-bottom-div { z-index: 1000; /* 提高堆叠顺序 */ } ``` #### 4. **iOS 安全区域问题** - **问题**:iPhone 底部 Home 指示条遮挡内容 - **修复**: ```css .fixed-bottom-div { padding-bottom: env(safe-area-inset-bottom); } ``` #### 5. **父容器裁剪问题** - **问题**:父元素设置了 `overflow: hidden`(虽然 fixed 定位基于视口,但某些浏览器会受影响)[^4] - **修复**: ```css html, body { overflow: visible !important; } ``` ### ⚡ JavaScript 动态调整方案 ```javascript // 实更新高度(解决移动端工具栏收缩问题) function adjustFixedDiv() { const fixedDiv = document.querySelector('.fixed-bottom-div'); fixedDiv.style.maxHeight = window.innerHeight + 'px'; } // 监听视口变化 window.addEventListener('resize', adjustFixedDiv); window.addEventListener('scroll', adjustFixedDiv); // 针对移动端 adjustFixedDiv(); // 初始化 ``` ### 🌟 最佳实践建议 1. **使用现代 CSS 单位**: ```css .fixed-bottom-div { max-height: 100dvh; /* 优先使用动态视口高度 */ max-height: -webkit-fill-available; /* Safari 备用方案 */ } ``` 2. **内容区域预留空间**: ```css .main-content { padding-bottom: 80px; /* 大于固定div高度 */ } ``` 3. **Flexbox 布局优化**: ```css body { display: flex; flex-direction: column; min-height: 100dvh; } .fixed-bottom-div { flex-shrink: 0; /* 防止收缩 */ } ``` ### 完整示例代码 ```html <!DOCTYPE html> <html> <head> <style> body { padding-bottom: 300px; /* 预留空间 */ } .fixed-bottom-div { position: fixed; bottom: 0; left: 0; width: 100%; background: #f0f0f0; padding: 15px; box-sizing: border-box; max-height: 50dvh; /* 动态视口高度 */ overflow-y: auto; /* 内部滚动 */ border-top: 1px solid #ccc; padding-bottom: env(safe-area-inset-bottom); /* iOS安全区 */ z-index: 1000; } </style> </head> <body> <!-- 长内容 --> <div style="height: 2000px; background: linear-gradient(white, lightblue);"> 页面内容... </div> <!-- 固定底部元素 --> <div class="fixed-bottom-div"> <h3>固定底部区域</h3> <p>此处内容可滚动...</p> <!-- 长内容 --> <div style="height: 800px;"></div> <p>底部内容结束</p> </div> <script> // 动态调整高度 window.addEventListener('resize', () => { document.querySelector('.fixed-bottom-div').style.maxHeight = window.innerHeight * 0.5 + 'px'; }); </script> </body> </html> ``` > **测试建议**:在移动设备上测试,使用 Chrome 设备模拟器并开启"显示移动设备工具栏"选项,模拟工具栏收缩效果[^1][^2]。 通过组合使用动态视口单位、内部滚动机制和适当的内容间距,可有效解决固定定位元素在滚动显示问题,特别是在移动设备上。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值