UniApp WebView 组件宽高设置与动态适配全方案

  • 小程序 / 网页 (H5)web-view默认强制全屏铺满页面,无法自定义宽高 ,只能整页跳转打开 H5;HBuilderX3.5.4+ H5 端支持fullscreen:false自定义尺寸。
  • App 端 (Android/iOS/ 鸿蒙) :原生子 WebView,自由自定义宽 / 高 /top/left,支持运行时动态修改尺寸,是自定义布局核心场景。
  • nvue 页面web-view默认宽高 0,必须手动写样式 /flex:1赋值宽高才显示uni-app

一、静态固定宽高

1. 父容器约束 + CSS 百分比(通用,优先推荐)

利用外层 view 限定尺寸,web-view 继承父容器 100% 宽高,App/H5 有效,小程序无效

复制代码
<template>
  <!-- 固定高度500px,宽度100%屏幕 -->
  <view class="web-wrap" :style="{width:'100%',height:webH+'px'}">
    <web-view :src="url" class="webview" :fullscreen="false"></web-view>
  </view>
</template>
<script>
export default {
  data(){
    return {url:'https://xxx.com',webH:500}
  }
}
</script>
<style>
.web-wrap{width:750rpx;margin:0 auto;}
.webview{width:100%;height:100%;}
</style>
  • rpx 适配 :使用750rpx做宽度基准,自动适配不同手机宽度uni-app。
  • 全屏写法(App) :页面关闭原生导航navigationStyle:"custom"web-wrap{height:100vh}铺满整屏。

2. App 专属 webview-styles 属性(原生样式)

仅 App-vue 生效,直接在组件标签设置原生 webview 位置尺寸:

复制代码
<web-view 
  :src="url"
  :fullscreen="false"
  :webview-styles="{width:'100%',height:'calc(100vh - 88px)',top:88}"
/>

二、动态屏幕适配(按设备可视区自动计算宽高)

方案 1:根据系统信息动态计算高度(避让导航 / 状态栏 /tab)

通过uni.getSystemInfoSync()获取屏幕参数,扣除状态栏、自定义导航、底部安全区高度得到可用 webview 高度:

复制代码
onLoad(){
  const sys = uni.getSystemInfoSync()
  // 状态栏高度
  const statusH = sys.statusBarHeight
  // 自定义导航高度88px、底部tab 50px
  const navH = 88,tabH=50
  // 可用高度 = 可视窗口 - 状态栏 -导航 -tab
  this.webH = sys.windowHeight - statusH - navH - tabH
}

方案 2:获取父容器 DOM 真实尺寸(动态布局场景)

createSelectorQuery查询外层容器实际宽高,适配弹性布局:

复制代码
async getWrapSize(){
  return new Promise(res=>{
    uni.createSelectorQuery().in(this)
      .select('.web-wrap').boundingClientRect(res=>{res(res)}).exec()
  })
},
async onReady(){
  const rect = await this.getWrapSize()
  this.webH = rect.height
  // #ifdef APP-PLUS 同步修改原生webview尺寸
  setTimeout(()=>{
    const curWeb = this.$scope.$getAppWebview()
    const wv = curWeb.children()[0]
    wv.setStyle({height:this.webH+'px',width:rect.width+'px'})
  },300)
  // #endif
}

三、H5 内容自适应高度(H5 内容多高,webview 自动多高|最常用)

原理:H5 通过uni.postMessage把自身内容高度传给 UniApp,宿主动态修改 webview 高度,全平台兼容 (小程序 / App/H5)

① 嵌入的 H5 页面 JS(必须嵌入 H5)
复制代码
<script>
// 发送页面实际内容高度
function sendWebHeight(){
  // 取body真实滚动高度
  const h = Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)
  // 向uni宿主发消息
  uni.postMessage({data:{type:'webHeight',val:h}})
}
// 页面加载、窗口缩放、图片加载完成都重新计算
window.onload = sendWebHeight
window.addEventListener('resize',sendWebHeight)
// 图片加载完重新计算
document.querySelectorAll('img').forEach(img=>{
  img.onload = sendWebHeight
})
</script>

② UniApp 宿主页面代码

复制代码
<template>
<view :style="{width:'100%',height:webH+'px'}">
  <web-view :src="url" @message="onWebMsg" :fullscreen="false"></web-view>
</view>
</template>
<script>
export default {
  data(){return {url:'xxx',webH:600}},
  methods:{
    onWebMsg(e){
      const msg = e.detail.data[0]
      if(msg.type==='webHeight'){
        this.webH = msg.val + 20 // +20防内容截断留白
        // #ifdef APP-PLUS 同步原生webview高度
        setTimeout(()=>{
          const wv = this.$scope.$getAppWebview().children()[0]
          wv.setStyle({height:this.webH+'px'})
        },100)
        // #endif
      }
    }
  }
}
</script>

缺点:外部不可控 H5(第三方网页如百度)无法植入 JS,不能用此方案

四、App 端原生 API 精准控制 WebView(终极自定义,第三方 H5 也能用)

1. 获取原生 WebView 实例 + setStyle 修改宽高 / 坐标(仅 App)uni-app

复制代码
// 页面onReady延时获取(webview初始化需要时间)
onReady(){
  // #ifdef APP-PLUS
  setTimeout(()=>{
    // 获取当前页面原生webview
    const pageWeb = this.$scope.$getAppWebview()
    // 拿到web-view对应的子webview实例
    const subWeb = pageWeb.children()[0]
    // 动态设置:宽、高、距离顶部、左边距
    subWeb.setStyle({
      width:'100%',
      height:'700px',
      top:uni.getSystemInfoSync().statusBarHeight+88+'px',
      left:0
    })
    // App原生API主动获取H5内容高度(无需H5插JS,第三方网页可用)
    // const realH = subWeb.getContentHeight()
    // subWeb.setStyle({height:realH+'px'})
  },500)
  // #endif
}
  1. UniApp-X 专属:@contentheightchange 监听内容高度变化

    <web-view :src="url" @contentheightchange="onContentChange"/>

五、横竖屏动态适配方案

  1. 全局页面横竖屏配置(pages.json)

    "globalStyle":{
    "pageOrientation":"auto" // auto自动旋转/portrait竖屏/landscape横屏
    }

  2. 横竖屏切换重算 WebView 尺寸 :监听窗口onResize事件,重新计算宽高并更新 webview

    onResize(){
    const sys = uni.getSystemInfoSync()
    this.webH = sys.windowHeight - 状态栏-导航高度
    // #ifdef APP-PLUS
    const wv = this.scope.getAppWebview().children()[0]
    wv.setStyle({width:sys.windowWidth+'px',height:this.webH+'px'})
    // #endif
    }

H5 内部 viewport 适配(嵌入 H5 必加 meta 标签)

复制代码
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

六、使用条件编译,H5平台时使用 iframe, 其他使用 webview

复制代码
<template>
  <view class="container">
    <view class="cert__box" :style="{height:webHeight+'px',}">
      <!-- :fullscreen="true" -->
      <!-- #ifdef H5 -->
      <iframe ref="refWebView" :src="preview_url" width="100%" height="100%" frameborder="0" scrolling="no" />
      <!-- #endif -->
      <!-- #ifndef H5 -->
      <web-view ref="refWebView" :src="preview_url" :update-title="false"></web-view>
      <!-- #endif -->
    </view>
    <view class="footer_btn"></view>
  </view>
</template>

