【问题标题】:How to use EMs in CSS Media Queries aligned with JavaScript events?如何在与 JavaScript 事件对齐的 CSS 媒体查询中使用 EM?
【发布时间】:2016-10-09 02:42:20
【问题描述】:

我在一个项目上工作了一段时间,我认为 em 在表示长度时是 de facto 单位。

我通常的做法是将 bodyhtml 元素设置为所需的 px 大小,并将所有其他元素设置为 1em。之后,其余的都在 em 中。直到今天早上,这似乎是一个不错的计划,直到我发现 媒体查询 似乎没有考虑到基础 bodyhtml 像素值。实际上,它们似乎采用了浏览器的默认字体大小,这似乎是一种非常奇怪的行为。我还找到了this article,这似乎证实了这一点。

我做了一个小的 JsFiddle 示例,它准确地显示了这种行为:

https://jsfiddle.net/5dq3kq2t/2/

html, body {
    font-size: 20px;
}

* {
  font-size: 1em;
}

#divOf50Em {
  width: 50em;
  border: solid 1px red;
}

#cell2 {
  display: none;
}

@media screen and (min-width: 50em) { /* 1000px, in theory (50 * 20px) */
  #cell1 {
    display: none;
  }

  #cell2 {
    display: table-cell;
  }

}

实验很简单,表格默认显示值“1”,直到满足50em min-width媒体尺寸.应显示值“2”。我还放置了一个 div,其大小为 50em 以显示何时应该触发该行为,并确认 CSS 在媒体查询之外工作。

如果您调整此实验的输出大小,您会认为两个值之间的偏移会发生在 1000px 值处,即 50em * 20px ,但事实并非如此,它发生在 800px50em * 16px (默认浏览器字体大小 - 如果这样当然是你的默认尺寸)。

我显然不确定为什么会发生这种情况,但我有两个问题:

  1. 有没有办法解决这个问题(例如覆盖默认浏览器字体大小 从 CSS 的角度来看)
  2. 如果没有,JavaScript 中有没有办法访问浏览器的默认值 字体大小?我找不到此信息。

否则,当使用媒体宽度和 ems 时,似乎不可能有一个与媒体查询对齐的脚本,因为我们不能相信浏览器的字体大小将始终为 16 像素

如果是这种情况,我的最后一个问题是,有没有办法在不返回像素的情况下对齐媒体查询和 JavaScript?我更喜欢相对单位而不是静态像素,它们通常使样式更简单。

【问题讨论】:

  • 不确定问题是什么? 1em 等价于 16px
  • @guest271314 如果你覆盖它,请检查我的 JsFiddle。您可以从 CSS 角度覆盖 16px,也可以从浏览器设置角度覆盖。
  • 有什么问题?
  • 样式表级联。后一个设置会覆盖前一个设置。也就是说,您重置或覆盖以前在html, body { font-size: 20px; } 设置的20px1em* { font-size: 1em; }
  • @guest271314 问题是给定的 html 和 body 为 20px,其他所有内容也应为 20px(对于 1em)。在所有样式表中,前提是 1em,从顶层开始 = 20px。问题是,媒体查询仍然认为 1em = 16px。此外,第二个问题是这个 16px 值似乎来自浏览器的样式表,这意味着它可以更改。我正在寻找一种方法来使这个值可预测。

标签: javascript html css responsive-design media-queries


【解决方案1】:

经过更多研究,

  1. 似乎无法在 CSS 或 JavaScript 中覆盖 1em value = browser default font-size in pixel
  2. 媒体查询是指浏览器,而不是似乎是正常/预期行为的 HTML 元素。
  3. 可以使用 JavaScript 获取浏览器的默认字体大小(以像素为单位),考虑到这只是权宜之计,我不会尝试。
  4. 真正的解决方案是要求所有媒体查询都被 JavaScript 覆盖,这将变得非常繁重且难以扩展。
  5. 使用其他单元可能会解决一些挑战,但至今仍会导致跨浏览器兼容性问题。

