场景应用
# 场景应用
# 1. 实现一个三角形
CSS绘制三角形主要用到的是border属性,也就是边框。
平时在给盒子设置边框时,往往都设置很窄,就可能误以为边框是由矩形组成的。实际上,border属性是右三角形组成的,下面看一个例子:
div{
width:0;
height:0;
border:100px solid;
border-color:orange blue red green;
}
将元素的长宽都设置为0,显示出来的效果是这样的:
所以可以根据border这个特性来绘制三角形:
(1)三角1
div{
width:0;
height:0;
border-top:50px solid red;
border-right:50px solid transparent;
border-left:50px solid transparent;
}
(2)三角2
div{
width:0;
height:0;
border-bottom:50px solid red;
border-right:50px solid transparent;
border-left:50px solid transparent;
}
(3)三角3
div{
width:0;
height:0;
border-left:50px solid red;
border-top:50px solid transparent;
border-right:50px solid transparent;
}
(4)三角4
div{
width:0;
height:0;
border-right:50px solid red;
border-top:50px solid transparent;
border-bottom:50px solid transparent;
}
(5)三角5
div{
width:0;
height:0;
border-top:50px solid red;
border-right:50px solid transparent;
}
还有很多,就不一一实现了,总体的原则就是通过上下左右边框来控制三角形的方向,用边框的宽度比来控制三角形的角度。
# 2. 实现一个扇形
用CSS实现扇形的思路和三角形基本一致,就是多了一个圆角的样式,实现一个90°的扇形:
div{
border:100px solid transparent;
width:0;
height:0;
border-radius:100px;
border-top-color:red;
}
# 3. 实现一个圆和半圆
(1)实现圆:
div{
width:100px;
height:100px;
border-radius:50%;
background-color:red;
}
注意:在使用border-radius时,使用50%和100%都可以得到一个圆,那这两个值到底有什么区别呢:border-radius的值是百分比的话,就相当于盒子的宽度和高度的百分比。如一个50px 150px的方形,如果border-radius设置为100%,则等价于:
border-radius:50% / 150px ;1
而border-radius又是由border-top-left-radius、border-top-right-radius、border-bottom-left-radius、border-bottom-right-radius组成,所有上面border-radius:100%又等价于:
border-top-left-radius:100%;
border-top-right-radius:100%;
border-bottom-left-radius:100%;
border-bottom-right-radius:100%;
或
border-top-left-radius:50px 150px;
border-top-right-radius:50px 150px;
border-bottom-left-radius:50px 150px;
border-bottom-right-radius:50px 150px;
为什么border-radius设置成100%和50%都能画成圆呢?因为,在W3C中对重合曲线做了规定:如果两个相邻的半径和超过了对应的盒子的边的长度,那么浏览器要重新计算以保证它们不重合。也就是说,如果相邻圆角的半径都设置成大于50%,那么浏览器会根据图形的实际情况做一些计算。因此,为了避免不必要的计算,建议使用border-radius: 50%。
(2)实现半圆:
div{
width:100px;
height:50px;
border-radius:0px 0px 100px 100px;
background-color:red;
}
# 4. 实现一个宽高自适应的正方形
- 利用vw来实现:
.square{
width:10%;
height:10vw;
background:tomato;
}
- 利用元素的margin/padding百分比是相对父元素width的性质来实现:
.square{
width:20%;
height:0;
padding-top:20%;
background:tomato;
}
- 利用子元素的margin-top的值来实现:
.square{
width:30%;
overflow:hidden;
background:yellow;
}
.square::after{
content:"";
display:block;
margin-top:100%;
}
# 5. 画一个梯形
<div class="trapezoid"></div>
(1)实现一个直角梯形:
.trapezoid{
height:0;
width:100px;
border-bottom:100px solid red;
border-right:40px solid transparent;
}
效果:
(2)实现一个等腰梯形
.trapezoid{
height:0;
width:100px;
border-width:0 40px 100px 40px;
border-style:none solid solid;
border-color:transparent transparent red;
}
效果:
# 6. 画一条0.5px的线
- 采用transform: scale()的方式,该方法用来定义元素的2D 缩放转换:
transform;scale(0.5,0.5);
- 采用meta viewport的方式
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimun-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
这样就能缩放到原来的0.5倍,如果是1px那么就会变成0.5px。viewport只针对于移动端,只在移动端上才能看到效果
# 7. 设置小于12px的字体
在谷歌下css设置字体大小为12px及以下时,显示都是一样大小,都是默认12px。
解决办法:
使用Webkit的内核的-webkit-text-size-adjust的私有CSS属性来解决,只要加了-webkit-text-size-adjust:none;字体大小就不受限制了。但是chrome更新到27版本之后就不可以用了。所以高版本chrome谷歌浏览器已经不再支持-webkit-text-size-adjust样式,所以要使用时候慎用。
使用css3的transform缩放属性-webkit-transform:scale(0.5); 注意-webkit-transform:scale(0.75);收缩的是整个元素的大小,这时候,如果是内联元素,必须要将内联元素转换成块元素,可以使用display:block/inline-block/...;
使用图片:如果是内容固定不变情况下,使用将小于12px文字内容切出做图片,这样不影响兼容也不影响美观。
# 8. 如何解决 1px 问题?
1px 问题指的是:在一些 Retina屏幕 的机型上,移动端页面的 1px 会变得很粗,呈现出不止 1px 的效果。原因很简单——CSS 中的 1px 并不能和移动设备上的 1px 划等号。它们之间的比例关系有一个专门的属性来描述:
windoe.devicePixelRatio= 设备物理像素 / CSS像素
打开 Chrome 浏览器,启动移动端调试模式,在控制台去输出这个 devicePixelRatio 的值。这里选中 iPhone6/7/8 这系列的机型,输出的结果就是2:
这就意味着设置的 1px CSS 像素,在这个设备上实际会用 2 个物理像素单元来进行渲染,所以实际看到的一定会比 1px 粗一些。
解决1px 问题的三种思路:
思路一:直接写 0.5px
如果之前 1px 的样式这样写:
border:1px solid #333;
可以先在 JS 中拿到 window.devicePixelRatio 的值,然后把这个值通过 JSX 或者模板语法给到 CSS 的 data 里,达到这样的效果(这里用 JSX 语法做示范):
<div id="container" data-device={{window.devicePixeRatio}}></div>
然后就可以在 CSS 中用属性选择器来命中 devicePixelRatio 为某一值的情况,比如说这里尝试命中 devicePixelRatio 为2的情况:
#container[data-device='2']{
border:0.5px solid #333;
}
直接把 1px 改成 1/devicePixelRatio 后的值,这是目前为止最简单的一种方法。这种方法的缺陷在于兼容性不行,IOS 系统需要8及以上的版本,安卓系统则直接不兼容。
思路二:伪元素先放大后缩小
这个方法的可行性会更高,兼容性也更好。唯一的缺点是代码会变多。
思路是先放大、后缩小:在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后、整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的两倍,border值设为 1px。接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的 50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border 也缩小为了 1px 的二分之一,间接地实现了 0.5px 的效果。
代码如下:
#container[data-device='2']{
position;relative;
}
#container[data-device='2']::after{
position:absolute;
top:0;
left:0;
width:200%;
height:200%;
content:'';
transform:scale(0.5);
transform-origin:left top;
box-sizing:border-box;
border:1px solid #333;
}
思路三:viewport 缩放来解决 这个思路就是对 meta 标签里几个关键属性下手:
<meta name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable-no"/>
这里针对像素比为2的页面,把整个页面缩放为了原来的1/2大小。这样,本来占用2个物理像素的 1px 样式,现在占用的就是标准的一个物理像素。根据像素比的不同,这个缩放比例可以被计算为不同的值,用 js 代码实现如下:
const sacle = 1 / windoe.devicePixeRation
// 这里metaEl 指的是 meat 标签对于的 Dom
metaEl.setAttrubute('content',"width=device-widht,user-scale=no,initial-scale=${scale}")
这样解决了,但这样做的副作用也很大,整个页面被缩放了。这时 1px 已经被处理成物理像素大小,这样的大小在手机上显示边框很合适。但是,一些原本不需要被缩小的内容,比如文字、图片等,也被无差别缩小掉了。