<script>
  import { getScreenWH } from "@/common/index.js"
  export default {
    data() {
      return {
        preview_url: "https://www.csdn.net/",
        footHeight:77
      }
    },

    computed: {
      webHeight() {
        console.log(getScreenWH().height);
        return getScreenWH().height
      }
    },

    onLoad(opt) {

    },

    onShow() {
    },

    onReady() {
      console.log("onReady >>>>>> ");
      // #ifdef H5
      if (this.$refs.refWebView) {
        uni.showLoading()
        this.$refs.refWebView.onload = () => {
          // 加载成功
          console.log("iframe loading finish >> onload ");
          uni.hideLoading()
        };
      }
      // #endif
      
      // 获取元素高度
      let _this = this
      const query = uni.createSelectorQuery().in(this);
      query.select('.footer_btn').boundingClientRect(data => {
          console.log("footer_btn",data)
          _this.footHeight = data.height
      }).exec();

    },

    onUnload() {
     
    },

    methods: {

      init() {
        apiGetCollectAuthSignUrl(this.applyId, this.taskId).then(res => {
          if (res && res.data) {
            this.preview_url = res.data.preview_url
            this.$forceUpdate()
          }
        }).catch(e=>{
          this.$toast(e.msg)
        })
      },

      handleNext() {
        uni.switchTab({
          url:"/pages/index/index"
        })
      }

    }
  }
</script>
<style>
  .page {
    background-color: rgba(242, 244, 245, 1) 30.77%;
  }
</style>
<style scoped lang="scss">
  .container {
    background: linear-gradient(360deg, rgba(242, 244, 245, 1) 30.77%, #F54F3C 76.44%);
    width: 750rpx;
    min-height: 800px;
    overflow: hidden;

    .tip-container {
      margin: 40rpx 30rpx;

      .tip__tag {
        font-weight: 500;
        font-size: 36rpx;
        color: #FFFFFF;
        text-align: left;
      }

      .tip_content {
        font-weight: 400;
        font-size: 24rpx;
        color: #FFFFFF;
        line-height: 40rpx;
        text-align: left;
        display: block;
      }
    }

    .cert__box {
      background: #FFFFFF;
      border-radius: 16rpx;
      min-height: 800rpx;
      margin: 30rpx;
      padding: 24rpx;
    }

    .footer_btn {
      position: fixed;
      left: 0;
      bottom: 0rpx;
      padding-bottom: 50rpx;
      width: 100%;
      height: 50px;
      background-color: #fff;
      z-index: 9999;

      .button {
        height: 94rpx;
        font-weight: 500;
        font-size: 32rpx;
        color: #FFFFFF;
        line-height: 94rpx;
        text-align: center;
        background: linear-gradient(52deg, #FA6C4A 0%, #F34A33 100%);
        border-radius: 1332rpx;
        margin: 24rpx;
      }

      .button_disabled {
        background: #EAEAEA;
        color: #AAAAAA;
      }
    }
  }
</style>
相关推荐
半个烧饼不加肉1 小时前
JS 底层探究-- 调用栈(Call Stack)
开发语言·前端·javascript
子午2 小时前
基于DeepSeek的智能校园教务管理系统~Web管理系统+Vue3+Python+DeepSeek智能问答
前端
change_fate2 小时前
ERR_PNPM_WORKSPACE_PKG_NOT_FOUND In ...
java·服务器·前端
超人不会飞_Jay2 小时前
26.6.3Vue笔记
前端·vue.js·笔记
御坂100272 小时前
Vue - @change应用实现下拉框联动功能
前端·javascript·vue.js
小雨下雨的雨2 小时前
基于 Electron 运行时的鸿蒙PC桌面应用-安全可靠的随机密码生成工具
前端·javascript·华为·electron·前端框架·鸿蒙
瘦瘦瘦大人2 小时前
Vue 项目实现关闭/刷新浏览器窗口前的离开确认提示
前端·javascript·vue.js
大家的林语冰2 小时前
尤雨溪官宣:Vite+ 全员加盟 Cloudflare,正式进军全栈开发和 AI 部署云平台!
前端·javascript·vite
独特的螺狮粉2 小时前
金属硬度与熔点对照表APP - 通过鸿蒙PC Electron框架完整技术实现指南
前端·javascript·electron·前端框架·开源·鸿蒙