【讨论】:

  • “可以通过使用 JavaScript 获得浏览器的默认字体大小(以像素为单位),我不会尝试,因为它只是一个权宜之计。” 为什么会这样方法是止损?
  • @guest271314 因为第 4 点。即使我们让 JavaScript 与媒体查询保持一致,媒体查询也不可靠,因为它们是基于浏览器设置的。所以从技术上讲,它可以解决其中一个问题,但要解决似乎更全球性的问题的一部分,将需要做很多工作。
  • 如果要求将单位设置为 50x 浏览器设置,或在 css 应用的设置,解决方法是将检索到的属性值乘以 50
  • @guest271314 我不确定我是否在关注你,但假设我们坚持使用 EM,因为它们是最受支持的“动态单位”,主要问题是保持根元素的像素值与媒体查询中使用的那个。这意味着,例如,如果您在移动显示器上更改根元素的 EM 值,则需要使用匹配的 EM 值重写所有媒体查询。这就是我想到的“真正的解决方案”,因为这也是跨浏览器友好的。但我不确定所有这些努力是否值得,并且可能无法很好地扩展。
  • 您也可以使用calc() 动态调整属性值。
【解决方案2】:

一种可能的解决方法是通过使用getComputedStyle 获取body 的子节点的font-size,将媒体查询设置为windowload 事件

:root, body {
    --size: 20px;
    --opt: 50rem;
    --def: 1rem;
    font-size: var(--size);
}

* {
  font-size: var(--def);
}

#divOf50Em {
  width: var(--opt);
  border: solid 1px red;
}

#cell2 {
  display: none;
}

window.onload = function() {
  document.getElementById('documentWidth').innerHTML = 'Window width: ' 
    + document.documentElement.clientWidth + 'px';

  var n = 50;

  var fontSize = parseInt(getComputedStyle(document.getElementById("divOf50Em"))
                 .getPropertyValue("font-size"));

  var css = `@media screen and (min-width:${fontSize * n}px) { 
               /* 1000px, in theory (50 * 20px) */
               #cell1 {
                 display: none;
               }

               #cell2 {
                 display: table-cell;
               }
             }`;

  var style = document.createElement("style");
  style.textContent = css;
  document.head.appendChild(style);

  window.addEventListener('resize', function() {
    document.getElementById('documentWidth').innerHTML = 'Window width: ' +
      document.documentElement.clientWidth + 'px';
  });
}

plnkrhttp://plnkr.co/edit/lncvWwBWc18C76UYhPnf?p=preview

【讨论】:

  • 非常令人印象深刻。你知道是否有一种简单的方法可以使这个浏览器更兼容?我知道我没有提到它,所以从技术上讲你解决了这个问题,但这个版本不能真正用于标准网站。
  • @NicolasBouvrette 您可以用var() 函数手动设置属性;还使用 + 操作符将 template literal 替换为字符串连接;将 fork plnkr 来演示示例
  • @NicolasBouvrette 请参阅第 2 版中的 plnkr.co/edit/lncvWwBWc18C76UYhPnf?p=preview。版本 3 使用 inheritfont-size 属性 * 选择器; calc(20 * 50)width 设置为 #divOf50Em 元素
  • 仍然很酷,但我还不能让它在 IE 中工作。我也不能在我的场景中使用 REM,因为浏览器支持可能超出了这个问题的范围。我不确定这个解决方案是否可以在我当前的用例中使用,而无需执行可能影响渲染和浏览器性能的更繁重的脚本。这就是为什么我不确定这实际上是一个值得解决的问题(如果我们考虑跨浏览器的挑战)。
  • 已经有一段时间没试过ie了。 ie不支持calc()吗?
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 2021-07-30
  • 2022-11-25
  • 1970-01-01
  • 2021-11-15
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多