CSS字体大小(响应式),相对于设备分辨率?

Posted

技术标签:

【中文标题】CSS字体大小(响应式),相对于设备分辨率?【英文标题】:CSS Font size (responsive), relative to device resolution? 【发布时间】:2017-04-25 00:47:15 【问题描述】:

假设我们有以下test.htm

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <style type="text/css">
.testdiv, .testdivB, .testdivC 
  width: 50%;
  height: 30%;
  margin: 6px;
  border: 2px solid gray;
  font-size: 4em;

.testdivB 
  font-size: 12px;

.testdivC 
  font-size: 30pt;

  </style>
</head>

<body>

  <div class="testdiv">Test one writing</div>
  <div class="testdivB">Test another writing</div>
  <div class="testdivC">Test three writing</div>

</body>
</html>

我尝试在 Chromium 中使用开发者工具对此进行测试,该工具允许我模拟不同的设备;这里:

* Apple iPhone 4        : device resolution  320 x  480 , a/r 0.666667
* Google Nexus 10       : device resolution  800 x 1280 , a/r 0.625
* Amazon Kindle Fire HDX: device resolution 1600 x 2560 , a/r 0.625

结果是这样的:

在此示例中,所有设备都是纵向的,并且具有“几乎”相同的纵横比 (~ 0.6+),即使它们的分辨率差异很大。

因此,在前两种情况下,相对于设备屏幕大小,我得到的字体大小大致相同,这是我想要实现的(尽管我很困惑testdivB 也显示几乎相同的大小,但它应该更小) - 这一切都很好。

但是,在第三个示例中,在具有最大分辨率的设备上,testdivB(在px 中定义)相对于设备屏幕尺寸要小得多。 testdivA 也不足为奇,因为em 是相对于浏览器的“计算字体大小”而言的——如果我没记错的话,它也以像素表示。

但是,我认为pt 会考虑设备屏幕分辨率,但它似乎没有:

http://www.w3.org/Style/Examples/007/units.en.html

过去,CSS 要求实现即使在计算机屏幕上也能正确显示绝对单位。但由于错误实现的数量超过了正确实现的数量,而且情况似乎没有改善,CSS 在 2011 年放弃了这一要求。目前,绝对单位必须仅在打印输出和高分辨率设备上正确工作。

好的,那么我有哪些选项可以在所有三种情况下实现大致相同的字体大小(相对于设备屏幕大小):

如果我不想使用 javascript(仅 HTML + CSS)? 如果我确实想使用 JavaScript(我猜有一种方法可以查询设备屏幕 - 而不是视口 - 分辨率,但我不确定是否真的有)?

【问题讨论】:

我相信媒体查询可以在这里与 Roberrrt 的答案一起使用,并使用类而不是 ID,并根据 Roberrrt 的代码使用相同的类名但大小不同,所以你最终会得到类似 @987654335 的东西@ 在不同的媒体查询和 font-size: calc(Xem + Xvmin); 类型的事物中。不过,这只是我的 “2 美分” 我很好奇,我的一个解决方案真的有帮助/有效吗:)? 确实,@Teepeemm,应该是.testdivC - 我更正了,但现在我不确定截图是用错误的.testdivB 还是正确的.testdivC (但看起来它是用正确的) 嗨@Roberrrt,你的回答我已经posted a comment,但它似乎在那里迷路了;我现在还有基于 JavaScript 的posted my own answer,它应该更详细地解释我在寻找什么;简而言之,我的问题是vmin 是用视口表示的,而不是设备分辨率,如果在桌面上使用并且浏览器不是“全屏”,这可能会给出错误的结果。 【参考方案1】:

不久前,我写了一个关于如何使用纯 HTML/CSS 实现此目的的小教程/示例:

响应单元 (vmin/vmax)

#small 
    font-size: calc(1em + 1vmin);


#medium 
    font-size: calc(1em + 2vmin);


#large 
    font-size: calc(1em + 3vmin);
