DEV Community

Cover image for CSS Battle #10 - Cloaked Spirits
Olzhas Askar
Olzhas Askar

Posted on

CSS Battle #10 - Cloaked Spirits

Times don't get no better, boys. The number ten is a special one. It is the first two-digit number. It is a famous football shirt number. In fact, it is so famous, that Turks would call something on numara, number ten, in order to express admiration. As for the challenge, it is going to be fun.

1. Div Way

Let's start with defining what we'll need. Three columns, squeezed together, with circle shapes on top. So, we'll make three divisions, having one another division inside each of them. In order to differentiate them from each other let's call the outer div column and the inner one circle. Here is the markup.

<div class="column">
    <div class="circle"></div>
</div>
<div class="column">
    <div class="circle"></div>
</div>
<div class="column">
    <div class="circle"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

All of this needs to be on a purple background. In order to create a frame for our shapes, let's restrict them by styling body tag. Note, that I am using a zero-padding and font-size: 0. And because of declaring padding we can't use * selector.

body {
  padding: 42px 30px 30px 42px;
  font-size: 0;
  background: #62306d;
}
Enter fullscreen mode Exit fullscreen mode

Then we switch to the columns. A column should have a width of 100px, a height of 150px, inline-block display obviously, otherwise, why would we be setting the font size to zero? All this on a nice yellow background with circled borders.

.column {
  width: 100px;
  height: 150px;
  display: inline-block;
  background: #f7ec7d;
  border-radius: 50px 50px 0 0;
}
Enter fullscreen mode Exit fullscreen mode

The code above doesn't work quite yet, because there is always an exception to a rule. The middle shape is almost like showing us a middle finger, it needs some special treatment. It's funny how :nth-child() is not zero-indexed. Nonetheless, we adjust the height, effectively pushing the side columns down.

.column:nth-child(2) {
  height: 250px;
}
Enter fullscreen mode Exit fullscreen mode

Inside of each column, we already have a division defined to represent a circle. We set width and height to the same sixty pixels and border-radius to fifty percent to get a circle. We add a border of twenty pixels and background color.

