增量 CSS 媒体查询
Incremental CSS Media Queries
考虑使用 media
查询和 transform
:
随着高度减小调整页面大小的样式表
@media (max-height: 620px) {
body {
transform: scale(0.95);
}
}
@media (max-height: 590px) {
body {
transform: scale(0.90);
}
}
@media (max-height: 560px) {
body {
transform: scale(0.85);
}
}
// and so on ...
页面 "zooms out" 随着 window 高度的减小,允许在较小的屏幕上显示全部内容。
如果我想支持小于 560px
高度的屏幕,我需要添加更多 media
查询。
请注意,对于每个 30px
的高度损失,我们在输入中调用 0.05
的比例尺。
问题:有没有办法只使用css
来定义增量媒体查询?
跟进: 如果没有纯粹的 css
解决方案,在 vanilla JS 中实现这种效果的最简单方法是什么?
编辑: 感谢大家针对此问题发布不同的解决方案。我感谢您的帮助。您的回答帮助我学习了如何改进我的代码。
单独使用 CSS 是不可能的。您可以使用 JS 通过添加 window.onresize 函数来监视 document
的 body
的大小调整和缩放。此解决方案还可以动态扩展,因此您无需担心断点或@media 查询。
function updateScale() {
let viewScale = window.innerHeight / document.documentElement.scrollHeight;
document.body.style = 'transform:scale(' + viewScale + ')';
document.documentElement.scrollHeight = window.innerHeight;
}
window.onresize = function() {
updateScale();
}
updateScale();
body {
transform-origin: 0 0;
margin: 0;
padding: 0;
overflow: hidden;
}
#block {
background-color: black;
width: 300px;
height: 4000px;
}
<div id='block'></div>
在这种情况下,您可能必须使用 vanilla JavaScript
。
因此,每个 30px
是 0.05
,或者每个 6px
从 650px
向下是 0.01
。
这意味着 600px
的数量是 1
并且每个 pixel
是 0.01/6
.
考虑到所有这些信息,我们可以使用 resize
事件来计算:
window.addEventListener('resize', changeTransform); // when resize, call changeTransform
var bodyEl = document.querySelector('body');
function changeTransform() {
var scale = 1; // default scale
if (window.innerHeight < 650) { // if window height < 650px, do magic
scale = -0.83 + (0.05/30)*window.innerHeight;
}
bodyEl.style.transform = "scale(" + scale + ")"; // apply scale (1 or the calculated one)
}
希望对您有所帮助。
@NathanFries 是正确的,这不是原生 CSS.
可以做到的
CSS 包括 viewport units 用于基于百分比的宽度和高度值,但您不能将其传递给 scale()
函数。
然后您需要将其绑定到某个 resize
事件侦听器。
这里是一个简单的例子,可能会完成你想要做的事情:
// @see https://github.com/WICG/EventListenerOptions/blob/9dcca95/explainer.md#feature-detection
// @example `elem.addEventListener('touchstart', fn, supportsPassive ? { passive: true } : false);`
var checkSupportPassiveEvents = function() {
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
},
});
window.addEventListener('testPassive', null, opts);
window.removeEventListener('testPassive', null, opts);
} catch (e) {}
return supportsPassive;
};
var supportsPassive = checkSupportPassiveEvents();
var mapRange = function(fn, inStart, inEnd, outStart, outEnd) {
if (outStart === void 0) {
outStart = inStart;
outEnd = inEnd;
inStart = 0;
inEnd = 1;
}
var inRange = inEnd - inStart,
outRange = outEnd - outStart;
return function(val) {
var original = fn((val - inStart) / inRange);
return outStart + outRange * original;
};
};
var linear = function(x) {
return x;
};
var minHeight = 320;
var maxHeight = 620;
var minScale = 0.45;
var maxScale = 1;
var screenHeightToScaleFactorInner = mapRange(linear, minHeight, maxHeight, minScale, maxScale);
var screenHeightToScaleFactor = function(height) {
if (height <= minHeight) {
return minScale;
} else if (height > maxHeight) {
return maxScale;
} else {
return screenHeightToScaleFactorInner(height);
}
};
window.addEventListener(
'resize',
function(e) {
var height = this.innerHeight;
this.document.body.style.transform = 'scale(' + screenHeightToScaleFactor(height) + ')';
},
supportsPassive ? { passive: true } : false
);
对于 CSS 解决方案,您可以考虑使用 vh
和 vw
单位,但它不可能使用比例,因为它需要一个无单位值。
另一种方法是使用 translateZ()
和一些透视来模拟比例动画。
这是一个基本示例。结果不准确,因为我只是想演示这个技巧。 运行 片段整页并调整 window 高度,您将看到元素缩放。
.box {
width:100px;
height:100px;
background:red;
transform:perspective(180px) translateZ(15vh);
transform-origin:top left;
}
<div class="box">
some text here
</div>
您只需要为不同的值找到正确的计算方法。
考虑使用 media
查询和 transform
:
@media (max-height: 620px) {
body {
transform: scale(0.95);
}
}
@media (max-height: 590px) {
body {
transform: scale(0.90);
}
}
@media (max-height: 560px) {
body {
transform: scale(0.85);
}
}
// and so on ...
页面 "zooms out" 随着 window 高度的减小,允许在较小的屏幕上显示全部内容。
如果我想支持小于 560px
高度的屏幕,我需要添加更多 media
查询。
请注意,对于每个 30px
的高度损失,我们在输入中调用 0.05
的比例尺。
问题:有没有办法只使用css
来定义增量媒体查询?
跟进: 如果没有纯粹的 css
解决方案,在 vanilla JS 中实现这种效果的最简单方法是什么?
编辑: 感谢大家针对此问题发布不同的解决方案。我感谢您的帮助。您的回答帮助我学习了如何改进我的代码。
单独使用 CSS 是不可能的。您可以使用 JS 通过添加 window.onresize 函数来监视 document
的 body
的大小调整和缩放。此解决方案还可以动态扩展,因此您无需担心断点或@media 查询。
function updateScale() {
let viewScale = window.innerHeight / document.documentElement.scrollHeight;
document.body.style = 'transform:scale(' + viewScale + ')';
document.documentElement.scrollHeight = window.innerHeight;
}
window.onresize = function() {
updateScale();
}
updateScale();
body {
transform-origin: 0 0;
margin: 0;
padding: 0;
overflow: hidden;
}
#block {
background-color: black;
width: 300px;
height: 4000px;
}
<div id='block'></div>
在这种情况下,您可能必须使用 vanilla JavaScript
。
因此,每个 30px
是 0.05
,或者每个 6px
从 650px
向下是 0.01
。
这意味着 600px
的数量是 1
并且每个 pixel
是 0.01/6
.
考虑到所有这些信息,我们可以使用 resize
事件来计算:
window.addEventListener('resize', changeTransform); // when resize, call changeTransform
var bodyEl = document.querySelector('body');
function changeTransform() {
var scale = 1; // default scale
if (window.innerHeight < 650) { // if window height < 650px, do magic
scale = -0.83 + (0.05/30)*window.innerHeight;
}
bodyEl.style.transform = "scale(" + scale + ")"; // apply scale (1 or the calculated one)
}
希望对您有所帮助。
@NathanFries 是正确的,这不是原生 CSS.
可以做到的CSS 包括 viewport units 用于基于百分比的宽度和高度值,但您不能将其传递给 scale()
函数。
然后您需要将其绑定到某个 resize
事件侦听器。
这里是一个简单的例子,可能会完成你想要做的事情:
// @see https://github.com/WICG/EventListenerOptions/blob/9dcca95/explainer.md#feature-detection
// @example `elem.addEventListener('touchstart', fn, supportsPassive ? { passive: true } : false);`
var checkSupportPassiveEvents = function() {
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
},
});
window.addEventListener('testPassive', null, opts);
window.removeEventListener('testPassive', null, opts);
} catch (e) {}
return supportsPassive;
};
var supportsPassive = checkSupportPassiveEvents();
var mapRange = function(fn, inStart, inEnd, outStart, outEnd) {
if (outStart === void 0) {
outStart = inStart;
outEnd = inEnd;
inStart = 0;
inEnd = 1;
}
var inRange = inEnd - inStart,
outRange = outEnd - outStart;
return function(val) {
var original = fn((val - inStart) / inRange);
return outStart + outRange * original;
};
};
var linear = function(x) {
return x;
};
var minHeight = 320;
var maxHeight = 620;
var minScale = 0.45;
var maxScale = 1;
var screenHeightToScaleFactorInner = mapRange(linear, minHeight, maxHeight, minScale, maxScale);
var screenHeightToScaleFactor = function(height) {
if (height <= minHeight) {
return minScale;
} else if (height > maxHeight) {
return maxScale;
} else {
return screenHeightToScaleFactorInner(height);
}
};
window.addEventListener(
'resize',
function(e) {
var height = this.innerHeight;
this.document.body.style.transform = 'scale(' + screenHeightToScaleFactor(height) + ')';
},
supportsPassive ? { passive: true } : false
);
对于 CSS 解决方案,您可以考虑使用 vh
和 vw
单位,但它不可能使用比例,因为它需要一个无单位值。
另一种方法是使用 translateZ()
和一些透视来模拟比例动画。
这是一个基本示例。结果不准确,因为我只是想演示这个技巧。 运行 片段整页并调整 window 高度,您将看到元素缩放。
.box {
width:100px;
height:100px;
background:red;
transform:perspective(180px) translateZ(15vh);
transform-origin:top left;
}
<div class="box">
some text here
</div>
您只需要为不同的值找到正确的计算方法。