Box arrow to take background colour of respective box

最后都变了- 提交于 2019-12-25 02:49:12

问题


I'll try to explain this as simple as possible:

For this example I want the arrow of each box to take the background colour of its respective box automatically by only adding red, black, grey classes to the box. I could easily do:

    .box.red {
      &:before {
        ...
        border-bottom: 1px solid $red;

      }
    }
   .box.black {
      &:before {
        ...
        border-bottom: 1px solid $black;

      }
    }
   .box.grey {
      &:before {
        ...
        border-bottom: 1px solid $grey;

      }
    }

But this implies that for every different colour I create I'll have to change the arrow colour manually. If in the future I want to add a green box for example I'll have to change its arrow colour to green in the CSS. Is there a way in Sass to make it so I don't need to worry with changing the arrow colour every time the box background colour changes?

Thank you.

See DEMO


回答1:


Since your element will have solid color you can create the arrow with a rectangle on where you apply rotation in order to achieve the layout then you can use inherit for background

.box {
  position: relative;
  width: 100px;
  height: 100px;
  margin-bottom: 40px;
  background:red;
}
.box::before {
  content:"";
  position:absolute;
  width:30px;
  height:30px;
  top:100%;
  left:20px;
  transform:translateY(-50%) rotateX(40deg) rotate(45deg);
  background:inherit;
}

.blue {
  background:blue;
}
.green {
  background:green;
}
<div class="box">

</div>

<div class="box blue">

</div>
<div class="box green">

</div>

You can also rely on CSS variable and you will be able to change the color only once even if it's used in many places.

Here is another way to create the shape where you can easily control the color, size and position of the arrow:

.box {
  position: relative;
  width: 100px;
  height: 100px;
  padding-bottom: var(--s,20px);
  margin-bottom:10px;
  background:
    linear-gradient(to top right,transparent 49.8%,var(--c,red) 50%) var(--p,20px) 100%,
    linear-gradient(to top left, transparent 49.8%,var(--c,red) 50%) calc(var(--p,20px) + var(--s,20px)) 100%,
    var(--c,red) content-box;
  background-size:var(--s,20px) var(--s,20px);
  background-repeat:no-repeat;
}

.blue {
  --c:blue;
  --s:15px;
  --p:40px;
}
.green {
  --c:green;
  --s:10px;
  --p:60px;
}
<div class="box"></div>

<div class="box blue"></div>

<div class="box green"></div>

You can easily achieve the same logic to your code:

.box {
  position: relative;
  width: 100px;
  height: 100px;
  margin-bottom: 40px;
  background:var(--c,green);
}
.box:before {
  content: ' ';
  border: solid transparent;
  border-bottom: 1px solid var(--c,green);
  border-width: 15px;
  height: 0;
  position: absolute;
  transform: rotate(180deg);
  width: 0;
  bottom: -30px;
  left: 20px;
}

.red {
  --c: #f00;
}

.black {
  --c: #000;
}

.grey {
  --c: #aaa;
}
<div class="box red"></div>
<div class="box black"></div>
<div class="box grey"></div>
<div class="box "></div>



回答2:


To get that effect, the best approach would be to use css inheritance. Since the parent box has the background set, then we can only inherit the value on the :after pseudo-element background property as well - we can't use it on the border color. Fortunately, we can get the "triangular arrow" effect without using border, but with regular background and clip-path rule instead. The full example is shown in the snippet below:

.box {
  position: relative;
  width: 100px;
  height: 100px;
  margin-bottom: 40px;
}
.box:before {
  content: '';
  position: absolute;
  background: inherit;
  clip-path: polygon(0 0, 30px 0, 15px 15px);
  width: 30px;
  height: 15px;
  bottom: -16px;
  left: 20px;
}

.red {
  background: #f00;
}

.black {
  background: #000;
}

.grey {
  background: #aaa;
}
<div class="box red"></div>
<div class="box black"></div>
<div class="box grey"></div>

Update for IE and Edge

If all of these are true:

  1. Compatibility with IE and Edge is your concern
  2. You can handle a bit of micro-duplication in your css rules
  3. You don't intend to have borders on your .box elements

then you can apply border-bottom-color to the .box class and inherit it in the :after pseudo element definition as follows:

.box {
  position: relative;
  width: 100px;
  height: 100px;
  margin-bottom: 40px;
}
.box:before {
  content: ' ';
  border-bottom: 1px solid;
  border-bottom-color: inherit;
  border-left: 1px solid transparent;
  border-right: 1px solid transparent;
  border-top: 1px solid transparent;
  border-width: 15px;
  height: 0;
  position: absolute;
  transform: rotate(180deg);
  width: 0;
  bottom: -30px;
  left: 20px;
}

.red {
  background: #f00;
  border-bottom-color: #f00;
}

.black {
  background: #000;
  border-bottom-color: #000;
}

.grey {
  background: #aaa;
  border-bottom-color: #aaa;
}
<div class="box red"></div>
<div class="box black"></div>
<div class="box grey"></div>



回答3:


This can be achieved using a SCSS mixin. See codepen here

In the linked codepen, there's a variable that defines your colors:

$color-list: (
  "red": #f00,
  "black": #000,
  "grey": #aaa,
);

This variable is the one-and-only place that the color needs to be defined. You can easily add more colors if more boxes are needed.

There is then a @mixin that adds the background-color and the colored border:

@mixin box-color() {
  @each $color in map-keys($color-list) {
    &.#{$color} {
      background: map-get($color-list, $color);
      &:before {
        content: ' ';
        border: solid transparent;
        border-bottom: 1px solid map-get($color-list, $color);
        border-width: 15px;
        height: 0;
        position: absolute;
        transform: rotate(180deg);
        width: 0;
        bottom: -30px;
        left: 20px;
      }
    }
  }
}

The mixin basically adds a new class for each color in the $color-list, and populates the class with the appropriate color for the background and pseudo element.

The mixin simply has to be included in the .box class:

.box {
  @include box-color();
  position: relative;
  width: 100px;
  height: 100px;
  margin-bottom: 40px;
}


来源:https://stackoverflow.com/questions/55090673/box-arrow-to-take-background-colour-of-respective-box

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!