.circle {
  width: 60px;
  height: 60px;
  border: 20px solid #aa445f;
  background: #e38f66;
  border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

Our special snowflake, the middle column, needs to be adjusted again. This time we change the background and the border color.

.column:nth-child(2) .circle {
  background: #aa445f;
  border-color: #e38f66;
}
Enter fullscreen mode Exit fullscreen mode

In case you didn't know, a border color and box-shadow default to the color attribute of an element, if omitted. So, we could rewrite our colors in the following manner.

.circle {
  width: 60px;
  height: 60px;
  border: 20px solid;
  border-radius: 50%;
  color: #aa445f;
  background: #e38f66;
}
.column:nth-child(2) .circle {
  color: #e38f66;
  background: #aa445f;
}
Enter fullscreen mode Exit fullscreen mode

So, this is it. You can start playing around with CSS to see how breaking things results in unexpected shapes. For example, try removing a height for columns or border for circles. Isn't it fun? Here you go with the full solution.

<div class="column"><div class="circle"></div></div>
<div class="column"><div class="circle"></div></div>
<div class="column"><div class="circle"></div></div>

<style>
  body {
    padding: 42px 30px 30px 42px;
    font-size: 0;
    background: #62306D;
  }
  .column {
    width: 100px;
    height: 150px;
    display: inline-block;
    background: #F7EC7D;
    border-radius: 50px 50px 0 0;
  }
  .column:nth-child(2) {
    height: 250px;
  }
  .circle {
    width: 60px;
    height: 60px;
    border: 20px solid #AA445F;
    background: #E38F66;
    border-radius: 50%;
  }
  .column:nth-child(2) .circle {
    background: #AA445F;
    border-color: #E38F66;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

2. Pseudo Way

Can we do it another way? Sure, we can. But before we do that, do you know what this (_>_) means? A nice smiley, isn't it? What if I showed you it in another context?

val ordered = seq.sort(_>_)
Enter fullscreen mode Exit fullscreen mode

It means, sort by ascending. Scala has some very unusual symbols for a developer with a background of C-like languages.
Do you what this * + * means? Clearly, it is an owl. An owl selector. After reading about it on Every Layout, I got fascinated by this simple, yet powerful idea - elements position should not be its own concern, rather its parent's. Previously, an owl selector would be used to solve this problem in an elegant way. Now we have a flexible box. Let's see how our solution would look like.

We still have three columns, but this time let's use paragraphs instead of divisions. It's semantically incorrect, I know, but you shouldn't be using CSS for drawing figures either. We choose p because of it's display: block property. To the middle element, we give an id to differentiate it from the rear ones. Notice how we don't need quotes if our attribute's value consists of a single word. Here is the markup.

<p></p>
<p id=a></p>
<p></p>
Enter fullscreen mode Exit fullscreen mode

To style a column we can reuse the same code from our previous solution. There are two differences, though. I used viewport height and viewport width as measurement units to be a little bit more soft coded, that is to allow some adaptiveness. And we also don't need display: inline-block.

p {
  width: 25vw;
  height: 50vh;
  background: #f7ec7d;
  border-radius: 12.5vw 12.5vw 0 0;
}
Enter fullscreen mode Exit fullscreen mode

Our middle ~finger~ column is restyled when it comes to height. We select it by targeting a paragraph which has an id attribute defined.

p[id] {
  height: 62.5vw;
}
Enter fullscreen mode Exit fullscreen mode

To recreate the circles, let's use pseudo-classes this time. All the same code from above, except for the addition of content: "" and display: block to make our sizing work. And of course, we overwrite background and border colors for the central column.

p:after {
  content: "";
  display: block;
  width: 20vh;
  height: 20vh;
  border: 5vw solid #aa445f;
  background: #e38f66;
  border-radius: 50%;
}
p[id]:after {
  background: #aa445f;
  border-color: #e38f66;
}
Enter fullscreen mode Exit fullscreen mode

Now we should see a white background with two columns on the left side. This is not what we want. But this is what we get, for we haven't done any placement of our elements. Here comes the missing piece.

body {
  height: calc(100vh + 8px);
  background: #62306d;
  display: flex;
  justify-content: center;
  align-items: flex-end;
}
Enter fullscreen mode Exit fullscreen mode

We specify a flex display, justify horizontally all columns to be in the center and align our items to the bottom of the screen. If you know why I had to add eight pixels to the whole height, and that's the only way I found so far to work, please let me know. I am curious as well.

So, here comes the whole solution.

<p></p>
<p id=a></p>
<p></p>

<style>
body {
  height: calc(100vh + 8px);
  background: #62306d;
  display: flex;
  justify-content: center;
  align-items: flex-end;
}
p {
  width: 25vw;
  height: 50vh;
  background: #f7ec7d;
  border-radius: 12.5vw 12.5vw 0 0;
}
p[id] {
  height: 62.5vw;
}
p:after {
  content: "";
  display: block;
  width: 20vh;
  height: 20vh;
  border: 5vw solid #aa445f;
  background: #e38f66;
  border-radius: 50%;
}
p[id]:after {
  background: #aa445f;
  border-color: #e38f66;
}
</style>
Enter fullscreen mode Exit fullscreen mode

3. Shadow Way

I've already mentioned, that if there is one thing I learned by solving these challenges then it would box-shadow. I will try to apply it here as well.

Caution! Do not try to repeat this in production!

The idea is to position three divs absolutely in relation to the whole page. Divs are named l for left, c for center and r for right.

<div id=l></div><div id=c></div><div id=r></div>
Enter fullscreen mode Exit fullscreen mode

These divs are going to be representing circles. They have the same width and height, background and border, everything like above. What makes the difference are position: fixed and specified top: 134px and left: 50px parameters.

div {
  position: fixed;
  top: 134px;
  left: 50px;
  width: 20vh;
  height: 20vh;
  background: #e38f66;
  border: 5vw solid #aa445f;
  border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

We adjust the placement and colors for the central and right elements a bit.

#c {
  top: 34px;
  left: 150px;
  background: #aa445f;
  border-color: #e38f66;
}
#r {
  left: 250px;
}
Enter fullscreen mode Exit fullscreen mode

Then we give colors to our body.

* {
  background: #62306d;
  color: #f7ec7d;
}
Enter fullscreen mode Exit fullscreen mode

You may wonder, why do we use color property? After all, we don't have any text here. The color property is taken as a default value for borders and shadows, that's why.
And here comes the jewel of the solution, the mighty box-shadow.

box-shadow: 0 10px, 0 20px, 0 30px, 0 40px, 0 50px, 0 60px, 0 70px, 0 80px,
  0 90px, 0 100px, 0 105px, 0 110px, 0 120px, 0 130px, 0 135px 0 5px, 0 190px 0
    30px;
Enter fullscreen mode Exit fullscreen mode

Just pile down a circle after circle after circle all the way down to the bottom. Initially, a ten-pixel distance is enough, but when the level of the left and right circles is reached, we will see a thin line, where the columns don't touch. So we make our last two circles bigger to cover the flaw.

Here is the whole solution.

<div id=l></div><div id=c></div><div id=r></div>

<style>
* {
  background: #62306d;
  color: #F7EC7D;
}
div {
  position: fixed;
  top: 134px;
  left: 50px;
  width: 20vh;
  height: 20vh;
  background: #e38f66;
  border: 5vw solid #aa445f;
  border-radius: 50%;
  box-shadow:0 10px, 0 20px, 0 30px, 0 40px, 0 50px, 0 60px, 0 70px, 0 80px, 0 90px, 0 100px, 0 105px, 0 110px, 0 120px, 0 130px, 0 135px 0 5px, 0 190px 0 30px;
}
#c {
  top: 34px;
  left: 150px;
  background: #aa445f;
  border-color: #e38f66;
}
#r {
  left: 250px;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Writing this took a lot of time. I hope you like it. Have a nice day!

