CSS Single Div Drawing - Shapes
Asked Answered
C

1

6

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?

Celesta answered 29/12, 2017 at 8:53 Comment(6)
i would say yes ... since you are able to apply multiple gradient, rotate them, adjust postion, etc ... you may also add 2 pseudo element where you apply the same thing ... BUT you need to be able to find how to cut the image into different elements to do thisSudiesudnor
@TemaniAfif I know I can add multiple gradients, but how can i rotate them? Plus, I know I need to cut the image, I just don't know how to create this feather shape. I tried a circle and triangle but no luck..Celesta
In addition to Temani’s answer, don’t forget you also have the ::before and ::after pseudo elements availible if you come out short with only one element.Cavicorn
@Cavicorn i also talked about pseudo-elements :)Sudiesudnor
@TemaniAfif You sure did! I scanned through your code samples without seeing them, but must have missed your fourth paragraph :o)Cavicorn
This is why canvas exists.Consonantal
S
1

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>
Sudiesudnor answered 29/12, 2017 at 9:56 Comment(4)
I know that I can put them on each other, I already do it (forgot to mention, sorry). I see you used a white circle to create the "rounded triangle" there, but I don't like when people use solutions like this. What if I wanna put a body background image?Celesta
@StyleShit am trying to provide the main features :) and as i said, it's an ugly start where i used white color to hide the black ... but it can be done with transparent also and this will involve time to do it. we simply need to understand the different features, try to divide the image into different portion and then code it ;) ... By the way i added more ways in my answerSudiesudnor
Saw the ways you added. The clip path looks pretty good, I'll check it out. Thanx!Celesta
@StyleShit i also updated my ugly solution so you can add a background ;)Sudiesudnor

© 2022 - 2024 — McMap. All rights reserved.