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

14

假设我们有以下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
这是结果:

结果如下:

chrome-test

在这个例子中,所有设备都是竖屏,并且拥有“几乎相同”的宽高比(约为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 (我猜应该有一种方法可以查询设备屏幕而非视口分辨率,但我不确定是否真的有这样的方法)?

2
我相信在这里使用媒体查询与Roberrrt的答案以及使用类而不是ID,并且根据Roberrrt的代码使用相同的类名但不同的尺寸,所以最终你会得到类似于.responsive_size的东西嵌套在不同的媒体查询中,以及font-size: calc(Xem + Xvmin);之类的东西。这只是我的个人看法。 - Funk Forty Niner
1
我很好奇,我的解决方案有帮助/起作用了吗? :) - roberrrt-s
确实, @Teepeemm,它应该是.testdivC - 我已经更正了,但现在我不确定截图是使用错误的 .testdivB 还是正确的 .testdivC(但它看起来是用正确的)。 - sdbbs
1
嗨@Roberrrt,我已经在你的回答中[发表了评论](https://dev59.com/d1gR5IYBdhLWcg3wp-q5#wyoboYgBc1ULPQZFA1_t),但它似乎在那里丢失了。我现在也根据JavaScript [发布了自己的答案](https://dev59.com/d1gR5IYBdhLWcg3wp-q5#41100838),这应该更详细地解释了我所寻找的内容;简而言之,我的问题是“vmin”是以视口而非设备分辨率表示的,如果在桌面上使用并且浏览器不是“全屏”,则可能会得出错误的结果。 - sdbbs
3个回答

29

我之前写过一篇关于如何使用纯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,然后将两个值相加以确定字体大小。


2
巧合的是,我也有一段时间在阅读有关同一主题的一些文章。在这里大声思考一下;如果使用类并根据屏幕大小应用媒体查询,那是否也有意义呢?因为ID是唯一的。 - Funk Forty Niner
2
抱歉,我无法提供一个fiddle,但我相信你知道我的意思;-) 最终,我使用了不同字体大小的媒体查询。@Roberrrt,但我一定会尝试你的方法 :-) - Funk Forty Niner
2
结合起来是有意义的,让我整理一下我的网站来测试一些东西。 - roberrrt-s
2
@Fred-ii- 我通常设置20em / 40em / 80em 媒体查询断点,并在此基础上"增强"字体大小,<20em calc(1em + 1vw)。 <40em calc(1.2em + 1vw)calc (1.5em + 1vw) - roberrrt-s
2
我认为你可以将 (.4em + 1vmin) + (.4em + 1vmax) 改为 (.8em + 1vw + 1vh)。令我惊讶的是,没有一种方便的方法可以说“使其成为正常大小”,并在所有设备上都能读取。 - Teepeemm
显示剩余7条评论

5

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

devtools-test-2

如您所见,第一个带有.testdiv规格的
,使用em来指定其相对大小,现在在各种设备尺寸下都得以保留(这正是我想要的);第二个
使用px,如预期一样无法保留相对大小,而第三个
使用pt规格也无法保留相对大小。

我遇到的第一个问题是如何获取设备分辨率。请注意,vwvh - 以及vminvmax - 都是相对于视口大小的,即窗口大小。在移动端这并不是太大的问题,因为移动端的浏览器通常会全屏启动(我甚至不确定在移动端上调整浏览器/应用程序窗口的大小是否可能,包括iOS或Android)- 但如果在桌面端使用浏览器,则可能会出现问题,因为浏览器可能最终无法全屏显示。

幸运的是,我们可以使用JavaScript获取设备分辨率(如何使用JavaScript检测屏幕分辨率?)。在这种情况下,我获取以像素为单位的设备宽度和高度,并从中计算devicemin,即两者中较小的值(类似于vmin)。然后,我将“基础字体大小”即<html>元素的字体大小设置为devicemin的2.67%(这是我的任意选择)的像素。这样做可以确保在具有不同分辨率的设备上,相对于设备分辨率,字体大小相同。

第二个问题,对我来说有些出乎意料,那就是您必须在头部添加一个<meta name="viewport" content="width=device-width, initial-scale=1.0"/>的条目/指令!否则,在没有它的情况下,iOS浏览器将只应用它们自己的字体大小/缩放,因此我们会得到一个意外的结果,例如:

devtools-ios-no-viewport

我事实上对Chromium开发者工具中的这个结果感到非常惊讶,以至于我不得不在Xcode iOS模拟器中尝试这个测试 - 令人惊讶的是,Chromium开发者工具实际上模拟了与iOS模拟器相同的行为(左图是开发者工具中下面的代码,右图是iOS模拟器中的OP代码)。更多信息,请参见Safari(iPhone)上呈现的某些字体大小更大...

无论如何,既然我有了这样的“基础”字体大小,我可以根据宽度<20em,<40em等来实现响应式设计,并确保这些大小将引用任何屏幕设备上的大致相同的相对区域...

<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://dev59.com/P3E95IYBdhLWcg3wlvCz
  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://dev59.com/YXA75IYBdhLWcg3wkJ71 ; 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>

2
问题的描述和解释非常好,包括了一个辉煌的解决方法。做得很棒! - roberrrt-s

0

此外,您可以使用%符号。就像下面这样:

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>


2
感谢@nmnsud - 但据我所知,百分比是相对于父元素的字体大小的,最终根元素又指定了以像素为单位的“计算字体大小”,因此我期望(并且在Chromium开发者工具中也是这样)Kindle HDX上的字体要比其他两种情况小(相对于设备尺寸); 有什么方法可以解决这个问题吗? - sdbbs
2
谢谢@nmnsud - 但我想我没有表达清楚; 我的意思是,即使您指定了像素大小作为起始字体大小,比如28像素,它与Nexus 10的屏幕宽度的比率(28/800)始终会比像Kindle HDX这样分辨率更高的设备的相同比率小得多,因此在该设备上具有较小的相对字体大小,并且将在此后传播到所有相对单位(%,em,rem ...)。 如果可以查询设备屏幕大小,则可以解决此问题,但vw,vh仅查询视口大小。 - sdbbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接