使用ResizeObserver和媒体查询获得相同的结果

问题描述

我已全局定义breakpoints

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

我也有media queries根据先前的padding-top来定义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-toppadding-bottom(媒体查询)不会与paddingLeft(ResizeObserver)同时改变,我也不知道为什么以及如何改变解决

-编辑--

我希望现在能更好地理解它:

请查看jsfiddle并调整结果大小,以查看div如何在不同时间更改padding-toppaddingLeft

解决方法

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"
  }
})

Demo