vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)

简介: vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)

什么是固定宽高比容器?

定义:

无论浏览器窗口或页面元素如何变化,容器的宽度和高度永远保持固定的比例,如16:9。

应用场景:

如大屏自适应,内部元素对容器宽高比依赖很高的复杂模块布局等。

纯CSS实现固定宽高比的容器

原理

  • padding-top的值为百分比时,最终padding-top的计算值 = 百分比 * 当前元素宽度的计算值,从而通过padding-top将容器撑开。
  • 为容器添加样式 box-sizing: border-box; 则容器的高度 = padding-top的计算值,从而实现容器高度根据容器的宽度按百分比自适应变化。
  • 使用“子绝父相”,让容器中的内容完全覆盖容器。

cssRatioContainer.vue

<template>
  <div class="box" :style="ratioStyle">
    <div class="content" :style="contentStyle">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    ratio: {
      type: Number,
      default: 1,
    },
    overflow: {
      type: String,
      default: "auto",
    },
    overflowX: {
      type: String,
    },
    overflowY: {
      type: String,
    },
  },
  computed: {
    ratioStyle() {
      let ratio = (1 / this.ratio) * 100;
      if (ratio == null || Number.isNaN(ratio)) {
        ratio = 100;
      }
      if (typeof ratio !== "string" || !ratio.endsWith("%")) {
        ratio = ratio + "%";
      }
      return `padding-top: ${ratio};`;
    },

    contentStyle() {
      const styles = [];
      if (this.overflow) {
        styles.push("overflow:" + this.overflow);
      }
      if (this.overflowX) {
        styles.push("overflow-x:" + this.overflowX);
      }
      if (this.overflowY) {
        styles.push("overflow-y:" + this.overflowY);
      }
      return styles.join(";");
    },
  },
};
</script>

<style scoped>
.box {
  position: relative;
  box-sizing: border-box;
}
.content {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
</style>

JS实现固定宽高比的容器

原理

  • 通过js获取容器的宽度计算值后,按宽高比计算出容器的高度,并赋值给容器。

jsRatioContainer.vue

<template>
  <div id="jsRatioContainerBox" class="box" :style="contentStyle">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    ratio: {
      type: Number,
      default: 1,
    },
    overflow: {
      type: String,
      default: "auto",
    },
    overflowX: {
      type: String,
    },
    overflowY: {
      type: String,
    },
  },
  data() {
    return {
      myHeight: "",
    };
  },
  computed: {
    contentStyle() {
      const styles = [];
      if (this.myHeight) {
        styles.push("height:" + this.myHeight);
      }
      if (this.overflow) {
        styles.push("overflow:" + this.overflow);
      }
      if (this.overflowX) {
        styles.push("overflow-x:" + this.overflowX);
      }
      if (this.overflowY) {
        styles.push("overflow-y:" + this.overflowY);
      }
      return styles.join(";");
    },
  },
  mounted() {
    this.setHeight();
    window.addEventListener("resize", () => {
      this.setHeight();
    });
  },
  watch: {
    ratio() {
      this.setHeight();
    },
  },
  methods: {
    // 根据宽高比和当前宽度,设置最终的高度
    setHeight() {
      this.$nextTick(() => {
        let myDom = document.getElementById("jsRatioContainerBox");
        let width = window.getComputedStyle(myDom)["width"];
        this.myHeight =
          Number(width.replace("px", "")) * (1 / this.ratio) + "px";
      });
    },
  },
};
</script>

<style scoped>
.box {
  width: 100%;
}
</style>

使用范例

<template>
  <div class="father">
    <h2>CSS实现固定宽高比的容器</h2>
    <CssRatioContainer
      ref="CssRatioContainer"
      id="CssRatioContainer"
      :ratio="ratioWidth / ratioHeight"
    >
      <div class="itemBox" v-for="item in 100" :key="item">段落{{ item }}</div>
    </CssRatioContainer>
    <p>容器的宽度为:{{ mySize.width }}</p>
    <p>容器的高度为:{{ mySize.height }}</p>
    <label>容器的宽高比:</label>
    <input
      class="inputStyle"
      type="number"
      v-model="ratioWidth"
      @input="getSize"
    />
    <input
      class="inputStyle"
      type="number"
      v-model="ratioHeight"
      @input="getSize"
    />
    <h2>JS实现固定宽高比的容器</h2>
    <JsRatioContainer :ratio="ratioWidth / ratioHeight">
      <div class="itemBox" v-for="item in 100" :key="item">段落{{ item }}</div>
    </JsRatioContainer>
  </div>
</template>
<script>
import CssRatioContainer from "./cssRatioContainer.vue";
import JsRatioContainer from "./jsRatioContainer.vue";
export default {
  components: { CssRatioContainer, JsRatioContainer },
  mounted() {
    this.getSize();
    window.addEventListener("resize", () => {
      this.getSize();
    });
  },
  methods: {
    getSize() {
      this.$nextTick(() => {
        let myDom = document.getElementById("CssRatioContainer");
        let myComputedStyle = window.getComputedStyle(myDom);
        this.$set(this.mySize, "height", myComputedStyle.height);
        this.$set(this.mySize, "width", myComputedStyle.width);
      });
    },
  },

  data() {
    return {
      mySize: {},
      ratioWidth: 6,
      ratioHeight: 1,
    };
  },
};
</script>
<style scoped>
.father {
  max-width: 1200px;
  margin: 20px;
}
.itemBox {
  background: red;
  border: 1px solid yellow;
}
.inputStyle {
  width: 60px;
  text-align: center;
}
</style>

目录
相关文章
|
Web App开发 前端开发 JavaScript
前端新利器:CSS容器查询——让组件真正“自适应
前端新利器:CSS容器查询——让组件真正“自适应
570 83
|
前端开发 API 开发者
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
本文由黑臂麒麟(6年前端经验)撰写,介绍ArkTS开发中的常用基础组件与布局组件。基础组件包括Text、Image、Button等,支持样式设置如字体颜色、大小和加粗等,并可通过Resource资源引用统一管理样式。布局组件涵盖Column、Row、List、Grid和Tabs等,支持灵活的主轴与交叉轴对齐方式、分割线设置及滚动事件监听。同时,Tabs组件可实现自定义样式与页签切换功能。内容结合代码示例,适合初学者快速上手ArkTS开发。参考华为开发者联盟官网基础课程。
1430 75
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
|
存储 前端开发 JavaScript
仿真银行app下载安装, 银行卡虚拟余额制作app,用html+css+js实现逼真娱乐工具
这是一个简单的银行账户模拟器项目,用于学习前端开发基础。用户可进行存款、取款操作,所有数据存储于浏览器内存中
|
人工智能 程序员 UED
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
941 21
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
数据采集 JavaScript Android开发
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
713 7
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
|
前端开发 JavaScript
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
833 14
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
前端开发
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
1267 1
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
html+js+css实现的建筑方块立体数字时钟源码
html+js+css实现的建筑方块立体数字时钟源码
689 33
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
317 24
纸屑飘落生日蛋糕场景js+css3动画特效
纸屑飘落生日蛋糕CSS3动画特效是一款js+css3制作的全屏纸屑飘落,生日蛋糕点亮庆祝动画特效。
276 3