<div id="small">Small text</div>
<div id="medium">Medium text</div>
<div id="large">Large text</div>

规则vmin 在您的上下文中非常有用。它需要 vmin: 屏幕最小边的 1/100。不管方向。将它与 calc() 中的基本 1em 结合起来,为我们提供了一种在 font-size 上应用小型自定义响应方面的好方法。

替代方法 (vw/vh)

#small 
    font-size: calc(1em + 1vw);


#medium 
    font-size: calc(1em + 2vw);


#large 
    font-size: calc(1em + 3vw);
<div id="small">Small text</div>
<div id="medium">Medium text</div>
<div id="large">Large text</div>

如果您希望对实际纵横比进行更多控制,我建议您使用vw 而不是vmin。视口宽度 (vw) 占视口宽度的 1/100。

基于视口纵横比的响应单元(vminvmax):

#test1 
    font-size: calc((.4em + 1vmin) + (.4em + 1vmax));


#test2 
    font-size: calc((.4em + 2vmin) + (.4em + 2vmax));


#test3 
    font-size: calc((.4em + 3vmin) + (.4em + 3vmax));
<div id="test1">Small text</div>
<div id="test2">Medium text</div>
<div id="test3">Large text</div>

我对这个解决方案非常满意,这种方式允许我们同时考虑视口宽度和长度。我们将基本字体大小一分为二(在本例中为 .4em),然后将其乘以 1vmin 和 1vmax,然后将这两个值相加来确定字体大小。

【讨论】:

巧合的是,前段时间我也浏览了几篇关于同一主题的文章。只是在这里大声思考;如果使用一个类,然后根据屏幕大小将其应用于媒体查询,这不是也有意义吗?由于 id 是唯一的。 对不起,我不能提供一个小提琴,但我很确定你知道我的意思 ;-) 最后,我最终使用了不同字体大小的媒体查询。 @Roberrrt 但我肯定会尝试你的方法:-) 结合起来会很有意义,让我总结一下自己的网站来测试一些东西。 @Fred-ii- 我通常选择 20em/40em/80em 媒体查询断点,并在其上“增强”基本字体大小,calc(1em + 1vw)。 calc(1.2em + 1vw)。 calc(1.5em + 1vw). 我认为您可以将(.4em + 1vmin) + (.4em + 1vmax) 更改为(.8em + 1vw + 1vh)。令我惊讶的是,没有一种方便的方式可以说“使其成为正常尺寸”并在所有设备上都可读。【参考方案2】:

好的,我想我找到了一个我可以使用的解决方案,它使用 JavaScript。使用下面粘贴的代码,我现在在 Chromium 开发人员工具中在不同设备上进行测试时得到了这个:

正如所见,第一个 div 的相对大小 .testdivem 的规范现在跨设备大小保留(这是我想要的); px 在第二个 div 中,正如预期的那样不会保留相对大小——pt 规范的第三种情况也没有。

我遇到的第一个问题是如何获得设备分辨率。请注意,vwvh - 以及 vminvmax - 与 viewport 大小相关,即窗口大小。这在移动设备中不是什么大问题,因为移动设备上的浏览器通常以“全屏”启动(我什至不确定是否可以在移动设备、iosandroid 上调整浏览器/应用程序窗口的大小) - 但它可能如果在桌面上使用浏览器会出现问题,因为浏览器最终可能无法全屏显示。

谢天谢地,可以使用 JavaScript (How to detect the screen resolution with JavaScript?) 获得设备分辨率,在这种情况下,我可以得到设备的宽度和高度(以像素为单位) - 并从中计算出 devicemin 是两者中较小的一个(类似于vmin)。然后我将&lt;html&gt; 元素的“基本字体大小”设置为devicemin(这是我自己的任意选择)的2.67%(以像素为单位)。希望这样可以确保我在不同分辨率的设备上具有相同的字体大小(相对于设备分辨率)。

第二个问题,有点出乎我的意料,是你必须在头脑中有一个&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"/&gt; 条目/指令!否则,没有它,iOS 浏览器只会应用他们自己的字体大小/缩放,因此我们会得到一个意想不到的结果:

