简答
不,您不能仅使用 CSS 来做到这一点。但是,您可以使用类似于您在问题中提到的方法(测量字体大小并相应地调整布局)来最小化影响。
长答案
您不能仅使用 CSS 来做到这一点,但是可以拥有一个无需重绘的高性能网站,并且可以回退到 no JS 的默认样式。
这种方法有一个缺点,您最终会在页面中注入样式表,这会影响第一次内容绘制时间。但是请记住,这与匹配媒体查询本质上是相同的(因此实际上,这与媒体查询之间没有区别,只是它依赖于 JavaScript)。
您可以通过内联相关样式来缓解这种情况,但显然这会带来页面权重成本。你将不得不决定哪个是更大的罪!
解决方法很简单。
(1) 使用与您描述的方法类似的方法计算出用户的字体大小。
(2) 根据需要加载覆盖关键布局选项的条件 CSS。
(2a) 或者向正文添加一个类,并根据现有样式表中的样式更改布局,或者如果在折叠上方,则在文档中内联。
1。计算出用户的字体大小
您可以在原版 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(默认大小)即可获得 %age scale。
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>