CSS 中的操作系统特定字体

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

我不确定确切的用例是什么,但 Sam Stephenson 最近问我

我立即想到的是使用旧技巧,您可以在根元素上放置一个包含用户代理的 data-attribute,您可以从中选择该属性。

var doc = document.documentElement;
doc.setAttribute('data-useragent', navigator.userAgent);

然后根据需要设置字体。在本例中,为 OS X 设置 Lucida Grande,但为最新版本设置 Helvetica Neue。

html {
  font-family: sans-serif;  
}

html[data-useragent*='Mac OS X'] {
  font-family: "Lucida Grande","Lucida Sans Unicode", Tahoma, sans-serif;
}

html[data-useragent*='Mac OS X 10_10'] {
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 
  font-weight: 300;
}

基本上有效。它是 UA 嗅探,这 不好,但我们在这里不做任何特别重要的任务,因此不会让我们的网站或网络面临风险。

Sam 尝试了另一条路径,并 变得很花哨。在这里,他创建了一个 iframe(因此没有干扰样式),插入一个 button 元素(默认情况下应该具有系统字体),并测试其样式。

(function() {
  window.addEventListener("DOMContentLoaded", function() {
    getSystemFontFamily(function(systemFontFamily) {
      var cssText = ".system-font { font-family: " + systemFontFamily + " }";
      var element = createStyleElement(cssText);
      document.head.insertBefore(element, document.head.firstChild);
    });
  });

  function getSystemFontFamily(callback) {
    withHiddenFrame(function(document) {
      var button = document.createElement("button");
      document.body.appendChild(button);
      callback(window.getComputedStyle(button).fontFamily);
    });
  }

  function withHiddenFrame(callback) {
    var frame = document.createElement("iframe");
    frame.style.cssText = "width: 0; height: 0; visibility: hidden";
    frame.onload = function() {
      callback(frame.contentDocument);
      document.body.removeChild(frame);
    }
    document.body.appendChild(frame);
  }

  function createStyleElement(cssText) {
    var element = document.createElement("style");
    element.type = "text/css";
    if (element.styleSheet) {
      element.styleSheet.cssText = cssText;
    } else {
      element.appendChild(document.createTextNode(cssText));
    }
    return element;
  }
})();

在 Yosemite(10.10.1)上,您将获得

.system-font { 
  font-family: '.HelveticaNeueDeskInterface-Regular';
}

奇怪的名字,但它有效。

在 10.9 中,您将获得

.system-font { 
  font-family: '.LucidaGrandeUI';
}

同样,奇怪的名字,但有效。

Tab Atkins 建议 CSS 应该能够使用 font-family: sans-serif; 来实现这一点,但不幸的是,它并不像那样工作。您将在 10.9 中获得 Helvetica,而不是 Lucida Grande。

Tab 还建议 尝试 @font-face。通过为 src 属性设置多个 local() 值,它可以工作

@font-face {
  font-family: "MacSystem";
  src:
    local(".HelveticaNeueDeskInterface-Regular"),
    local(".LucidaGrandeUI");
}

body {
  font-family: "MacSystem", sans-serif;
}

这里的技巧是首先选择“最稀有”的一个。当我在这台 Yosemite 10.10.1 上键入时,font-family: ".LucidaGrandeUI"; 可以正常工作,因此它必须在列表中排在第二位才能使此方法生效。

我确信,您可以将此想法扩展到 Linux 和 Windows 等其他系统,并创建一个大型的 @font-face 声明来涵盖所有方面。如果有人愿意,请随时发布,我会在这里链接它。

2016 年 9 月更新

很多网站开始使用一个本地字体栈,该栈试图使用任何“系统字体”。该字体栈看起来像

由 GitHub 使用

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

由 WordPress 管理员和 Medium 界面使用

body {
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}