csscss-shapeslinear-gradientsradial-gradients

CSS Single Div Drawing - Shapes


I'm trying to draw using CSS gradients and a single div.

Unfortunately, there is no enough information about it so I needed to learn it myself by reading other people's code. Here are some examples:

https://codepen.io/PButcher/pen/JMRKpG

https://codepen.io/jkantner/pen/zdeJYg

https://codepen.io/jkantner/pen/ppjRBP

https://codepen.io/jkantner/pen/XMLVXa

So far, I've learned how to create only a few basic shapes:

div
{
    height: 20em;
    width: 20em;
    
    background:
        linear-gradient( 0deg, #000 0%, #000 100% ) 1em 1em / 5em 5em,
        radial-gradient( circle at center, #000 70%, transparent 70% ) 1em 7em / 5em 5em,
        linear-gradient( 45deg, #000 0%, #000 50%, transparent 50% ) 1em 13em / 5em 5em,
        linear-gradient( -45deg, #000 0%, #000 50%, transparent 50% ) 7em 1em / 5em 5em,
        linear-gradient( 135deg, #000 0%, #000 50%, transparent 50% ) 7em 7em / 5em 5em,
        linear-gradient( -135deg, #000 0%, #000 50%, transparent 50% ) 7em 13em / 5em 5em,
        radial-gradient( 100% 100% at top, #000 50%, transparent 50% ) 14em 1em / 5em 5em,
        radial-gradient( 100% 100% at bottom, #000 50%, transparent 50% ) 14em 2em / 5em 5em,
        linear-gradient( 45deg, #000 0%, #000 50%, transparent 50% ) 14em 7em / 4em 7em,
        radial-gradient( 100% 50%, #000 0%, #000 50%, transparent 50% ) 14em 14em / 5em 5em;

    background-repeat: no-repeat;
}
<div></div>

But, I wanna create more complicated shapes like, for example, this eagle's beak & feathers, or the shadow on it.

enter image description here

Can it be achieved using CSS and a single div?


Solution

  • As I commented above, we can use multiple techniques to achieve something like this :

    1. radial-gradient with either circle or ellipse and by adjusting size and position

    .elem {
     width:300px;
      height:200px;
      border:1px solid;
      background:
           radial-gradient(ellipse at center, red 15%,transparent 15%),
           radial-gradient(circle at 40px 120px, #ffc20f 20%,transparent 20%),
           radial-gradient(circle at right bottom, #000 25%,transparent 25%);
    }
    <div class="elem"></div>

    1. Linear-gradient that we can rotate and adjust size and position:

    .elem {
      width:300px;
      height:200px;
      border:1px solid;
      background:
           linear-gradient(20deg,transparent 20%,#ffc20f 20%,#ffc20f 30%,transparent 30%) no-repeat 98px -50px / 51px 151px,
           linear-gradient(-20deg,transparent 20%,#ffc20f 20%,#ffc20f 30%,transparent 30%) no-repeat 98px -50px /51px 151px,
           linear-gradient(30deg,red 20%,transparent 20%) no-repeat 10px 30px / 50px 50px,
           linear-gradient(to right,blue 20%,transparent 20%) no-repeat 70px 20px / 50px 60px,
           linear-gradient(40deg,#000 20%,transparent 20%) no-repeat 200px 20px / 15px 100px,
           linear-gradient(-40deg,#000 20%,transparent 20%) no-repeat 200px 20px / 15px 100px;
                  
    
    }
    <div class="elem" ></div>

    1. There is also the clip-path that can help you to cut your element and adjust the global shape. This will also allow you to have you element above any background. (but this feature is not yet supported by all the browser) :

    body {
      background: #f2f2f5;
    }
    
    .elem {
      background: #000;
      width: 300px;
      height: 200px;
      -webkit-clip-path: polygon(3% 39%, 13% 21%, 26% 13%, 47% 14%, 69% 21%, 83% 25%, 90% 33%, 72% 37%, 87% 45%, 62% 49%, 87% 58%, 72% 61%, 58% 62%, 42% 62%, 29% 59%, 17% 64%, 18% 50%, 21% 42%, 10% 48%, 5% 59%);
      clip-path: polygon(3% 39%, 13% 21%, 26% 13%, 47% 14%, 69% 21%, 83% 25%, 90% 33%, 72% 37%, 87% 45%, 62% 49%, 87% 58%, 72% 61%, 58% 62%, 42% 62%, 29% 59%, 17% 64%, 18% 50%, 21% 42%, 10% 48%, 5% 59%);
    }
    <div class="elem"></div>

    1. you can also use pseudo-elements that will allow you to add at max 2 new elements on which you can apply the 3 techniques above and also other CSS property like box-shadow, opacity, filter, transform, etc. This will allow you to divide the shape more easily.

    Then the main trick is to use them above each other in order to obtain the final shape.


    Here is an ugly start to show that it's possible if you are able to cut the design into different part and calulate different size/positions:

    body {
      background: red;
    }
    
    .eagle {
      width: 300px;
      height: 200px;
      position: relative;
      background: radial-gradient(circle at 100px 70px, #000 2.5%, transparent 2.5%), linear-gradient(10deg, transparent 20%, #000 20%, #000 29%, transparent 30%) no-repeat 98px -8px / 142px 86px, linear-gradient(6deg, transparent 20%, #ffc20f 20%, #ffc20f 35%, transparent 35%) no-repeat 98px -50px / 141px 168px, radial-gradient(circle at 150px 100px, #000 15%, transparent 15%), radial-gradient(circle at 110px 130px, #000 15%, transparent 15%), radial-gradient(circle at 100px 100px, #ffc20f 20%, transparent 20%), radial-gradient(circle at 100px 100px, #000 25%, transparent 25%), #ffffff;
      clip-path: polygon(18% 35%, 23% 27%, 43% 14%, 64% 10%, 81% 27%, 79% 41%, 62% 66%, 48% 74%, 63% 49%, 46% 47%, 43% 53%, 33% 53%, 34% 52%, 29% 64%, 31% 77%, 20% 69%, 20% 69%, 17% 62%, 15% 52%, 16% 41%);
      ;
    }
    
    .eagle:before {
      content: "";
      position: absolute;
      top: 17%;
      left: 60%;
      height: 22px;
      width: 30px;
      border-radius: 50%;
      background-image: radial-gradient(circle at center, #000 29%, #ffc20f 20%);
    }
    
    .eagle:after {
      content: "";
      position: absolute;
      top: 36%;
      left: 58%;
      height: 84px;
      width: 27px;
      transform: rotate(45deg) skewY(-61deg);
      background-image: linear-gradient(to right, #000 29%, #ffc20f 20%, #ffc20f 80%, #000 80%);
    }
    <div class="eagle"></div>