简体   繁体   English

如何使用 CSS 媒体查询检测 Android 设备的默认字体大小?

[英]How to detect Android device's default font size with CSS media queries?

In Android, Settings > Accessibility > Font Size the user can set font size between "Small", "Default", "Large", "Largest".在 Android 中,设置 > 辅助功能 > 字体大小,用户可以在“小”、“默认”、“大”、“最大”之间设置字体大小。 Among other things, this setting affects default font size of HTML content in WebViews.除其他外,此设置会影响 WebViews 中 HTML 内容的默认字体大小。

I've developed my layouts to look well with the default font size.我已经开发了我的布局,使其与默认字体大小相得益彰。 Setting font size to "Largest" causes text to get cut off in some places, a horizontal scrollbar appear on others etc. In these cases I can use an alternative layout (for example, stack things vertically instead of horizontally), but I'm not sure how to detect which layout to use.将字体大小设置为“最大”会导致文本在某些地方被截断,水平滚动条出现在其他地方等。在这些情况下,我可以使用另一种布局(例如,垂直堆叠而不是水平堆叠),但我不确定如何检测要使用的布局。

Ideally, I would use CSS media queries.理想情况下,我会使用 CSS 媒体查询。 Something like:就像是:

#foo {
    display: flex;
}

@media (min-width: 360px) {
    #foo {
        /* If at least 360px available, use a horizontal layout */
        flex-direction: row;
    }
}

Problem is, the 360px breakpoint isn't affected by the Font Size setting on the device (which makes sense).问题是,360px 断点不受设备上字体大小设置的影响(这是有道理的)。 I've also tried other measurement units: rem, ch, cm – but none of them seemed to take into account device's font size.我也尝试过其他测量单位:rem、ch、cm——但它们似乎都没有考虑到设备的字体大小。

I've thought about doing something like this on page load:我考虑过在页面加载时做这样的事情:

  • display a line of constant text (say, "0000000000") on the screen在屏幕上显示一行常量文本(例如“0000000000”)
  • measure it in JS在JS中测量它
  • if the measured width / device width ratio is above some set constant, switch to the alternative layout如果测量的宽度/设备宽度比高于某个设置的常数,则切换到替代布局

But this approach would add complexity, delay and repaints and flicker on page load.但是这种方法会增加复杂性、延迟和重绘以及页面加载时的闪烁。

Is there a way to take device font size in account in CSS (media queries or otherwise)?有没有办法在 CSS (媒体查询或其他)中考虑设备字体大小?

Short Answer简短的回答

No, you cannot do this just using CSS.不,您不能仅使用 CSS 来执行此操作。 However you can minimise impact using a method similar to the one you mentioned in your question (measuring font size and adjusting layout accordingly).但是,您可以使用类似于您在问题中提到的方法(测量字体大小并相应地调整布局)来最小化影响。

Long Answer长答案

You cannot do this with just CSS, however it is possible to have a performant website without repaints and fall-back to your default styles for no JS .您不能仅使用 CSS 来执行此操作,但是可以拥有一个无需重绘的高性能网站,并且可以在没有 JS的情况下回退到您的默认 styles。

There is one downside to this method, you do end up injecting a style sheet into the page which will affect first contentful paint times.这种方法有一个缺点,你最终会在页面中注入一个样式表,这会影响第一次内容绘制时间。 However bear in mind that this is essentially the same as having a matching media query (so in reality, there is no difference between this and a media query other than it relies on JavaScript).但是请记住,这与匹配媒体查询本质上是相同的(因此实际上,这与媒体查询之间没有区别,只是它依赖于 JavaScript)。

You can mitigate this by inlining the relevant styles but obviously that carries a page weight cost.您可以通过内联相关的 styles 来缓解这种情况,但显然这会带来页面重量成本。 You will have to decide which is the greater sin!你将不得不决定哪个是更大的罪!

The solution is quite simple.解决方案非常简单。

(1) Work out the user's font size using the method similar to the one you described. (1) 使用与您描述的方法类似的方法计算出用户的字体大小。

(2) Load in conditional CSS that overrides the key layout options as you desire. (2) 加载有条件的 CSS,它会根据需要覆盖键布局选项。

(2a) Alternatively add a class to the body and change the layout based on that from styles within existing style sheets or inlined in the document if above the fold. (2a) 或者,将 class 添加到正文,并根据现有样式表中的 styles 更改布局,或者如果在折叠上方,则在文档中内联。

1. Work out the user's font size 1.计算出用户的字体大小

You can do this in vanilla JS right within the header of the page as an inline script so it does not delay anything (other than parsing the script) and it will still be performant.您可以在页面的 header 中作为内联脚本在 vanilla JS 中执行此操作,因此它不会延迟任何内容(除了解析脚本)并且它仍然可以执行。

Try the below example with you font size set to "medium" first, then set your font-size to "extra large" and run the script again.尝试以下示例,首先将字体大小设置为“中”,然后将字体大小设置为“特大”并再次运行脚本。 Your font size should show as 16px and 24px respectively.您的字体大小应分别显示为 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>

We now have a font size that is relative to the user's scaling.我们现在有一个相对于用户缩放的字体大小。

We can further improve this by simply dividing the resultant font size by 16 (default size) to get a %age scale.我们可以通过简单地将生成的字体大小除以 16(默认大小)来进一步改进这一点,以获得 %age 比例。

 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. Load in conditional CSS 2.加载有条件的CSS

Now that we know if the font size has been scaled by the user we simply conditionally load CSS.现在我们知道字体大小是否已被用户缩放,我们只需有条件地加载 CSS。

To do this we need a simple JavaScript check为此,我们需要一个简单的 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
}

