如何在与JavaScript事件一致的CSS媒体查询中使用EMs?

如何在与JavaScript事件一致的CSS媒体查询中使用EMs?,javascript,html,css,responsive-design,media-queries,Javascript,Html,Css,Responsive Design,Media Queries,我在一个项目上工作了一段时间,我认为在表达长度时,使用em是事实上的单位 我通常的处理方法是将body和html元素设置为所需的px大小,将所有其他元素设置为1em。之后,其余的都在em中。直到今天早上,这似乎是一个不错的计划,直到我发现媒体查询似乎没有考虑基本体和HTMLPX值。事实上,它们似乎采用浏览器的默认字体大小,这似乎是一种非常奇怪的行为。我还发现了似乎证实这一点的证据 我已经完成了一个小的JSFIDLE示例,它正好显示了这种行为: 实验很简单,默认情况下,表格显示值“1”,直到满足

我在一个项目上工作了一段时间,我认为在表达长度时,使用em是事实上的单位

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

我已经完成了一个小的JSFIDLE示例,它正好显示了这种行为:

实验很简单,默认情况下,表格显示值“1”,直到满足50em最小宽度介质大小。应显示值“2”的值。我还放置了一个大小为50em的div,以显示何时应该触发该行为,并确认CSS在媒体查询之外工作

如果你调整这个实验的输出大小,你会期望这两个值之间的偏移会发生在1000px的值上,该值是50em*20px,但它不会发生,它会发生在800px的值上,该值是50em*16px(默认浏览器字体大小-当然,如果这是您的默认大小)

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

  • 是否有办法解决此问题(例如,覆盖默认浏览器字体大小) (从CSS的角度)
  • 如果没有,JavaScript中是否有方法访问浏览器的默认设置 字体大小?我找不到这个信息
  • 否则,在使用media width和ems时,似乎不可能有一个脚本与某些行为的媒体查询保持一致,因为我们不能依赖浏览器的字体大小始终为16px

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

    经过更多研究

  • 看起来没有办法覆盖CSS或JavaScript中的
    1em value=browser默认字体大小(像素)
  • 媒体查询指的是浏览器,而不是HTML元素,这似乎是正常/预期的行为
  • 通过使用JavaScript可以获得浏览器的默认字体大小(以像素为单位),我不会尝试使用JavaScript,因为这只是权宜之计
  • 一个真正的解决方案将要求所有媒体查询都被JavaScript覆盖,这将变得非常繁重且难以扩展
  • 使用其他单位可能会解决一些挑战,但会导致跨浏览器的兼容性问题,直到今天

  • 一种可能的解决方法是,通过使用
    getComputedStyle

    :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;
    }
    


    plnkr

    不确定问题是什么?
    1em
    相当于
    16px
    @guest271314如果您不覆盖它,请检查我的JSFIDLE。您可以从CSS透视图覆盖16px,也可以从浏览器设置透视图覆盖16px。问题是什么?样式表层叠。后一个设置覆盖前一个设置。也就是说,您可以重置,或者verwrite之前将
    20px
    at
    html,body{font-size:20px;}
    设置为
    1em
    at
    *{font-size:1em;}
    @guest271314问题是,给定的html和body都是20px,其他所有内容都应该是20px(对于1em).在所有样式表中,前提是1em,从顶层开始=20px。问题是,媒体查询仍然认为1em=16px。此外,第二个问题是,这个16px值似乎来自浏览器的样式表,这意味着它可以更改。我正在寻找一种方法使这个值可预测。“通过使用JavaScript,可以获得浏览器的默认字体大小(以像素为单位),我不会尝试使用JavaScript,因为这只是权宜之计。"为什么这种方法是权宜之计?@guest271314,因为第4点。即使我们将JavaScript与媒体查询对齐,媒体查询也不会可靠,因为它们基于浏览器设置。因此从技术上讲,它可以解决其中一个问题,但只解决一个看起来更全球化的问题的一部分需要大量工作l、 如果要求将一个单位设置为50x浏览器设置,或者设置应用于
    css
    ,解决方法是将一个属性的检索值乘以
    50
    @guest271314,我不确定我是否在跟踪您,但假设我们坚持使用EMs,因为它们是最受支持的“动态单位”,主要问题是将根元素的像素值与媒体查询中使用的像素值保持一致。这意味着,如果您在移动显示器上更改根元素的EM值,则需要使用匹配的EM值重写所有媒体查询。这是我心目中的“真正解决方案”因为这将是跨浏览器友好的。但我不确定它是否值得所有这些努力,并且可能无法很好地扩展。您也可以使用
    calc()
    动态调整属性值。非常令人印象深刻。你知道有没有一种简单的方法可以让它更兼容浏览器吗?我知道我没有提到它,所以从技术上来说你解决了这个问题,但这个版本不能真正用于标准网站。@NicolasBouvrette你可以用
    var()代替
    用于手动设置属性的函数;还可以使用
    +
    运算符将
    模板文字
    替换为字符串连接;将分叉plnkr进行演示example@NicolasBou
    :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';
      });
    }