先看效果:

众所周知,我们平时获取获取窗口的宽高都是 JavaScript 获取的,要不然直接通过 JavaScriptresize 监听页面宽高变化。

但现在不一样了!我们可以直接通过 CSS 获取 window 的尺寸,并且可以通过变量来进行使用。

在我第一眼看到这个消息的感觉是不可置信!但这是真的,下面我将带大家复习一下在 Vue、React、Svelte 以及原生 JavaScript 中如何获取 window 尺寸,然后带大家一览新的获取方案!

示例

点击马上掘金中间的左右箭头,可以查看高度的监听。

本来是先写的传统方案获取尺寸,但想到大家可能都了解怎么实现,就放在了后面,大家有需要可以自己在后面复习一下。😊😊

CSS 获取窗口大小

属性定义

通过 CSS 新增的 @property ,可以让我们创建自定义属性,并给它定义其类型以及初始值(初始值在不经改变的情况下一直是该值)。
利用这个功能,我们可以创建一个宽高属性出来。

 1@property --w_raw {
 2  syntax: '<length>';
 3  inherits: true;
 4  initial-value: 100vw;
 5}
 6
 7@property --h_raw {
 8  syntax: '<length>';
 9  inherits: true;
10  initial-value: 100vh;
11}

这其中:

  • syntax 是这个属性的单位,我们给它设置为 <length> ,以便于让浏览器理解这是一个长度单位
  • initial-value 是这个属性的初始值,如果不修改,它一直是 100vw
  • inherits 是这个属性是否可以被继承,设置 false | true 都不影响使用

计算为数字

现在我们有一个 CSS 能识别的 length ,但这个单位我们不认识,所以我们要通过 CSS 提供的数学函数计算出真正的数字长度,因此我们要使用 CSS 数学工具中的 atans2(y, x)tan()

  • atans(y, x) :返回点 (x, y) 到原点的角度(弧度单位)
  • tan() :返回给定角度的正切

通过上面这两个数学函数,计算 --w_raw--h-raw1px 之间角度的正切值,进而得到宽高的纯数字。

将数字展示到页面

通过 CSS 的计数器将数字展示到页面上。

这其中:

  • counter(w) :表示计数器 w 的值
  • counter-reset: w var(--w) :表示计数器 w 被重置为 —w 的值
 1body::before {
 2  content: counter(w) 'x' counter(h);
 3  counter-reset: h var(--h) w var(--w);
 4}

完整代码

 1@property --w_raw {
 2  syntax: '<length>';
 3  inherits: false;
 4  initial-value: 100vw;
 5}
 6
 7@property --h_raw {
 8  syntax: '<length>';
 9  inherits: false;
10  initial-value: 100vh;
11}
12
13:root {
14  --w: tan(atan2(var(--w_raw), 1px));
15  --h: tan(atan2(var(--h_raw), 1px));
16}
17
18body::before {
19  position: fixed;
20  top: 50%;
21  left: 50%;
22  transform: translate(-50%, -50%);
23  content: counter(w) 'x' counter(h);
24  counter-reset: h var(--h) w var(--w);
25}

复习一下传统开发中的获取方案

JavaScript

在原生 JavaScript 中,我们通过 innerWidth 获取窗口宽度,然后通过监听 resize 变化重新赋值。

 1let windowWidth = window.innerWidth;
 2
 3function handleResize = () => windowWidth = window.innerWidth
 4
 5window.addEventListener('resize', handleResize)
 6window.addEventListener('resize', handleResize)

Vue

在 Vue3 中,我们可以通过自定义 Hook 的方式实现 resize

 1import { ref, onMounted, onUnmounted } from 'vue';
 2
 3export function useWindowWidth() {
 4  const windowWidth = ref(window.innerWidth);
 5
 6  const handleResize = () => {
 7    windowWidth.value = window.innerWidth;
 8  };
 9
10  onMounted(() => {
11    window.addEventListener('resize', handleResize);
12  });
13
14  onUnmounted(() => {
15    window.removeEventListener('resize', handleResize);
16  });
17
18  return windowWidth;
19}

由于 Vue2 不支持自定义 Hook ,我们则需通过 Mixin 的方式实现。

 1export const windowMixin = {
 2  data() {
 3    return {
 4      windowWidth: window.innerWidth
 5    };
 6  },
 7  methods: {
 8    handleResize() {
 9      this.windowWidth = window.innerWidth;
10    }
11  },
12  mounted() {
13    window.addEventListener('resize', this.handleResize);
14  },
15  beforeDestroy() {
16    window.removeEventListener('resize', this.handleResize);
17  }
18};

React

React 也是一个简单的 Hook

 1import { useState, useEffect } from 'react';
 2
 3export function useWindowWidth() {
 4  const [windowWidth, setWindowWidth] = useState(window.innerWidth);
 5
 6  useEffect(() => {
 7    const handleResize = () => {
 8      setWindowWidth(window.innerWidth);
 9    };
10
11    
12    handleResize();
13
14    
15    window.addEventListener('resize', handleResize);
16
17    
18    return () => {
19      window.removeEventListener('resize', handleResize);
20    };
21  }, []);
22
23  return windowWidth;
24}

通过上面文章,相信大家可以学会 CSS 如何实现监听 window 宽度,并且可以举一反三的利用该原理做更多的事情。✌️

同时我们还复习了多种语言中如何监听 window 宽度。

个人笔记记录 2021 ~ 2025