事实上,我对 Chromium 开发者工具中的这个结果感到非常惊讶,以至于我不得不在 Xcode iOS 模拟器中尝试测试 - 令人惊讶的是,Chromium 开发者工具实际上确实模拟了与 iOS 模拟器相同的行为做了(左图是开发者工具中的代码,右图是iOS模拟器中的OP代码)。有关这方面的更多信息,请参阅Some font-size's rendered larger on Safari (iPhone) ...

无论如何,既然我有这样的“基本”字体大小,我可以根据宽度

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <!-- MUST have, so iPhone doesn't autozoom and change the fontsize! -->
  <script type="text/javascript">
  // https://***.com/questions/2242086/how-to-detect-the-screen-resolution-with-javascript
  var devicewidth = window.screen.width;
  var deviceheight = window.screen.height;
  var devicemin = Math.min(devicewidth, deviceheight);
  // say we want base font size: 16px @ 600px (min of 800x600); 16/600 = 0.0266667
  var basefontsize = Math.round(0.0267*devicemin);
  // apply:
  var rootElement = document.documentElement;
  rootElement.style.fontSize = basefontsize;
  // report:
  console.log(navigator.userAgent);
  var report = "device res: " + devicewidth + " x " + deviceheight + " ; base font size: " + basefontsize + "/" + rootElement.style.fontSize;
  console.log(report);
  function reporter() 
    document.getElementById("dreport").innerHTML = report + "/" + document.documentElement.style.fontSize + " ... " + navigator.userAgent;
  
  window.onload = reporter;
  </script>
  <style type="text/css">
body 
  /* https://***.com/questions/3226001 ; no real need/effect in this case, though */
  -webkit-text-size-adjust: none;

.testdiv, .testdivB, .testdivC 
  width: 50%;
  height: 30%;
  margin: 6px;
  border: 2px solid gray;
  font-size: 4em;

.testdivB 
  font-size: 12px;

.testdivC 
  font-size: 30pt;

#dreport 
  font-size: 0.76em;

  </style>
</head>

<body>
  <div id="dreport"></div>
  <div class="testdiv">Test one writing</div>
  <div class="testdivB">Test another writing</div>
  <div class="testdivC">Test three writing</div>

</body>
</html>

【讨论】:

对问题的出色描述和解释,包括解决问题的绝妙方法。做得很好!【参考方案3】:

另外,您可以使用% 符号。如下所示:

div.wrapper 
   font-size: 28px;

div.small 
   font-size: 80%;

div.big 
   font-size: 150%;
<div class="wrapper">
    <div class="small">Small text</div>
    <div class="normal">Normal text</div>
    <div class="big">Big text</div>
</div>

【讨论】:

谢谢@nmnsud - 但据我所知,% 是相对于父字体大小的,最终根有一个“计算字体大小”再次以像素为单位指定,所以我再次期望(这就是我在 Chromium 开发人员工具中得到的)Kindle HDX 上的字体比其他两种情况更小(相对于设备大小);有什么办法解决吗? 谢谢@nmnsud - 但我想我不清楚;我的意思是,即使您将像素数量指定为起始字体大小,比如 28 像素,它与 Nexus 10 (28/800) 的屏幕宽度的比率总是比相同的比率小得多具有较大分辨率的设备,例如 Kindle HDX (28/1600),因此您在该设备上具有较小的相对字体大小,并且此后将在所有相对单位中传播(%,em,rem ...)可以修复这个,如果可以查询 device 屏幕大小,但是 vw, vh 只查询视口大小。

以上是关于CSS字体大小(响应式),相对于设备分辨率?的主要内容,如果未能解决你的问题,请参考以下文章

自适应和响应式区别以及写法

css 在移动设备上面使用响应式字体大小

移动设备的 HTML 响应式字体大小

javascript控制rem字体大小

面试问题总结

关于pxremem物理像素等