Open fondadam opened 7 years ago
在网页中,随处可见各种三角标(小三角): tooltip提示框、下拉菜单、返回顶部按钮 ... 其中的实现方案也各式各样,虽然看起来很简单,但哪一个才是最适合我们当下需求的呢?
tooltip提示框
下拉菜单
返回顶部按钮
最近,团队内部React组件库中的某个组件(Trigger),需要给其浮层添加一个三角标,秉着再小的需求也要一个方案的原则,在这里给大家分享分享我实现这个三角标的思路以及记录下来的一些知识点。
注意控制好z-index、padding、margin等
摸清楚大致需求后,我们先将细节放一边,从简单的入手: 绘制一个实心三角。
对于纯CSS来说,最容易想到便是使用border来实现三角形的绘制,只要控制好border四条边的样式,别说上下左右朝向的三角,甚至是各种直三角、等腰三角都能轻而易举。
border
<div class="demo"></div>
.demo { width: 0; height: 0; border-width: 10px; border-color: #000 transparent transparent; border-style: solid; }
优点: 简单、快捷、兼容性好 缺点: 因为使用的是border,所以对一些阴影、渐变的添加可能难以达到你想要的效果
创建一个正方形的元素A,里面再使用伪元素创建一个被旋转了45度的正方形元素B,同时将A设置成overflow: hidden,元素B则通过定位溢出,便可完美实现一个三角标。
overflow: hidden
.demo { position: relative; width: 100px; height: 100px; background-color: transparent; overflow: hidden; } .demo:after { position: absolute; content: ""; background-color: #F00; width: 100px; height: 100px; top: -70%; transform: rotate(45deg) }
优点: 暂时没想到什么优点,就是复杂了些,但绘制其他复杂图形用此方法倒是挺不错的 缺点: 使用了CSS3(PS: IE6/7/8现在基本不考虑了吧,再说还有postcss呢
postcss
图片转换成base64编码 优点: 随意设计,想要怎么样的三角就怎样的三角 缺点: 对于较大的图片,一长串的字符串看着也闹心 (PS: 你需要先设计一个图片)
base64
使用字符如▲、▶、▼、◀,你可以用text-shadow属性添加阴影, 但可惜最多只能某两条边。 优点: 快 缺点: 可控性差
▲、▶、▼、◀
text-shadow
当然,要是觉得有趣,可以尝试用Canvas、SVG去实现。
从技术角度来看,有非常多的方案,毕竟这也是一个老掉牙的话题了。但作为一个通用组件的patch,需要考虑的地方还是很多的。因组件库使用的是React,在这里我将会从React的角度去举例。
React
通用、向后兼容... 因组件Trigger不仅是在tooltip这种场景下使用了,在该组件库中的某些地方比如SearchSelect、DatePicker中也有继承组件Trigger,所以为了兼容,需要给组件Trigger暴露一个参数showArrow去控制是否渲染这个三角标。
tooltip
SearchSelect
DatePicker
showArrow
class Trigger extends React.Component { // ... renderTriggerArrow(showArrow = false) { if (showArrow) { return ( <div className="gm-trigger-arrow"></div> ); } else { return null; } } render() { // ... return React.cloneElement(component, Object.assign({}, { children: [ this.renderTriggerArrow(true), this.renderTooltip() ] })) } }
三角标与浮层间的样式过渡不应该是突兀的 一开始我选择的是border的实现方案,简单快捷。于是便有了这样:
正因为三角标的小,所以1px的差异都会显得那么突兀,但稍微修正一下,再下移那么一点不就可以遮挡住浮层边框,完美实现浮层的提示小三角了吗? 看起来貌似基本实现需求了,但若产品说这样实心三角不好看,要设置成空心的,类似这样:
1px
transform方案
div
看到被三角标遮挡住的D了吗?
D
你也许会说,那通过控制z-index使浮层遮挡住正方形的话,这样不就没有侵入了吗?但是这样浮层和三角标间的border就被暴露出来了。
z-index
box-shadow
transform
.demo { width: 0; height: 0; border-top: 4px solid transparent; border-right: 4px solid #FFF; border-bottom: 4px solid #FFF; border-left: 4px solid transparent; box-shadow: 1px 1px 0px #DDD; transform: rotate(-135deg); }
在这里使用了box-shadow模拟三角的边框,虽然box-shadow只能模拟出两条边框,但这已经足够了,加之transform的辅助,旋转一定角度,便可实现最终效果。
为了组件的调用方便,我们应该暴露诸如arrowBgColor、arrowBorderColor这样的参数给调用者,方便直接修改三角标的border和背景,而不应该单纯暴露arrowStyle这样的参数给调用者自己去修改样式,这样会显得麻烦而且也没必要暴露。
arrowBgColor
arrowBorderColor
arrowStyle
<Trigger showArrow arrowBgColor="#FFF" arrowBorderColor='#000' > <Button /> </Trigger>
背景
在网页中,随处可见各种三角标(小三角):
tooltip提示框
、下拉菜单
、返回顶部按钮
... 其中的实现方案也各式各样,虽然看起来很简单,但哪一个才是最适合我们当下需求的呢?最近,团队内部React组件库中的某个组件(Trigger),需要给其浮层添加一个三角标,秉着再小的需求也要一个方案的原则,在这里给大家分享分享我实现这个三角标的思路以及记录下来的一些知识点。
需求list
注意控制好z-index、padding、margin等
实现方案
摸清楚大致需求后,我们先将细节放一边,从简单的入手: 绘制一个实心三角。
border实现
对于纯CSS来说,最容易想到便是使用
border
来实现三角形的绘制,只要控制好border
四条边的样式,别说上下左右朝向的三角,甚至是各种直三角、等腰三角都能轻而易举。优点: 简单、快捷、兼容性好 缺点: 因为使用的是
border
,所以对一些阴影、渐变的添加可能难以达到你想要的效果transform实现
创建一个正方形的元素A,里面再使用伪元素创建一个被旋转了45度的正方形元素B,同时将A设置成
overflow: hidden
,元素B则通过定位溢出,便可完美实现一个三角标。优点: 暂时没想到什么优点,就是复杂了些,但绘制其他复杂图形用此方法倒是挺不错的 缺点: 使用了CSS3(PS: IE6/7/8现在基本不考虑了吧,再说还有
postcss
呢图片法
图片转换成
base64
编码 优点: 随意设计,想要怎么样的三角就怎样的三角 缺点: 对于较大的图片,一长串的字符串看着也闹心 (PS: 你需要先设计一个图片)字符
使用字符如
▲、▶、▼、◀
,你可以用text-shadow
属性添加阴影, 但可惜最多只能某两条边。 优点: 快 缺点: 可控性差当然,要是觉得有趣,可以尝试用Canvas、SVG去实现。
进一步实现
从技术角度来看,有非常多的方案,毕竟这也是一个老掉牙的话题了。但作为一个通用组件的patch,需要考虑的地方还是很多的。因组件库使用的是
React
,在这里我将会从React
的角度去举例。通用、向后兼容... 因组件Trigger不仅是在
tooltip
这种场景下使用了,在该组件库中的某些地方比如SearchSelect
、DatePicker
中也有继承组件Trigger,所以为了兼容,需要给组件Trigger暴露一个参数showArrow
去控制是否渲染这个三角标。三角标与浮层间的样式过渡不应该是突兀的 一开始我选择的是
border
的实现方案,简单快捷。于是便有了这样:正因为三角标的小,所以
1px
的差异都会显得那么突兀,但稍微修正一下,再下移那么一点不就可以遮挡住浮层边框,完美实现浮层的提示小三角了吗? 看起来貌似基本实现需求了,但若产品说这样实心三角不好看,要设置成空心的,类似这样:transform方案
。但不同于单纯的实现一个三角形,在这里比较简单,先创建一个正方形div
,然后旋转45度,设置其背景颜色和浮层的背景颜色一致,再加上其相应的边框便可实现想要的浮层空心小三角的效果。 但是,这样会带来一个小问题,即有时候小三角会遮挡住浮层的元素显示:看到被三角标遮挡住的
D
了吗?你也许会说,那通过控制
z-index
使浮层遮挡住正方形的话,这样不就没有侵入了吗?但是这样浮层和三角标间的border
就被暴露出来了。border
、box-shadow
、transform
结合的方案,这种方法相对简单而且能避免上面说到的各种小问题。在这里使用了
box-shadow
模拟三角的边框,虽然box-shadow
只能模拟出两条边框,但这已经足够了,加之transform
的辅助,旋转一定角度,便可实现最终效果。最终实现
为了组件的调用方便,我们应该暴露诸如
arrowBgColor
、arrowBorderColor
这样的参数给调用者,方便直接修改三角标的border
和背景,而不应该单纯暴露arrowStyle
这样的参数给调用者自己去修改样式,这样会显得麻烦而且也没必要暴露。总结