目录
一、横屏适配
很多视口我们要对横屏和竖屏显示不同的布局,所以我们需要检测在不同的场景下给定不同的样式:
1、JavaScript检测横屏
获取屏幕旋转方向:window.orientation
window.addEventListener("resize", ()=>{
if (window.orientation === 180 || window.orientation === 0) {
// 正常方向或屏幕旋转180度
console.log('竖屏');
};
if (window.orientation === 90 || window.orientation === -90 ){
// 屏幕顺时钟旋转90度或屏幕逆时针旋转90度
console.log('横屏');
}
});
2、CSS检测横屏
@media screen and (orientation: portrait) {
/*竖屏...*/
}
@media screen and (orientation: landscape) {
/*横屏...*/
}
二、图片模糊问题
1、产生原因
我们平时使用的图片大多数都属于位图( png、jpg...
),位图由一个个像素点构成的,每个像素都具有特定的位置和颜色值:
理论上,位图的每个像素对应在屏幕上使用一个物理像素来渲染,才能达到最佳的显示效果。
而在 dpr>1
的屏幕上,位图的一个像素可能由多个物理像素来渲染,然而这些物理像素点并不能被准确的分配上对应位图像素的颜色,只能取近似值,所以相同的图片在 dpr>1
的屏幕上就会模糊:
2、解决方案
为了保证图片质量,我们应该尽可能让一个屏幕像素来渲染一个图片像素,所以,针对不同 DPR
的屏幕,我们需要展示不同分辨率的图片。
如:在 dpr=2
的屏幕上展示两倍图 (@2x)
,在 dpr=3
的屏幕上展示三倍图 (@3x)
。
3、media查询
使用 media
查询判断不同的设备像素比来显示不同精度的图片
.avatar{
background-image: url(conardLi_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
.avatar{
background-image: url(conardLi_2x.png);
}
}
@media only screen and (-webkit-min-device-pixel-ratio:3){
.avatar{
background-image: url(conardLi_3x.png);
}
}
只适用于背景图
4、image-set
使用 image-set
:
.avatar {
background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}
只适用于背景图
5、srcset
使用 img
标签的 srcset
属性,浏览器会自动根据像素密度匹配最佳显示图片:
<img src="conardLi_1x.png"
srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">
6、JavaScript 拼接图片url
使用 window.devicePixelRatio
获取设备像素比,遍历所有图片,替换图片地址:
const dpr = window.devicePixelRatio;
const images = document.querySelectorAll('img');
images.forEach((img)=>{
img.src.replace(".", `@${dpr}x.`);
})
7、使用svg
SVG
的全称是可缩放矢量图( ScalableVectorGraphics
)。不同于位图的基于像素, SVG
则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。
除了我们手动在代码中绘制 svg
,我们还可以像使用位图一样使用 svg
图片:
<img src="conardLi.svg">
<img src="data:image/svg+xml;base64,[data]">
.avatar {
background: url(conardLi.svg);
}
三、1px问题
为了适配各种屏幕,我们写代码时一般使用设备独立像素来对页面进行布局。而在设备像素比大于
1
的屏幕上,我们写的1px
实际上是被多个物理像素渲染,这就会出现1px
在有些屏幕上看起来很粗的现象。
1、border-image
基于 media
查询判断不同的设备像素比给定不同的 border-image
:
.border_1px {
border-bottom: 1px solid #000;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {
.border_1px {
border-bottom: none;
border-width: 0 0 1px 0;
border-image: url(../img/1pxline.png) 0 0 2 0 stretch;
}
}
2、background-image
和 border-image
类似,准备一张符合条件的边框背景图,模拟在背景上。
.border_1px {
border-bottom: 1px solid #000;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {
.border_1px {
background: url(../img/1pxline.png) repeat-x left bottom;
background-size: 100% 1px;
}
}
上面两种都需要单独准备图片,而且圆角不是很好处理,但是可以应对大部分场景。
3、伪类 + transform
基于 media
查询判断不同的设备像素比对线条进行缩放:
.border_1px:before {
content: '';
position: absolute;
top: 0;
height: 1px;
width: 100%;
background-color: #000;
transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {
.border_1px:before {
transform: scaleY(0.5);
}
}
@media only screen and (-webkit-min-device-pixel-ratio:3) {
.border_1px:before {
transform: scaleY(0.33);
}
}
这种方式可以满足各种场景,如果需要满足圆角,只需要给伪类也加上 border-radius
即可。
4、svg
上面我们 border-image
和 background-image
都可以模拟 1px
边框,但是使用的都是位图,还需要外部引入。
借助 PostCSS
的 postcss-write-svg
我们能直接使用 border-image
和 background-image
创建 svg
的 1px
边框:
@svg border_1px {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%;
}
}
.example {
border: 1px solid transparent;
border-image: svg(border_1px param(--color #00b1ff)) 2 2 stretch;
}
上面的方案是大漠在他的文章中推荐使用的,基本可以满足所有场景,而且不需要外部引入,这是我个人比较喜欢的一种方案。