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

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

工具来源

Caret

Caret是Lugo 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宽度: 三角形大小
  • 边框宽度: 三角形边框大小
  • 方向: 三角形超哪个方向,主要有 toprightbottom 和 left 四个方向
  • 颜色: 边框颜色,也是实心三角形的颜色
  • 背景颜色: 制作空心三角形的内部颜色

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

定义混合宏 caret

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

  • $caret-width:用来设置三角形的大小
  • $border-width:设置边框的大小
  • $direction:设置三角形方向
  • $border-color:设置边框的颜色
  • $background-color:设置背景颜色

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

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

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

...

}

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

  • 代表方向性,比如说向下,向左,向上,向右等,这些三角形是不做定位处理,常常是跟在某个元素之后
  • 跟tooltip和Popover等提示框一起使用

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 (v3.4.12)

// Compass (v1.0.3)

// ----

@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 {

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);

}

}

CSS

.tips {

width: 200px;

height: 50px;

line-height: 50px;

text-align: center;

position: relative;

margin: 20px auto;

border: 1px solid orange;

border-radius: 3px;

}

.tips .caret {

top: -10px;

left: 10px;

position: absolute;

}

.tips .caret:before, .tips .caret:after {

content: "";

position: absolute;

}

.tips .caret:before {

top: 0;

left: 0;

border-bottom: 10px solid orange;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.tips .caret:after {

left: 1px;

top: 1px;

border-bottom: 9px solid #fff;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

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

Sass

// ----

// Sass (v3.4.12)

// Compass (v1.0.3)

// ----

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

position: $position;

&:before,

&:after {

content:"";

position: absolute;

}

@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 == 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 == 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;

}

} @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;

}

}

}

