How can I correctly add a shadow and a gradient to my triangular shape?

前端 未结 5 758
暗喜
暗喜 2021-01-01 17:59

I want to make the following design:

I tried with :after and :before but it does not work. Here’s my current code:

相关标签:
5条回答
  • 2021-01-01 18:08

    Change to (only changed lines listed, keep everything else as-is):

    .design:before {
      ...
      border-left: 114px solid transparent;
      border-right: 114px solid transparent;
      ...
      width: 0;
    }
    
    0 讨论(0)
  • 2021-01-01 18:20

    Here is an idea with skew transformation and drop-shadow filter. You simply need some extra element to correctly have the gradient. The trick is to invert the skew to keep the gradient direction correct (not needed if we deal with solid color)

    .box {
      width: 150px;
      height: 150px;
      position: relative;
      z-index:0;
      overflow: hidden;
      filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
    }
    
    .box span {
      position: absolute;
      z-index:-1;
      top: 0;
      width: 50%;
      height: 100%;
      overflow: hidden;
    }
    
    .box span:first-of-type {
      left: 0;
      transform: skewY(35deg);
      transform-origin: top right;
    }
    
    .box span:last-of-type {
      right: 0;
      transform: skewY(-35deg);
      transform-origin: top left;
    }
    
    .box span::before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: linear-gradient(to bottom, blue , red );
      transform-origin: inherit;
    }
    
    .box span:first-of-type::before {
      transform: skewY(-35deg);
    }
    
    .box span:last-of-type::before {
      transform: skewY(35deg);
    }
    
    p {
     margin:0;
     color:#fff;
     font-size:45px;
     line-height:100px;
     text-align:center;
    }
    <div class="box">
      <span></span><span></span>
      <p>29</p>
    </div>

    Here is how we can do with a left or right gradient. In this case we don't need extra elements because the skew will not affect the direction:

    .box {
      width: 150px;
      height: 150px;
      position: relative;
      z-index:0;
      overflow: hidden;
      filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
    }
    
    .box:before,
    .box:after{
      content:"";
      position: absolute;
      z-index:-1;
      top: 0;
      width: 50%;
      height: 100%;
      overflow: hidden;
      background:linear-gradient(to right,blue,red);
      background-size:200% 100%;
    }
    
    .box:before{
      left: 0;
      transform: skewY(35deg);
      transform-origin: top right;
    }
    
    .box:after{
      right: 0;
      transform: skewY(-35deg);
      transform-origin: top left;
      background-position:right;
    }
    
    p {
     margin:0;
     color:#fff;
     font-size:45px;
     line-height:100px;
     text-align:center;
    }
    <div class="box">
      <p>29</p>
    </div>

    And here is with an arbitrary gradient:

    .box {
       --g:linear-gradient(45deg,blue,red 60%,yellow); /* gradient coloration*/
    
      width: 150px;
      height: 150px;
      margin:15px;
      display:inline-block;
      position: relative;
      z-index:0;
      overflow: hidden;
      filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
    }
    
    .box span {
      position: absolute;
      z-index:-1;
      top: 0;
      width: 50%;
      height: 100%;
      overflow: hidden;
    }
    
    .box span:first-of-type {
      left: 0;
      transform: skewY(35deg);
      transform-origin: top right;
    }
    
    .box span:last-of-type {
      right: 0;
      transform: skewY(-35deg);
      transform-origin: top left;
    }
    
    .box span::before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: var(--g);
      background-size:200% 100%;
      transform-origin: inherit;
    }
    
    .box span:first-of-type::before {
      transform: skewY(-35deg);
    }
    
    .box span:last-of-type::before {
      transform: skewY(35deg);
      background-position:right;
    }
    
    p {
     margin:0;
     color:#fff;
     font-size:45px;
     line-height:100px;
     text-align:center;
    }
    <div class="box">
      <span></span><span></span>
      <p>29</p>
    </div>
    
    <div class="box" style="--g:linear-gradient(-62deg,blue,red 60%,yellow)">
      <span></span><span></span>
      <p>29</p>
    </div>

    Since each element is taking 50% of the width we make the background to be 200% to have its size as the main container then we adjust the position to create the illusion of one background. It's like each element will show half of the main background.


    An optimized version using mask

    .box {
      width: 150px;
      height: 150px;
      filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
    }
    .box > div {
      height: 100%;
      background: linear-gradient(35deg, blue, red);
      -webkit-mask: 
        linear-gradient(#fff, #fff) top/100% 70%, 
        linear-gradient(to bottom right, #fff 49.5%, transparent 50%) bottom right/50% 30%, 
        linear-gradient(to bottom left,  #fff 49.5%, transparent 50%) bottom left /50% 30%;
      mask: 
        linear-gradient(#fff, #fff) top/100% 70%, 
        linear-gradient(to bottom right, #fff 49.5%, transparent 50%) bottom right/50% 30%, 
        linear-gradient(to bottom left,  #fff 49.5%, transparent 50%) bottom left /50% 30%;
      -webkit-mask-repeat: no-repeat;
              mask-repeat: no-repeat;
    }
    p {
      margin: 0;
      color: #fff;
      font-size: 45px;
      line-height: 100px;
      text-align: center;
    }
    <div class="box">
      <div>
        <p>29</p>
      </div>
    </div>

    Or clip-path

    .box {
      width: 150px;
      height: 150px;
      filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
    }
    .box > div {
      height: 100%;
      background: linear-gradient(35deg, blue, red);
      clip-path:polygon(0 0,100% 0,100% 70%,50% 100%,0 70%);
    }
    p {
      margin: 0;
      color: #fff;
      font-size: 45px;
      line-height: 100px;
      text-align: center;
    }
    <div class="box">
      <div>
        <p>29</p>
      </div>
    </div>

    0 讨论(0)
  • 2021-01-01 18:25

    You can use clip-path as I did. Here is my solution.

    .design {
      background: #ea053a;
      -webkit-clip-path: polygon(50% 0%, 100% 0, 100% 75%, 50% 100%, 0% 75%, 0 0);
      clip-path: polygon(50% 0%, 100% 0, 100% 75%, 50% 100%, 0% 75%, 0 0);
      height: 155px;
      width: 155px;
    }
    
    .month {
      text-align:center;
      padding: 1rem 0 .25rem 0;
      color:#fff;
      font-weight:bold;
      font-size: 18px;
    }
    
    .day {
      text-align: center;
      font-size: 60px;
      font-weight:bold;
      color: #fff;
    }
    <div class="design">
      <div class="month">Diciembre</div>
      <div class="day">29</div>
    </div>

    0 讨论(0)
  • 2021-01-01 18:26

    If you change your CSS to the following minor changes, then you can achieve the result that you have expected:

    .design {
      background: #ea053a;
      display: inline-block;
      height: 100px;
      margin-left: 33px;
      margin-right: 40px;
      position: relative;
      width: 180px;
    }
    
    .design:before {
      border-top: 43px solid #ea053a;
      border-left: 90px solid transparent;
      border-right: 90px solid transparent;
      margin-right: 40px;
      content: "";
      height: 0;
      left: 0;
      position: absolute;
      top: 0px;
      margin-top: 100px;
      width: 0;
    }
    

    Here is the working of the above CSS:

    .design {
      background: #ea053a;
      display: inline-block;
      height: 100px;
      margin-left: 33px;
      margin-right: 40px;
      position: relative;
      width: 180px;
    }
    
    .design:before {
      border-top: 43px solid #ea053a;
      border-left: 90px solid transparent;
      border-right: 90px solid transparent;
      margin-right: 40px;
      content: "";
      height: 0;
      left: 0;
      position: absolute;
      top: 0px;
      margin-top: 100px;
      width: 0;
    }
    <div class="design">
    
    </div>

    Hope this was helpful.

    My Fiddle

    0 讨论(0)
  • 2021-01-01 18:28

    Here is my solution to add shadow and gradient to the shape

    .design {
      background: #ea053a;
      display: inline-block;
      height: 155px;
      margin-left: 33px;
      margin-right: 40px;
      position: relative;
      width: 228px;
      filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.8));
     
    }
    
    .triangle {
      position: absolute;
      height: 100px;
      top: 155px;
      width: 228px;
      -webkit-clip-path: polygon(49% 44%, 0% 100%, 100% 100%);
      clip-path: polygon(49% 44%, 0% 100%, 100% 100%);
      background-color: #ea053a;
      transform: rotate(180deg);
      
    }
    <div class="design">
      <div class="triangle">
      </div>
    </div>

    0 讨论(0)
提交回复
热议问题