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

前端 未结 5 788
暗喜
暗喜 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: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;
    }

    29

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

    29

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

    29

    29

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

    29

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

    29

提交回复
热议问题