如何使用 CSS 媒体查询检测 Android 设备的默认字体大小?
How to detect Android device's default font size with CSS media queries?
在 Android 中,设置 > 辅助功能 > 字体大小用户可以在 "Small"、"Default"、"Large"、"Largest" 之间设置字体大小。除其他事项外,此设置会影响 WebView 中 HTML 内容的默认字体大小。
我已经开发出适合默认字体大小的布局。将字体大小设置为 "Largest" 会导致文本在某些地方被截断,水平滚动条出现在其他地方等。在这些情况下,我可以使用替代布局(例如,垂直而不是水平堆叠东西),但我我不确定如何检测要使用的布局。
理想情况下,我会使用 CSS 媒体查询。类似于:
#foo {
display: flex;
}
@media (min-width: 360px) {
#foo {
/* If at least 360px available, use a horizontal layout */
flex-direction: row;
}
}
问题是,360px 断点不受设备上字体大小设置的影响(这是有道理的)。我也尝试过其他测量单位:rem、ch、cm – 但其中 none 似乎考虑了设备的字体大小。
我考虑过在页面加载时做这样的事情:
- 在屏幕上显示一行固定文本(比如“0000000000”)
- 在 JS 中测量它
- 如果测得的宽度/设备宽度比高于某个设定常量,则切换到替代布局
但这种方法会增加页面加载的复杂性、延迟、重绘和闪烁。
有没有办法在 CSS(媒体查询或其他)中考虑设备字体大小?
您可以使用 VH(视口高度)或 VW(视口宽度)字体大小度量,字体将根据设备视口的百分比调整大小,例如:
1vh = 视口高度的 1%
2vw = 视口宽度的 2% 等
如果您正在做媒体选择器,您也可以使用 rem 或 px 作为字体大小。
您仍然需要为不同的设备添加@media 选择器,请记住视口是设备屏幕的实际尺寸,例如 10 英寸屏幕将有一个最大 1280px 或以下的@media 选择器。
/* please use caniuse.com for browser compatibility table*/
h1 {
font-size: 2.5vw;
}
h2 {
font-size: 2vw;
}
p {
font-size: 12px;
}
@media only screen and (max-width:768px) {
h1 {
font-size: 5vw;
}
h2 {
font-size: 4vw;
}
p {
font-size: 18px;
}
}
<h1>text</h1>
<h2>text</h2>
<p>some normal font controled by media query</p>
Is there a way to take device font size in account in CSS (media queries or otherwise)?
媒体查询用于根据设备宽度设置字体大小,而不是相反。
您可能使用的单位将始终基于设备宽度,而不是字体大小(因为此时无法定义)。
您可以做的是,您可以根据基本字体大小设置它们,而不是根据百分比或使用 px 单位定义列宽。
例如,而不是
.flex-col {
flex: 0 1 30%;
}
你可以使用
.flex-col {
flex: 0 1 20rem;
}
真正的问题不是你的媒体查询,而是你的容器没有以响应方式定义(例如固定宽度和高度)导致截断和滚动条。
简答
不,您不能仅使用 CSS 来完成此操作。但是,您可以使用类似于您在问题中提到的方法(测量字体大小并相应地调整布局)来最大程度地减少影响。
长答案
您不能仅使用 CSS 来做到这一点,但是可以拥有一个高性能的网站而无需重绘和 fall-back 您的默认样式 no JS.
此方法有一个缺点,您最终会将样式 sheet 注入页面,这会影响第一个内容绘制时间。但是请记住,这与具有匹配的媒体查询本质上是相同的(因此实际上,这与媒体查询之间没有区别,除了它依赖于 JavaScript)。
您可以通过内联相关样式来缓解这种情况,但显然这会带来页面权重成本。你将不得不决定哪个是更大的罪过!
解决方法很简单。
(1) 使用与您描述的方法类似的方法计算出用户的字体大小。
(2) 加载条件 CSS 以根据需要覆盖按键布局选项。
(2a) 或者将 class 添加到 body 并根据现有样式 sheet 中的样式更改布局,或者如果在折叠上方则内嵌在文档中.
1。算出用户的字体大小
您可以在页面的 header 内使用 vanilla JS 作为内联脚本执行此操作,因此它不会延迟任何内容(除了解析脚本)并且它仍然是高性能的。
尝试下面的示例,首先将字体大小设置为“中”,然后将 font-size 设置为“超大”,然后再次 运行 脚本。您的字体大小应分别显示为 16px 和 24px。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
console.log(style)
<div id="foo">a</div>
我们现在有一个与用户缩放比例相关的字体大小。
我们可以进一步改进这一点,只需将生成的字体大小除以 16(默认大小)即可获得百分比比例。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
console.log(style, fontSizePercentage + "%");
<div id="foo">a</div>
2。加载条件 CSS
既然我们知道用户是否缩放了字体大小,我们只需有条件地加载 CSS。
为此,我们需要一个简单的 JavaScript 检查
//set to whatever criteria you need, if your site still works on "large" font size and only needs adjustment at "extra large" then use 124 etc.
if(fontSizePercentage > 100){
//add the CSS
}
在下面的示例中,我将 3 列变成了 3 行,以演示字体大小如何决定要应用的样式。
请注意,为了模拟动态添加的 CSS 文件,我添加了一些内联 CSS 代码,这些代码被写入样式 sheet,您显然只需添加一个样式 [=158] =](我已经包含了一个函数来执行此操作,只是注释掉了调用该函数的位置)。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
el.remove();
console.log(fontSizePercentage);
//this is just to simulate adding CSS, you would obviously import a style sheet properly here. I have put the proper function further down.
var normal = `
.col3{
float: left;
width: 32%;
margin-right: 1%;
}
`
var bigger = `
.col3{
float: left;
width: 100%;
}
`
var styleSheet = document.createElement("style");
styleSheet.type = "text/css";
if(fontSizePercentage > 100){
styleSheet.innerText = bigger;
}else{
styleSheet.innerText = normal;
}
document.head.appendChild(styleSheet);
////actual style sheet code/////
function addCss(fileName) {
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = fileName;
head.appendChild(link);
}
if(fontSizePercentage > 100){
//addCss('url-to-large-font-size-layout');
}else{
//addCss('url-to-normal-font-size-layout');
}
<div id="foo">a</div>
<div class="col3">column</div>
<div class="col3">column</div>
<div class="col3">column</div>
您将从示例中看到我们动态添加样式sheet,在示例中的两个样式sheet 之间进行选择。实际上,您可能只需要检查使用大字体样式 sheet 的要求,因为您的标准字体大小将被您的主要 CSS.
覆盖
优点
此方法实际上与 'font size media query' 相同,并带有微小的 JavaScript 开销。
缺点
如果您对重绘感到困扰,那么性能显然对您很重要,此方法会添加一个额外的请求,并且可以延迟“首屏内容”的首次内容绘制/初始页面呈现。
因此我提出第二个建议:
2a。在 body.
中添加一个 class
使用与上面完全相同的方法,但不是插入样式 sheet 而是简单地使用检查字体大小在页面加载时将 class 添加到 body。
只需将样式包含在当前样式 sheet 中,但将额外的 body class 作为限定符。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
el.remove();
var bod = document.getElementById('simulated-body');
if(fontSizePercentage > 100){
bod.classList.add('large-font-layout');
}
console.log(fontSizePercentage);
.col3{
float: left;
width: 32%;
margin-right: 1%;
}
.large-font-layout .col3{
float: left;
width: 100%;
}
<div id="simulated-body">
<div id="foo">a</div>
<div class="col3">column</div>
<div class="col3">column</div>
<div class="col3">column</div>
</div>
pros 这不会添加任何额外的请求,应该不会影响您的页面绘制。一般来说,此选项比第一个选项更可取,因为您只需要覆盖少数 CSS classes,因此增加的权重可以忽略不计。
cons - 为您的 CSS.
添加额外的权重
结论
一些body应该添加一个“用户字体大小”媒体查询:-P
说真的,我会选择我给你的 (2a) 选项和 inline your critical CSS。如果您在 CSS 中更改超过 100 classes(因此 CSS 重量成为问题)那么您的设计有问题,因此速度差异可以忽略不计。再加上 JS 小于 1kb,不会影响你的绘画,这是一个简单但有效的解决问题的方法。
选项 2 的奖金信息
作为一个额外的想法,您可以将选项 2 与检查屏幕宽度结合起来,以真正达到 mi估计沿线路发送的数据量。然而,这随后开始增加相当大的复杂性,这是您所说的要避免的事情。为了完整起见,我将其包含在此处。
function getFontSizePercentage(){
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
el.remove();
return fontSizePercentage;
}
function getPageWidth(){
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
}
function addCSS(fileName) {
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = fileName;
head.appendChild(link);
}
var fontSizePercentage = getFontSizePercentage();
var pageWidth = getPageWidth();
var cssSize = "1920";
switch(true) {
case (pageWidth < 1366):
cssSize = "1366";
break;
case (pageWidth < 728):
var cssSize = "728";
break;
default:
cssSize = "1920";
}
var cssPath = "styles/screen-width-" + cssSize + "-font-size-adjust";
if(fontSizePercentage > 100){
console.log("adding CSS for width: " + cssSize, cssPath);
addCSS(cssPath);
}else{
console.log("not adding CSS", cssPath);
}
<div id="foo">a</div>
在 Android 中,设置 > 辅助功能 > 字体大小用户可以在 "Small"、"Default"、"Large"、"Largest" 之间设置字体大小。除其他事项外,此设置会影响 WebView 中 HTML 内容的默认字体大小。
我已经开发出适合默认字体大小的布局。将字体大小设置为 "Largest" 会导致文本在某些地方被截断,水平滚动条出现在其他地方等。在这些情况下,我可以使用替代布局(例如,垂直而不是水平堆叠东西),但我我不确定如何检测要使用的布局。
理想情况下,我会使用 CSS 媒体查询。类似于:
#foo {
display: flex;
}
@media (min-width: 360px) {
#foo {
/* If at least 360px available, use a horizontal layout */
flex-direction: row;
}
}
问题是,360px 断点不受设备上字体大小设置的影响(这是有道理的)。我也尝试过其他测量单位:rem、ch、cm – 但其中 none 似乎考虑了设备的字体大小。
我考虑过在页面加载时做这样的事情:
- 在屏幕上显示一行固定文本(比如“0000000000”)
- 在 JS 中测量它
- 如果测得的宽度/设备宽度比高于某个设定常量,则切换到替代布局
但这种方法会增加页面加载的复杂性、延迟、重绘和闪烁。
有没有办法在 CSS(媒体查询或其他)中考虑设备字体大小?
您可以使用 VH(视口高度)或 VW(视口宽度)字体大小度量,字体将根据设备视口的百分比调整大小,例如:
1vh = 视口高度的 1% 2vw = 视口宽度的 2% 等
如果您正在做媒体选择器,您也可以使用 rem 或 px 作为字体大小。
您仍然需要为不同的设备添加@media 选择器,请记住视口是设备屏幕的实际尺寸,例如 10 英寸屏幕将有一个最大 1280px 或以下的@media 选择器。
/* please use caniuse.com for browser compatibility table*/
h1 {
font-size: 2.5vw;
}
h2 {
font-size: 2vw;
}
p {
font-size: 12px;
}
@media only screen and (max-width:768px) {
h1 {
font-size: 5vw;
}
h2 {
font-size: 4vw;
}
p {
font-size: 18px;
}
}
<h1>text</h1>
<h2>text</h2>
<p>some normal font controled by media query</p>
Is there a way to take device font size in account in CSS (media queries or otherwise)?
媒体查询用于根据设备宽度设置字体大小,而不是相反。
您可能使用的单位将始终基于设备宽度,而不是字体大小(因为此时无法定义)。
您可以做的是,您可以根据基本字体大小设置它们,而不是根据百分比或使用 px 单位定义列宽。
例如,而不是
.flex-col {
flex: 0 1 30%;
}
你可以使用
.flex-col {
flex: 0 1 20rem;
}
真正的问题不是你的媒体查询,而是你的容器没有以响应方式定义(例如固定宽度和高度)导致截断和滚动条。
简答
不,您不能仅使用 CSS 来完成此操作。但是,您可以使用类似于您在问题中提到的方法(测量字体大小并相应地调整布局)来最大程度地减少影响。
长答案
您不能仅使用 CSS 来做到这一点,但是可以拥有一个高性能的网站而无需重绘和 fall-back 您的默认样式 no JS.
此方法有一个缺点,您最终会将样式 sheet 注入页面,这会影响第一个内容绘制时间。但是请记住,这与具有匹配的媒体查询本质上是相同的(因此实际上,这与媒体查询之间没有区别,除了它依赖于 JavaScript)。
您可以通过内联相关样式来缓解这种情况,但显然这会带来页面权重成本。你将不得不决定哪个是更大的罪过!
解决方法很简单。
(1) 使用与您描述的方法类似的方法计算出用户的字体大小。
(2) 加载条件 CSS 以根据需要覆盖按键布局选项。
(2a) 或者将 class 添加到 body 并根据现有样式 sheet 中的样式更改布局,或者如果在折叠上方则内嵌在文档中.
1。算出用户的字体大小
您可以在页面的 header 内使用 vanilla JS 作为内联脚本执行此操作,因此它不会延迟任何内容(除了解析脚本)并且它仍然是高性能的。
尝试下面的示例,首先将字体大小设置为“中”,然后将 font-size 设置为“超大”,然后再次 运行 脚本。您的字体大小应分别显示为 16px 和 24px。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
console.log(style)
<div id="foo">a</div>
我们现在有一个与用户缩放比例相关的字体大小。
我们可以进一步改进这一点,只需将生成的字体大小除以 16(默认大小)即可获得百分比比例。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
console.log(style, fontSizePercentage + "%");
<div id="foo">a</div>
2。加载条件 CSS
既然我们知道用户是否缩放了字体大小,我们只需有条件地加载 CSS。
为此,我们需要一个简单的 JavaScript 检查
//set to whatever criteria you need, if your site still works on "large" font size and only needs adjustment at "extra large" then use 124 etc.
if(fontSizePercentage > 100){
//add the CSS
}
在下面的示例中,我将 3 列变成了 3 行,以演示字体大小如何决定要应用的样式。
请注意,为了模拟动态添加的 CSS 文件,我添加了一些内联 CSS 代码,这些代码被写入样式 sheet,您显然只需添加一个样式 [=158] =](我已经包含了一个函数来执行此操作,只是注释掉了调用该函数的位置)。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
el.remove();
console.log(fontSizePercentage);
//this is just to simulate adding CSS, you would obviously import a style sheet properly here. I have put the proper function further down.
var normal = `
.col3{
float: left;
width: 32%;
margin-right: 1%;
}
`
var bigger = `
.col3{
float: left;
width: 100%;
}
`
var styleSheet = document.createElement("style");
styleSheet.type = "text/css";
if(fontSizePercentage > 100){
styleSheet.innerText = bigger;
}else{
styleSheet.innerText = normal;
}
document.head.appendChild(styleSheet);
////actual style sheet code/////
function addCss(fileName) {
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = fileName;
head.appendChild(link);
}
if(fontSizePercentage > 100){
//addCss('url-to-large-font-size-layout');
}else{
//addCss('url-to-normal-font-size-layout');
}
<div id="foo">a</div>
<div class="col3">column</div>
<div class="col3">column</div>
<div class="col3">column</div>
您将从示例中看到我们动态添加样式sheet,在示例中的两个样式sheet 之间进行选择。实际上,您可能只需要检查使用大字体样式 sheet 的要求,因为您的标准字体大小将被您的主要 CSS.
覆盖优点 此方法实际上与 'font size media query' 相同,并带有微小的 JavaScript 开销。
缺点 如果您对重绘感到困扰,那么性能显然对您很重要,此方法会添加一个额外的请求,并且可以延迟“首屏内容”的首次内容绘制/初始页面呈现。
因此我提出第二个建议:
2a。在 body.
中添加一个 class使用与上面完全相同的方法,但不是插入样式 sheet 而是简单地使用检查字体大小在页面加载时将 class 添加到 body。
只需将样式包含在当前样式 sheet 中,但将额外的 body class 作为限定符。
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
el.remove();
var bod = document.getElementById('simulated-body');
if(fontSizePercentage > 100){
bod.classList.add('large-font-layout');
}
console.log(fontSizePercentage);
.col3{
float: left;
width: 32%;
margin-right: 1%;
}
.large-font-layout .col3{
float: left;
width: 100%;
}
<div id="simulated-body">
<div id="foo">a</div>
<div class="col3">column</div>
<div class="col3">column</div>
<div class="col3">column</div>
</div>
pros 这不会添加任何额外的请求,应该不会影响您的页面绘制。一般来说,此选项比第一个选项更可取,因为您只需要覆盖少数 CSS classes,因此增加的权重可以忽略不计。
cons - 为您的 CSS.
添加额外的权重结论
一些body应该添加一个“用户字体大小”媒体查询:-P
说真的,我会选择我给你的 (2a) 选项和 inline your critical CSS。如果您在 CSS 中更改超过 100 classes(因此 CSS 重量成为问题)那么您的设计有问题,因此速度差异可以忽略不计。再加上 JS 小于 1kb,不会影响你的绘画,这是一个简单但有效的解决问题的方法。
选项 2 的奖金信息
作为一个额外的想法,您可以将选项 2 与检查屏幕宽度结合起来,以真正达到 mi估计沿线路发送的数据量。然而,这随后开始增加相当大的复杂性,这是您所说的要避免的事情。为了完整起见,我将其包含在此处。
function getFontSizePercentage(){
var el = document.getElementById('foo');
var style = window.getComputedStyle(el, null).getPropertyValue('font-size');
var fontSize = style;
var fontSizePercentage = parseFloat(style) / 16 * 100;
el.remove();
return fontSizePercentage;
}
function getPageWidth(){
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
}
function addCSS(fileName) {
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = fileName;
head.appendChild(link);
}
var fontSizePercentage = getFontSizePercentage();
var pageWidth = getPageWidth();
var cssSize = "1920";
switch(true) {
case (pageWidth < 1366):
cssSize = "1366";
break;
case (pageWidth < 728):
var cssSize = "728";
break;
default:
cssSize = "1920";
}
var cssPath = "styles/screen-width-" + cssSize + "-font-size-adjust";
if(fontSizePercentage > 100){
console.log("adding CSS for width: " + cssSize, cssPath);
addCSS(cssPath);
}else{
console.log("not adding CSS", cssPath);
}
<div id="foo">a</div>