In the below example I have 3 columns that turn into 3 rows to demonstrate how font size dictates which styles to apply.在下面的示例中,我有 3 列变成 3 行,以演示字体大小如何决定要应用哪个 styles。

Please note to simulate a dynamically added CSS file I added some inline CSS code that gets written to a style sheet, you would obviously just add a style sheet (I have included a function to do this and just commented out where that function is called). Please note to simulate a dynamically added CSS file I added some inline CSS code that gets written to a style sheet, you would obviously just add a style sheet (I have included a function to do this and just commented out where that function is called) .

 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>

You will see from the example we add the stylesheet dynamically, choosing between two style sheets in the example.您将从示例中看到我们动态添加样式表,在示例中的两个样式表之间进行选择。 In reality you would probably only need to do the check for the requirement to use the large fonts stylesheet as your standard font size will be covered by your main CSS.实际上,您可能只需要检查使用大型 fonts 样式表的要求,因为您的标准字体大小将被您的主要 CSS 覆盖。

pros This method effectively is the same as a 'font size media query' and carries a tiny JavaScript overhead.优点这种方法实际上与“字体大小媒体查询”相同,并带有很小的 JavaScript 开销。

cons If you are bothered by repaints then performance is obviously important to you, this method adds an additional request and can delay First Contentful Paint / Initial page rendering for "above the fold content".缺点如果您对重绘感到困扰,那么性能显然对您很重要,此方法会添加一个额外的请求,并且可能会延迟“首屏内容”的首次内容绘制/初始页面渲染。

Because of this I offer a second suggestion:因此,我提出第二个建议:

2a. 2a. Add a class to the body.将 class 添加到主体。

Use exactly the same method as above but instead of inserting a style sheet simply use the check for font size to add a class to the body on page load.使用与上述完全相同的方法,但不要插入样式表,只需使用检查字体大小在页面加载时将 class 添加到正文。

The simply include the styles within your current style sheets but with the additional body class as a qualifier.只需将 styles 包含在您当前的样式表中,但附加主体 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 this doesn't add any extra requests, should not affect your page paint.优点这不会添加任何额外的请求,不应该影响您的页面绘制。 Generally this option will be preferable to the first option as you should only need to override a handful of CSS classes so the added weight is negligible.通常,此选项比第一个选项更可取,因为您只需要覆盖少数 CSS 类,因此增加的权重可以忽略不计。

cons - adds extra weight to your CSS.缺点- 增加了 CSS 的重量。

Conclusion结论

Somebody should add a "user font size" media query:-P有人应该添加“用户字体大小”媒体查询:-P

Seriously though I would go with the (2a) option I gave you and inline your critical CSS .说真的,虽然我会 go 与我给你的(2a)选项并内联你的关键 CSS If you are changing more than 100 classes in your CSS (and so CSS weight becomes a problem) then something is wrong with your design so the speed difference will be negligible.如果您在 CSS 中更改超过 100 个类(因此 CSS 的重量成为问题),那么您的设计有问题,因此速度差异可以忽略不计。 Couple that with the fact that the JS is less than 1kb and it will not affect your paints and it is a simple but effective solution to your problem.再加上 JS 小于 1kb,它不会影响您的绘画,这是一个简单但有效的解决您问题的方法。

Bonus info for option 2选项 2 的奖励信息

As an additional thought you can combine option 2 with checking the screen width to really minimise the amount of data sent down the wire.作为一个额外的想法,您可以将选项 2 与检查屏幕宽度结合起来,以真正最大限度地减少通过网络发送的数据量。 However this then starts adding considerable complexity which is something you said you wanted to avoid.然而,这开始增加相当大的复杂性,这是你说你想要避免的。 I have included it here for completeness.为了完整起见,我将其包含在此处。

 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>

you can use the VH (viewport height) or VW(viewport width) font-size measures and the font will resize based on % of device viewport for example:您可以使用 VH(视口高度)或 VW(视口宽度)字体大小度量,字体将根据设备视口的百分比调整大小,例如:

1vh = 1% of viewport heigth 2vw = 2% of viewport width etc 1vh = 视口高度的 1% 2vw = 视口宽度的 2% 等

If you are doing media selector you could as well use rem or px as font-size.如果你在做媒体选择器,你也可以使用 rem 或 px 作为字体大小。

You will still have to add @media selector for different devices, keep in mind viewport is the actual size of a device screen, like 10inch screens will have a @media selector up to 1280px or bellow.您仍然需要为不同的设备添加@media 选择器,请记住视口是设备屏幕的实际尺寸,例如 10 英寸屏幕将有一个高达 1280 像素或以下的@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)?有没有办法在 CSS (媒体查询或其他)中考虑设备字体大小?

Media queries are used to set font size based on device width, not the contrary.媒体查询用于根据设备宽度设置字体大小,而不是相反。

The unit you might use will always be based on the device width, not on the font size (as this can't be already defined at this point).您可能使用的单位将始终基于设备宽度,而不是字体大小(因为此时无法定义)。

What you can do is, instead of defining the width of your columns based on percentage or using px units, you can set them on the base font size.您可以做的是,您可以在基本字体大小上设置它们,而不是根据百分比或使用 px 单位来定义列的宽度。

For instance, instead of例如,而不是

.flex-col {
  flex: 0 1 30%;
}

you may use你可以使用

.flex-col {
  flex: 0 1 20rem;
}

The real problem are not your media queries but the fact that your containers are not defined in a responsive way (with both fix width and height for instance) causing cut off and scrollbars.真正的问题不是您的媒体查询,而是您的容器没有以响应方式定义(例如固定宽度和高度)导致截断和滚动条的事实。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM