前端工程师经常遇到要在页面上做弹出提示层,不少框架给出了非常方便的组件,只需要给某个元素附上一个类就能实现漂亮的tip效果。
这篇文档介绍如何根据CSS的border属性实现一个箭头居中显示的tip层组件。
定义通用tip类
给通用的tip类定义一些必要的样式
/* tips */
.ui-tip{
width:auto;
height:auto;
padding:.3rem;
margin:0 auto;
position:relative;
text-align:center;
border-radius:5px;
}
接着定义一个箭头类,因为不是所有的tip层都需要箭头,只要给需要箭头的tip层加上这个类就能出现箭头,去掉类名即去掉箭头。
/* tip with arrow */
.ui-tip-arrow::before,.ui-tip-arrow::after{
content: "";
display: block;
position: absolute;
width: 0;
height: 0px;
border-width: .25rem;
border-style: solid;
}
这里定义了::before
和::after
两个伪元素,为什么要两个?这个问题在后面解释,先往下看。
再定义两个类,分别是向上的箭头和向下的箭头:
/* arrow up */
.ui-tip-arrow.ui-tip-arrow-up::after{
border-left-color: transparent;
border-top-color: transparent;
bottom:100%;
right:50%;
}
.ui-tip-arrow.ui-tip-arrow-up::before{
border-right-color: transparent;
border-top-color: transparent;
bottom:100%;
left:50%;
}
/* arrow down */
.ui-tip-arrow.ui-tip-arrow-down::after{
border-left-color: transparent;
border-bottom-color: transparent;
right:50%;
top:100%;
}
.ui-tip-arrow.ui-tip-arrow-down::before{
border-right-color: transparent;
border-bottom-color:transparent;
left:50%;
top:100%;
}
利用两个伪元素实现一个居中的箭头,这里要注意两点:
-
::before
和::after
各显示为一个箭头的左半部分和右半部分,需要调整好它们的四个边上的border
属性。 - 对
::before
和::after
两个伪元素设置好恰当的left
和right
属性值,这样他们才能居中显示。
这样一个箭头居中显示的tip类就做好了,剩下的就是给tip和箭头层定义theme,这里定义了一个黑底白字的主题:
/* a black background theme */
.ui-theme-black{background-color:rgba(48,48,48,1);color:white;}
.ui-theme-black::after,.ui-theme-black::before {border-color: rgba(48,48,48,1);}
如何使用
跟大多数的组件使用方法类似,只需要给显示为tip的元素添加对于的类名,例如:
<div class="ui-tip ui-tip-arrow ui-tip-arrow-up ui-theme-black" id="tip_1">箭头向上的tip层</div>
<div class="ui-tip ui-tip-arrow ui-tip-arrow-down ui-theme-black" id="tip_2">just code it!</div>
显示效果如下:
结语
上面提到了一个问题,就是为什么要用两个伪元素实现箭头,用一个不行么?当然可以!只是用一个伪元素的话要让箭头居中就比较困难了。
因为提示层的文字数量会变,宽度是不固定的,要让伪元素处于居中的位置,就需要给它某种规则,例如常见的固定宽度+margin
方法,或者使用伸缩盒子模型,但这些规则相对比较复杂。以后或许会使用这些方法来实现,这里暂不做讨论。
我们再把图片放大,仔细看一下上面的解决方案:
其中::before
元素的left
值为50%,确保它的左边在tip层的中间位置,然后让它的顶部和右侧的border显示为透明;::after
元素则相反,让它的right
值为50%,使其右边位于tip层的中间位置并且设置其左侧和顶部border
透明。
Good!
参考过的文档: