如何通过Sass将工具转换成可用的混合宏

为了提高码农的开发效率,现在在线上有很多在线小工具,这些小工具可以帮助大家快速实现自己需要的效果,并且可以生成可用代码。前几天看到一个制作三角的小工具,尝试着使用Sass来将其转换成可用的混合宏。尝试成功,来说说怎么实现的。其实只要你有时间,很多小工具都可以用类似的方法来实现。

工具来源

Caret

CaretLugo Labs分享的一个制作三角形的在线小工具,在这个小工具中,你只要修改几个参数,就能生成你需要的三角形,如图:

Caret

来简单的看一个示例,我们调整几个小参数:

自动就会生成所需的三角形代码:

.caret {
  position: relative;
}

.caret:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border-top: 50px solid #9a1b1b;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
}

.caret:after {
  content: '';
  position: absolute;
  left: 5px;
  top: 0;
  border-top: 45px solid #ece6e1;
  border-left: 45px solid transparent;
  border-right: 45px solid transparent;
}

实现原理这里就不多说了,就是使用border和伪类:after:before来实现。

工具分析

从Caret小工具中可以非常明显的得知,制作三角形只需要五个参数:

文章开头的图中,可以获悉,三角形分为两种,一种是实心三角形,另一种是空心三角形。当边框大小和Caret宽度相等时三角形呈一个实心三角形,另外当背景颜色和边框颜色相同时,也会呈实心三角形。只有这两种情形都不具备之时,才会是一个空心三角形。

定义混合宏caret

如果要实现一个类似于caret工具的混合宏,也需要给这个混合宏传相同的参数。假设定义的混合宏名caret,给混合宏传递的参数有:

除此之外,在工具的基础我们添加另一个参数$position用来控制三角形的定位形式。

如此一来,caret的混合宏所传的参数就有六个:

@mixin caret($position, $caret-width, $border-width, $direction, $border-color, $background-color){
    ...
}

三角形在Web使用中常见的地方,主要会有:

Caret

制作三角形都是依赖于元素的伪类:before:after来实现,而且都是通过绝对定位来控制三角形。

@mixin caret($position,$caret-width,$border-width,$direction,$border-color,$background-color){
  position: $position;

  &:before,
  &:after {
    content:"";
    position: absolute;
  }
}

注:由于我们三角形同时需要实现空心和实心两种三角形风格,因此在这个混合宏中同时使用了:before:after

三角形方向有四种方向,因此使用Sass的@if{}@else if{}根据$direction参数传的值来判断三角形的方向。而且每个方向的不同时,对应的CSS属性topleftborder值不一样。共中最为关键的是border中的border-widthborder-color

由于三角形有空心和实心之分,所以在计算boder-width的值时,是通过混合宏中$caret-width$border-width差值来决定。

$caret-width - $border-width

当其值为0时,生成的三角形是实现三角形,反之将是空心三角形。

对于空心三角表,则通过:before:after层叠造成的一个假像来实现,如下图:

Caret

上图演示的是向下三角形,那么根据$direction传递的参数,根据同样的原理,可以得到:

@mixin caret($position,$caret-width,$border-width,$direction,$border-color,$background-color){
  position: $position;

  &:before,
  &:after {
    content:"";
    position: absolute;
  }
  @if $direction == top {
    &:before {
      top:0;
      left: 0;
      border-bottom: $caret-width solid $border-color;
      border-left: $caret-width solid transparent;
      border-right: $caret-width solid transparent;
    }
    &:after {
      left: $border-width;
      top: $border-width;
      border-bottom: ($caret-width - $border-width) solid $background-color;
      border-left: ($caret-width - $border-width) solid transparent;
      border-right: ($caret-width - $border-width) solid transparent;
    }
  }
  @else if $direction == right {
    &:before {
      top:0;
      left: 0;
      border-left: $caret-width solid $border-color;
      border-top: $caret-width solid transparent;
      border-bottom: $caret-width solid transparent;
    }
    &:after {
      left: 0;
      top: $border-width;
      border-left: ($caret-width - $border-width) solid $background-color;
      border-top: ($caret-width - $border-width) solid transparent;
      border-bottom: ($caret-width - $border-width) solid transparent;
    }
  }
  @else if $direction == bottom {
    &:before {
      top:0;
      left: 0;
      border-top: $caret-width solid $border-color;
      border-left: $caret-width solid transparent;
      border-right: $caret-width solid transparent;
    }
    &:after {
      left: $border-width;
      top: 0;
      border-top: ($caret-width - $border-width) solid $background-color;
      border-left: ($caret-width - $border-width) solid transparent;
      border-right: ($caret-width - $border-width) solid transparent;
    }
  } 
  @else if $direction == left {
    &:before {
      top:0;
      left: 0;
      border-right: $caret-width solid $border-color;
      border-top: $caret-width solid transparent;
      border-bottom: $caret-width solid transparent;
    }
    &:after {
      left: $border-width;
      top: $border-width;
      border-right: ($caret-width - $border-width) solid $background-color;
      border-top: ($caret-width - $border-width) solid transparent;
      border-bottom: ($caret-width - $border-width) solid transparent;
    }
  }
}

示例

混合宏完成了,实战一回。

假设你需要制作一个tips,可以简单的像这样使用:

HTML

<div class="tips">
  <span class="caret"></span>
  我是一个tooltip
</div>

SCSS

.tips {
  width: 200px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  position: relative;
  margin: 20px auto;
  border: 1px solid orange;
  border-radius: 3px;

  .caret {
    top: -10px;
    left: 10px;
    @include caret(absolute,10px,1px,top,orange,#fff);
  }
}

效果

下面的示例中,演示了其他几种三种形式:

结论

使用Sass实现三角形的方案多种,但这篇文章仅仅是想向大家介绍的是如何使用Sass这样的预处理器,将在线的小工具转换成实用的混合宏。如果您对此感兴趣,可以自己动手试试别的小工具。欢迎在下面的评论中与我们一起分享你定义的混合宏。

出处:http://www.w3cplus.com/preprocessor/caret-mixin.html