首页 > 解决方案 > 使用 ResizeObserver 和媒体查询获得相同的结果

问题描述

我已经全局定义breakpoints

breakpoints: {
  xs: "0px",
  sm: "320px",
  md: "672px",
  lg: "1056px",
  xl: "1312px",
},

我还必须根据之前media queries定义padding-topand :padding-bottombreakpoints

@media (min-width: 672px) {
    padding-top: 2rem;
    padding-bottom: 2rem;
}
@media (min-width: 0px) {
    padding-top: 1rem;
    padding-bottom: 1rem;
}

最后,我ResizeObserver用来观察document.body和设置paddingLeft,例如:

const observer = new ResizeObserver(([entry]) => {
  if (entry.contentRect.width >= Number.parseInt(breakpoints.xl)) {
    document.body.style.paddingLeft = "10em"
  } else if (entry.contentRect.width >= Number.parseInt(breakpoints.lg)) {
    document.body.style.paddingLeft = "10em"
  } else if (entry.contentRect.width >= Number.parseInt(breakpoints.md)) {
    document.body.style.paddingLeft = "10em"
  } else if (entry.contentRect.width >= Number.parseInt(breakpoints.xs)) {
    document.body.style.paddingLeft = "5em"
  }
})

observer.observe(document.body)

问题是padding-topor padding-bottom(媒体查询)不会同时改变paddingLeft(ResizeObserver),我不知道为什么以及如何解决。

--- 已编辑 ---

我希望现在可以更好地理解:

请查看jsfiddle并调整结果大小以查看在不同时间的div变化padding-top和变化。paddingLeft

标签: javascriptcssdomwindow-resize

解决方案


是元素的contentRect内容框,没有填充、边框和边距。由于body元素的默认margin: 8px;和滚动条宽度,entry.contentRect.width将比窗口宽度小 33px。

16px (body margin) + 17px (scollbar width) = 33px

参考

https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentRect

https://xebia.com/blog/resize-observer-api-detecting-element-size-change/

或者,您可以使用MediaQueryList.onchange

MediaQueryList 对象存储有关应用于文档的媒体查询的信息,支持针对文档状态的即时和事件驱动匹配。

一个断点的例子

const element = document.getElementById("test");

var mql = window.matchMedia('(min-width: 672px)');

mql.addEventListener("change", (e) => {
  if (e.matches) {
    element.style.paddingLeft = "10em"
  } else {
    element.style.paddingLeft = "unset"
  }
})

演示


推荐阅读