Using background-clip on a gradient overlay

775 Views Asked by At

What I'm trying to achieve: enter image description here

Both elements (the arrow container + full width bar) share the same gradient. What I've tried is to make both elements separately and just apply the gradient to both of them, but for obvious reasons it looks clipped:

Codepen: https://codepen.io/sigurdmazanti/pen/bGarpvJ

Snippet:

.container {
  background: white;
  width: 100%;
  height: 71px;
}

.arrow-container {
  height: 34px;
  width: 118px;
  border-radius: 15px 15px 0 0;
  text-align: center;
  margin: 0 auto;
  color: white;
  background: transparent linear-gradient(180deg, #415fb4 0%, #0e2460 100%) 0 0 no-repeat padding-box;
}

.bar {
  height: 37px;
  background: transparent linear-gradient(180deg, #415fb4 0%, #0e2460 100%) 0 0 no-repeat padding-box;
}
<div class="container">
  <div class="arrow-container">&#x2191;</div>
  <div class="bar"></div>
</div>

I then got the idea of using a full width + full height overlay with the gradient, and then using background-clip to clip the two elements, so they both share the gradient. But I'm struggling a bit with it, and it seems like I'm using it the wrong way around.

Codepen: https://codepen.io/sigurdmazanti/pen/popryWz

Snippet:

.container {
  overflow: hidden;
  background: white;
  width: 100%;
  height: 71px;
}

.bg-gradient {
  background: transparent linear-gradient(180deg, #415fb4 0%, #0e2460 100%) 0 0 no-repeat padding-box;
  background-clip: content-box;
  width: 100%;
  height: 100%;
}

.arrow-container {
  height: 34px;
  width: 118px;
  border-radius: 15px 15px 0 0;
  text-align: center;
  margin: 0 auto;
  background-color: red;
}

.bar {
  height: 37px;
  background-color: red;
}
<div class="container">
  <div class="bg-gradient">
      <div class="arrow-container">&#x2191;</div>
      <div class="bar"></div>
  </div>
</div>

I cannot use ::after & ::before pseudo-elements, they need to be two separate elements as the arrow-element needs an eventhandler. Am I on the right path, or is this even achievable?

Thank you!

1

There are 1 best solutions below

0
On BEST ANSWER

Make the height of the gradient equal to the sum of both element then control the size:

.container {
  background: white;
  height: 71px;
}

.arrow-container {
  height: 34px;
  width: 118px;
  border-radius: 15px 15px 0 0;
  text-align: center;
  margin: 0 auto;
  color: white;
  background: 
  linear-gradient(180deg, #415fb4 0%, #0e2460 100%) top/100% 71px;
}

.bar {
  height: 37px;
  background: 
  linear-gradient(180deg, #415fb4 0%, #0e2460 100%) bottom/100% 71px;
}
<div class="container">
  <div class="arrow-container">&#x2191;</div>
  <div class="bar"></div>
</div>

Or do it like below using pseudo element:

.container {
  background: white;
  height: 71px;
  position:relative; /* relative here */
  z-index: 0;
}

.arrow-container {
  height: 34px;
  width: 118px;
  border-radius: 15px 15px 0 0;
  text-align: center;
  margin: 0 auto;
  color: white;
}

.bar {
  height: 37px;
}

.arrow-container,
.bar {
 -webkit-mask:linear-gradient(#000 0 0); /* clip the gradient to the element area */
}

/* your gradient here */
.arrow-container:before,
.bar:before {
  content:"";
  position:absolute;
  inset:0;
  background: linear-gradient(180deg, #415fb4 0%, #0e2460 100%);
  z-index:-1;
}
<div class="container">
  <div class="arrow-container">&#x2191;</div>
  <div class="bar"></div>
</div>