.box {

width: 100px;

height: 100px;

margin: 20px;

border: 1px solid orange;

display: inline-block;

background: orange;

position: relative;

vertical-align: middle;

&.box2 {

background-color: transparent;

border: 1px solid orange;

}

.caret-top {

bottom: 9px;

left: 20px;

@include caret(absolute,10px,1px,top,orange,#fff);

}

.caret-right {

left: -1px;

top: 20px;

@include caret(absolute,10px,1px,right,orange,#fff);

}

.caret-bottom {

top: -1px;

left: 20px;

@include caret(absolute,10px,1px,bottom,orange,#fff);

}

.caret-left {

right: 9px;

top: 20px;

@include caret(absolute,10px,1px,left,orange,#fff);

}

}

.tip{

width: 150px;

height: 50px;

background: #000;

border-radius:3px;

position: relative;

display: inline-block;

vertical-align: middle;

margin: 20px;

.caret-top{

top: -10px;

left: 10px;

@include caret(absolute,10px,1px,top,#000,#000);

}

.caret-right{

top: 10px;

right: 0px;

@include caret(absolute,10px,1px,right,#000,#000);

}

.caret-bottom{

bottom: 0px;

left: 10px;

@include caret(absolute,10px,1px,bottom,#000,#000);

}

.caret-left{

left: -10px;

top: 10px;

@include caret(absolute,10px,1px,left,#000,#000);

}

}

.tip2 {

background-color: transparent;

border: 1px solid #000;

.caret-top {

@include caret(absolute,10px,1px,top,#000,#fff);

}

.caret-right {

@include caret(absolute,10px,1px,right,#000,#fff);

}

.caret-bottom {

@include caret(absolute,10px,1px,bottom,#000,#fff);

}

.caret-left {

@include caret(absolute,10px,1px,left,#000,#fff);

}

}

CSS

.box {

width: 100px;

height: 100px;

margin: 20px;

border: 1px solid orange;

display: inline-block;

background: orange;

position: relative;

vertical-align: middle;

}

.box.box2 {

background-color: transparent;

border: 1px solid orange;

}

.box .caret-top {

bottom: 9px;

left: 20px;

position: absolute;

}

.box .caret-top:before, .box .caret-top:after {

content: "";

position: absolute;

}

.box .caret-top:before {

top: 0;

left: 0;

border-bottom: 10px solid orange;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.box .caret-top:after {

left: 1px;

top: 1px;

border-bottom: 9px solid #fff;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

.box .caret-right {

left: -1px;

top: 20px;

position: absolute;

}

.box .caret-right:before, .box .caret-right:after {

content: "";

position: absolute;

}

.box .caret-right:before {

top: 0;

left: 0;

border-left: 10px solid orange;

border-top: 10px solid transparent;

border-bottom: 10px solid transparent;

}

.box .caret-right:after {

left: 0;

top: 1px;

border-left: 9px solid #fff;

border-top: 9px solid transparent;

border-bottom: 9px solid transparent;

}

.box .caret-bottom {

top: -1px;

left: 20px;

position: absolute;

}

.box .caret-bottom:before, .box .caret-bottom:after {

content: "";

position: absolute;

}

.box .caret-bottom:before {

top: 0;

left: 0;

border-top: 10px solid orange;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.box .caret-bottom:after {

left: 1px;

top: 0;

border-top: 9px solid #fff;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

.box .caret-left {

right: 9px;

top: 20px;

position: absolute;

}

.box .caret-left:before, .box .caret-left:after {

content: "";

position: absolute;

}

.box .caret-left:before {

top: 0;

left: 0;

border-right: 10px solid orange;

border-top: 10px solid transparent;

border-bottom: 10px solid transparent;

}

.box .caret-left:after {

left: 1px;

top: 1px;

border-right: 9px solid #fff;

border-top: 9px solid transparent;

border-bottom: 9px solid transparent;

}

.tip {

width: 150px;

height: 50px;

background: #000;

border-radius: 3px;

position: relative;

display: inline-block;

vertical-align: middle;

margin: 20px;

}

.tip .caret-top {

top: -10px;

left: 10px;

position: absolute;

}

.tip .caret-top:before, .tip .caret-top:after {

content: "";

position: absolute;

}

.tip .caret-top:before {

top: 0;

left: 0;

border-bottom: 10px solid #000;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.tip .caret-top:after {

left: 1px;

top: 1px;

border-bottom: 9px solid #000;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

.tip .caret-right {

top: 10px;

right: 0px;

position: absolute;

}

.tip .caret-right:before, .tip .caret-right:after {

content: "";

position: absolute;

}

.tip .caret-right:before {

top: 0;

left: 0;

border-left: 10px solid #000;

border-top: 10px solid transparent;

border-bottom: 10px solid transparent;

}

.tip .caret-right:after {

left: 0;

top: 1px;

border-left: 9px solid #000;

border-top: 9px solid transparent;

border-bottom: 9px solid transparent;

}

.tip .caret-bottom {

bottom: 0px;

left: 10px;

position: absolute;

}

.tip .caret-bottom:before, .tip .caret-bottom:after {

content: "";

position: absolute;

}

.tip .caret-bottom:before {

top: 0;

left: 0;

border-top: 10px solid #000;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.tip .caret-bottom:after {

left: 1px;

top: 0;

border-top: 9px solid #000;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

.tip .caret-left {

left: -10px;

top: 10px;

position: absolute;

}

.tip .caret-left:before, .tip .caret-left:after {

content: "";

position: absolute;

}

.tip .caret-left:before {

top: 0;

left: 0;

border-right: 10px solid #000;

border-top: 10px solid transparent;

border-bottom: 10px solid transparent;

}

.tip .caret-left:after {

left: 1px;

top: 1px;

border-right: 9px solid #000;

border-top: 9px solid transparent;

border-bottom: 9px solid transparent;

}

.tip2 {

background-color: transparent;

border: 1px solid #000;

}

.tip2 .caret-top {

position: absolute;

}

.tip2 .caret-top:before, .tip2 .caret-top:after {

content: "";

position: absolute;

}

.tip2 .caret-top:before {

top: 0;

left: 0;

border-bottom: 10px solid #000;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.tip2 .caret-top:after {

left: 1px;

top: 1px;

border-bottom: 9px solid #fff;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

.tip2 .caret-right {

position: absolute;

}

.tip2 .caret-right:before, .tip2 .caret-right:after {

content: "";

position: absolute;

}

.tip2 .caret-right:before {

top: 0;

left: 0;

border-left: 10px solid #000;

border-top: 10px solid transparent;

border-bottom: 10px solid transparent;

}

.tip2 .caret-right:after {

left: 0;

top: 1px;

border-left: 9px solid #fff;

border-top: 9px solid transparent;

border-bottom: 9px solid transparent;

}

.tip2 .caret-bottom {

position: absolute;

}

.tip2 .caret-bottom:before, .tip2 .caret-bottom:after {

content: "";

position: absolute;

}

.tip2 .caret-bottom:before {

top: 0;

left: 0;

border-top: 10px solid #000;

border-left: 10px solid transparent;

border-right: 10px solid transparent;

}

.tip2 .caret-bottom:after {

left: 1px;

top: 0;

border-top: 9px solid #fff;

border-left: 9px solid transparent;

border-right: 9px solid transparent;

}

.tip2 .caret-left {

position: absolute;

}

.tip2 .caret-left:before, .tip2 .caret-left:after {

content: "";

position: absolute;

}

.tip2 .caret-left:before {

top: 0;

left: 0;

border-right: 10px solid #000;

border-top: 10px solid transparent;

border-bottom: 10px solid transparent;

}

.tip2 .caret-left:after {

left: 1px;

top: 1px;

border-right: 9px solid #fff;

border-top: 9px solid transparent;

border-bottom: 9px solid transparent;

}

结论

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

以上是 如何通过 Sass 将工具转换成可用的混合宏 的全部内容, 来源链接: utcz.com/z/264167.html

回到顶部