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

标签 android css webview media-queries accessibility

在 Android 中,设置 > 辅助功能 > 字体大小用户可以在“小”、“默认”、“大”、“最大”之间设置字体大小。除其他外,此设置会影响 WebView 中 HTML 内容的默认字体大小。

我已经开发了我的布局以使用默认字体大小看起来很好。将字体大小设置为“最大”会导致文本在某些地方被截断,其他地方会出现水平滚动条等。在这些情况下,我可以使用替代布局(例如,垂直而不是水平堆叠东西),但我不确定如何检测要使用的布局。

理想情况下,我会使用 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——但它们似乎都没有考虑到设备的字体大小。

我想过在页面加载时做这样的事情:
  • 在屏幕上显示一行常量文本(例如“0000000000”)
  • 在 JS 中测量它
  • 如果测量的宽度/设备宽度比高于某个设置常数,则切换到替代布局

  • 但是这种方法会增加页面加载的复杂性、延迟、重绘和闪烁。

    有没有办法在 CSS(媒体查询或其他)中考虑设备字体大小?

    最佳答案

    简答
    不,您不能仅使用 CSS 来做到这一点。但是,您可以使用类似于您在问题中提到的方法(测量字体大小并相应地调整布局)来最大限度地减少影响。
    长答案
    你不能只用 CSS 来做到这一点,但是可以有一个高性能的网站而无需重新绘制和回退到您的默认样式 无 JS .
    这种方法有一个缺点,你最终会在页面中注入(inject)一个样式表,这会影响第一次内容绘制时间。但是请记住,这与具有匹配的媒体查询本质上相同(因此实际上,除了依赖 JavaScript 之外,这与媒体查询没有区别)。
    您可以通过内联相关样式来缓解这种情况,但显然这会带来页面权重成本。你必须决定哪个是更大的罪!
    解决方法很简单。
    (1) 使用类似于您描述的方法计算用户的字体大小。
    (2) 加载条件 CSS,根据需要覆盖关键布局选项。
    (2a) 或者,在正文中添加一个类,并根据现有样式表中的样式或在文档中内联(如果位于首屏)中的样式更改布局。
    1. 计算出用户的字体大小
    您可以在页面标题中的 vanilla JS 中作为内联脚本执行此操作,因此它不会延迟任何事情(除了解析脚本)并且它仍然具有性能。
    尝试以下示例,首先将字体大小设置为“中等”,然后将字体大小设置为“超大”并再次运行脚本。您的字体大小应分别显示为 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 代码,您显然只需要添加一个样式表(我已经包含了一个函数来执行此操作,只是注释掉了该函数的调用位置) .

    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>

    您将在示例中看到我们动态添加样式表,在示例中的两个样式表之间进行选择。实际上,您可能只需要检查是否需要使用大字体样式表,因为您的主 CSS 将涵盖您的标准字体大小。
    优点
    这种方法实际上与“字体大小媒体查询”相同,并带有很小的 JavaScript 开销。
    缺点
    如果您对重绘感到困扰,那么性能显然对您很重要,此方法会添加一个额外的请求,并且可以延迟“首屏内容”的首次内容绘制/初始页面渲染。
    因此,我提出第二个建议:
    2a.向正文添加一个类。
    使用与上面完全相同的方法,但不插入样式表,只需使用字体大小检查在页面加载时向正文添加类。
    简单地包含当前样式表中的样式,但使用附加的主体类作为限定符。

    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>

    优点 这不会添加任何额外的请求,不应影响您的页面绘制。通常,此选项比第一个选项更可取,因为您只需要覆盖少数 CSS 类,因此增加的权重可以忽略不计。
    缺点 - 为您的 CSS 增加额外的权重。
    结论
    有人应该添加“用户字体大小”媒体查询:-P
    说真的,虽然我会选择我给你的 (2a) 选项和 inline your critical CSS .如果您要更改 CSS 中的 100 多个类(因此 CSS 权重成为问题),那么您的设计就有问题,因此速度差异可以忽略不计。再加上 JS 小于 1kb,它不会影响您的绘画,这是一个简单但有效的问题解决方案。
    选项 2 的奖励信息
    作为一个额外的想法,您可以将选项 2 与检查屏幕宽度结合起来,以真正减少通过线路发送的数据量。然而,这会开始增加相当大的复杂性,这是您说要避免的。为了完整起见,我将其包含在此处。

    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 - 如何使用 CSS 媒体查询检测 Android 设备的默认字体大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62151458/

    相关文章:

    java - 根据按钮链接在 webview 中显示特定的 url

    android - Android 中来自 VKontakte 的用户信息

    android - 自定义 ListView 不显示数据

    java - 微调下拉菜单 ExpandableListView

    html - 用CSS布局( float )不同高度的 block

    android - WebView可以用于HTML解析吗?

    javascript - 安卓网页 View : inject a function call to the onclick event of a checkbox

    android - 自定义 LinearLayout 的膨胀子项在覆盖 onMeasure 时不显示

    javascript - onclick后如何设置在JQUERY中包含image和div span内容

    html - 网站顶部和按钮之间的空间?