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

Get the same result with ResizeObserver and media query

我全局定义了breakpoints:

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

我还有 media queries 来定义 padding-toppadding-bottom,基于之前的 breakpoints:

@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 将比 window 宽度小 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

A MediaQueryList object stores information on a media query applied to a document, with support for both immediate and event-driven matching against the state of the document.

示例 有一个断点

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