11月08, 2016

css简单气泡的实现

我们先来看一下效果图吧:

tip-arrow

这种效果,如果切图是相当简单的。当然这次我们希望是用css来实现。单独一层border是无法实现空心的箭头,所以我们需要有两层。可以简单地使用beforeafter两个伪类。

在实现具体效果前,我也搜索了一下,结果找到一篇好文:可自定义配置箭头的CSS3气泡提示框

基于它,我实现下面的scss版本:

@mixin tip-arrow($colorBg, $colorBorder, $size, $pos, $borderWidth: 1px) {
    position: relative;
    background: $colorBg;
    border: $colorBorder solid $borderWidth;
    &:before, &:after {
        @if $pos == "left" {
            right: 100%;
            top: 50%;
        }
        @if $pos == "right" {
            left: 100%;
            top: 50%;
        }
        @if $pos == "top" or (length($pos) == 2 and nth($pos, 1) == "top") {
            bottom: 100%;
            left: 50%;
        }
        @if (length($pos) == 2 and nth($pos, 1) == "top") and nth($pos, 2) >= 0 {
            left: nth($pos, 2) + ($size + round($borderWidth * 1.41421356));
        }
        @if (length($pos) == 2 and nth($pos, 1) == "top") and nth($pos, 2) < 0 {
            left: unquote("calc( 100% - #{($size + round($borderWidth * 1.41421356))} - #{abs(nth($pos, 2))} )");
        }
        @if $pos == "bottom" or (length($pos) == 2 and nth($pos, 1) == "bottom") {
            top: 100%;
            left: 50%;
        }
        border: solid transparent;
        content: " ";
        height: 0;
        width: 0;
        position: absolute;
        pointer-events: none;
    }
    &:after {
        border-width: $size;
        @if $pos == "left" {
            border-right-color: $colorBg;
            margin-top: -$size;
        }
        @if $pos == "right" {
            border-left-color: $colorBg;
            margin-top: -$size;
        }
        @if $pos == "top" or (length($pos) == 2 and nth($pos, 1) == "top") {
            border-bottom-color: $colorBg;
            margin-left: -$size;
        }
        @if $pos == "bottom" or (length($pos) == 2 and nth($pos, 1) == "bottom") {
            border-top-color: $colorBg;
            margin-left: -$size;
        }
    }
    &:before {
        border-width: $size + round($borderWidth * 1.41421356);
        @if $pos == "left" {
            border-right-color: $colorBorder;
            margin-top: -($size + round($borderWidth * 1.41421356));
        }
        @if $pos == "right" {
            border-left-color: $colorBorder;
            margin-top: -($size + round($borderWidth * 1.41421356));
        }
        @if $pos == "top" or (length($pos) == 2 and nth($pos, 1) == "top") {
            border-bottom-color: $colorBorder;
            margin-left: -($size + round($borderWidth * 1.41421356));
        }
        @if $pos == "bottom" or (length($pos) == 2 and nth($pos, 1) == "bottom") {
            border-top-color: $colorBorder;
            margin-left: -($size + round($borderWidth * 1.41421356));
        }
    }
}

注意:上面的版本只实现了,上、下、左、右、左上、右上。左下和右下,未实现,但可以实现,只是我目前的需求里面不需要而已。

具体调用:

.dui-tip-arrow,
.dui-tip-error-arrow{
    font-size: 12px;
    display: inline-block;
    border-radius: 3px;
}

.dui-tip-arrow {
    padding: 8px 15px;
    border: #d2d2d3 solid 1px;
    &.dui-tip-left-arrow {
        @include tip-arrow(#fff, #d2d2d3, 5px, left);
    }

    &.dui-tip-right-arrow {
        @include tip-arrow(#fff, #d2d2d3, 5px, right);
    }

    &.dui-tip-top-arrow {
        @include tip-arrow(#fff, #d2d2d3, 5px, top);
    }

    &.dui-tip-top-left-arrow {
        @include tip-arrow(#fff, #d2d2d3, 5px, top 15px);
    }

    &.dui-tip-top-right-arrow {
        @include tip-arrow(#fff, #d2d2d3, 5px, top -15px);
    }

    &.dui-tip-bottom-arrow {
        @include tip-arrow(#fff, #d2d2d3, 5px, bottom);
    }
}

.dui-tip-error-arrow {
    height: 18px;
    line-height: 18px;
    background: #ffa5a5;
    color: #fff;
    padding: 0 5px;
    display: inline-block;
    border: #ffa5a5 solid 1px;
    &.dui-tip-error-left {
        @include tip-arrow(#ffa5a5, #ffa5a5, 5px, left);
    }

    &.dui-tip-error-right {
        @include tip-arrow(#ffa5a5, #ffa5a5, 5px, right);
    }

    &.dui-tip-error-top {
        @include tip-arrow(#ffa5a5, #ffa5a5, 5px, top);
    }

    &.dui-tip-error-bottom {
        @include tip-arrow(#ffa5a5, #ffa5a5, 5px, bottom);
    }

    &.dui-tip-error-top-left {
        @include tip-arrow(#ffa5a5, #ffa5a5, 5px, top 5px);
    }

    &.dui-tip-error-top-right {
        @include tip-arrow(#ffa5a5, #ffa5a5, 5px, top -5px);
    }

}

注,左上是通过top 5px,5px是指距离最左边顶点的距离。右上则是通过top -5px,负数代表它是右边,5px是指距离最右边顶点的距离。

有了这个玩意,那么将来遇到其他的气泡,就可以基于上面的代码做扩展了。

本文链接:www.my-fe.pub/post/css-tip-arrow.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。