在移动端使用100vh被遮盖问题

目录

前言 

产生问题的原因:

 解决方法:(js)

window.innerHeight

在vue项目中实现

更简单的方式(纯css)

Chrome出现问题(纯css)

Usage 用法

第 1 步:安装插件:

第 2 步:检查您的项目是否存在 PostCSS 配置:

第 3 步:将插件添加到插件列表:

第 4 步:在您的 CSS 中使用 height: 100vh 或者 min-height: 100vh 。

参考或翻译

前言 

在移动端中,我们通常想要某块页面全屏展示而使用height:100vh来实现,但是不同的浏览器在地址栏/工具栏的影响下,实现方式也有区别,使得其无法很好的适配多种浏览器。所以最好避免通过css来设置高度,而是通过js来设置高度,获得完整的视口体验!

产生问题的原因:

移动浏览器(Chrome和Safari)具有“帮助”功能,其中地址栏有时可见,有时隐藏,从而改变了视口的可见大小。 这些浏览器没有将100vh高度调整为视口高度变化时屏幕的可见部分,而是将100vh设置为浏览器的高度,并隐藏了地址栏。 结果是,当地址栏可见时,屏幕的底部将被切除。

如下图:在地址栏出现/显示的时候,浏览器错误的将100vh设置为屏幕高度,而不是除去地址栏的可见宽度,因此下部分的蓝色按钮被挡住看不见。

 解决方法:(js)
window.innerHeight

解决此问题的一种方法是依靠javascript而不是CSS。 页面加载时,将高度设置为window.innerHeight可以将高度正确设置为窗口的可见部分。 如果地址栏可见,则window.innerHeight将为屏幕上可见部分的高度。 如果地址栏是隐藏的,则window.innerHeight将是全屏的高度,这正是您所期望的。

诀窍是将视口值存储在CSS变量中,并将其应用于元素而不是 vh 单位。

在vue项目中实现

${app}/src/app.vue

<script>
export default {
  name: 'App',
  mounted() {
    //首先我们获得视口高度并将其乘以1%以获得1vh单位的值
    let vh = window.innerHeight * 0.01
    // 然后,我们将——vh自定义属性中的值设置为文档的根
    document.documentElement.style.setProperty('--vh', `${vh}px`)

    // 我们监听resize事件 视图大小发生变化就重新计算1vh的值
    window.addEventListener('resize', () => {
      // 我们执行与前面相同的脚本
      let vh = window.innerHeight * 0.01
      console.log(vh);
      document.documentElement.style.setProperty('--vh', `${vh}px`)
    })
  },
}
</script>

 ${app}/views/foo.vue

因此,我们现在可以像使用任何其他单位一样使用 --vh vh 我们的高度值,将其乘以 100,我们就得到了我们想要的完整高度。

<style lang="scss" scoped>
.container {
  height: 100vh; /* 对于不支持自定义属性的浏览器的回退 */
  height: calc(var(--vh, 1vh) * 100);
</style>
更简单的方式(纯css)

看到了一片推文,解决了只可以通过js来实现适应屏幕视图的问题,使用的是纯css

在他的例子中希望写一个基本的弹性框布局(页眉、主页脚、粘性页脚),像是下面这样

 实现代码:

//html部分
<body>
  <header>HEADER GOES HERE</header>
  <main>MAIN GOES HERE</main>
  <footer>FOOTER GOES HERE</footer>
</body>

//css部分
<style>
body {
  display: flex; 
  flex-direction: column;
  margin: 0;
  min-height: 100vh;
}

main {
  flex: 1;
}
</style>

但是在iphone上运行览器测试,他的粘性页脚看起来并不那么粘: 

页脚隐藏在 Safari 的菜单栏下方 

使用-webkit-fill-available 可以允许元素本质上适合特定的布局,即填充该属性的可用空间。

添加以下样式

<style>
body {
  min-height: 100vh;
  /* 移动端视图bug修复 */
  min-height: -webkit-fill-available;
}

html {
  height: -webkit-fill-available;
}
</style>

这样就可以实现上图的粘性底部了,但是这个仍然有一些问题,在某些情况下只 -webkit-fill-available 会导致Chrome出现问题

Chrome出现问题(纯css)

在最后一篇博文中给出了修复方案,安装插件PostCSS来修复iOS的错误 100vh 。

它可以在Chrome(在某些情况下只 -webkit-fill-available 会导致Chrome出现问题),iOS / iPad / MacOS Safari和所有其他浏览器。纯CSS解决方案,不需要JS。

<style>
body {
  /* 由于底部面板,页脚将在iOS Safari上隐藏 */
  height: 100vh;
}
</style>

 添加支持

<style>
body {
  height: 100vh;
}

/* 避免Chrome浏览器看到Safari黑客 */
@supports (-webkit-touch-callout: none) {
  body {
    /* The hack for Safari */
    height: -webkit-fill-available;
  }
}
</style>

 它也适用于 min-height 、 max-height

Usage 用法
第 1 步:安装插件:

npm install --save-dev postcss postcss-100vh-fix

第 2 步:检查您的项目是否存在 PostCSS 配置:

 postcss.config.js 在项目根目录中、 "postcss" 部分 package.json  postcss 捆绑包配置中。

如果您不使用 PostCSS,请根据官方文档 official docs 添加,并在设置中设置此插件。


第 3 步:将插件添加到插件列表:
module.exports = {
plugins: [
+   require('postcss-100vh-fix'),
    require('autoprefixer')
  ]
}

第 4 步:在您的 CSS 中使用 height: 100vh 或者 min-height: 100vh 
参考或翻译

避免在移动网络上使用100vh https://chanind.github.io/javascript/2019/09/28/avoid-100vh-on-mobile-web.html

在移动设备上观察单位的技巧

https://css-tricks.com/the-trick-to-viewport-units-on-mobile/

新的通过css解决vh

CSS fix for 100vh in mobile WebKit - Matt Smith 

改进了上面博客的方法以修复 Chrome 中的错误并包装到 PostCSS 插件中(这样您就可以编写 min-height: 100vh 代码并且不记得进行黑客攻击)。

GitHub - postcss/postcss-100vh-fix: PostCSS plugin to fix height/min-height: 100vh on iOS 

  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以使用`node-sass`和`sass-loader`来解析`.scss`文件,同时使用`postcss-loader`和`autoprefixer`来自动添加浏览器厂商前缀,最后使用`css-loader`和`style-loader`将CSS样式注入到HTML页面中。 在Vue项目中,可以在`vue.config.js`文件中进行配置: ```javascript module.exports = { css: { loaderOptions: { sass: { prependData: ` @import "@/assets/scss/_variables.scss"; @import "@/assets/scss/_mixins.scss"; ` }, postcss: { plugins: [ require('autoprefixer')({ overrideBrowserslist: ['last 2 versions', '>1%'] }) ] } } } } ``` 然后,可以在`.vue`文件中使用`<style lang="scss">`标签来编写Sass样式,例如: ```scss // _variables.scss $base-font-size: 16px; $base-width: 750px; // _mixins.scss @function px2rem($px) { @return ($px / $base-font-size) * 1rem; } @mixin center() { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } // index.vue <style lang="scss"> .container { width: $base-width; margin: 0 auto; } .title { font-size: px2rem(32px); margin-top: px2rem(20px); } .box { width: 50vw; height: 50vh; background-color: #f00; @include center(); } </style> <template> <div class="container"> <h1 class="title">Hello World!</h1> <div class="box"></div> </div> </template> ``` 以上示例中,`$base-font-size`和`$base-width`变量定义在`_variables.scss`中,`px2rem()`和`center()`混合宏定义在`_mixins.scss`中,然后在`index.vue`中引入并使用它们来实现移动端自适应布局。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值