Top comments (3)

Collapse
 
nando123 profile image
Nancy Do

1 div solution

<div></div>
<style>
  body {
    background: #62306D;
  }

  *::before, *::after {
    position: fixed; 
    content: "";
    background: #E38F66;
    color: #E38F66;
  }

  div {
    margin: 100px 142px; 
    width: 100px;
    height: 200px;
    background: #F7EC7D;
    color: #F7EC7D;
    box-shadow: 
      -100px 100px, 
      100px 100px;
  }

    div::before {
    margin: -50px 0;
    width: 100px; 
    height: 100px; 
    border-radius: 50%;
    color: #AA445F;
    box-shadow: 
      -100px 100px, 
      100px 100px;
  }

  div::after {
    margin: -30px 20px;
    width: 60px; 
    height: 60px; 
    background: #AA445F;
    border-radius: 50%;
    box-shadow: 
      -100px 100px, 
      100px 100px;
  }
</style>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
1072418776 profile image
1072418776

p{
width:0px;
height:12px;
box-shadow: 192px 138px 0 50px#F7EC7D,
192px 350px 0 150px #F7EC7D,
0 0 0 1000px #62306D

}
p:before{
content:'';
display:inline-block;
width:60px;
height:60px;
margin:162px 0 0 62px;
background:#E38F66;
box-shadow: 0 0 0 20px#AA445F,
200px 0#E38F66,
200px 0 0 20px#AA445F,
100px -100px #AA445F,
100px -100px 0 20px#E38F66;

border-radius:50%;

}

Collapse
 
santosj666 profile image
santosj666

Only started learning CSS two months ago as my first language into coding, anway heres my solution. please go easy on me XD.

body{
background:#62306D;
}
.o{
background:#E38F66;
border-radius: 50%;
box-shadow:0px 0px 0px 20px #AA445F;
}
.c{
width:60;
height:60;
position:absolute;
}
.r{
height:200;
width:100;
background:#F7EC7D;
position: absolute;
z-index:-1;
}
.a{
top:170;
left:70;
}
.b{
top:170;
right:70;
}
.d{
background:#AA445F;
border-radius: 50%;
top:70;
left:170;
box-shadow:0px 0px 0px 20px #E38F66;
}
.e{
left:150;
top:100;
}
.f,.g{
top:200;
}
.f{
right:50;
}
.g{
left:50;
}