loading...
Cover image for CSS Battle #8 - Forking Crazy

CSS Battle #8 - Forking Crazy

pheeria profile image Olzhas Askar ・6 min read

You know what? The title says it all. Forking Crazy!
This was by far the most challenging piece of all. Even though there is another one I couldn't solve yet.
The thing is, it is difficult to match the smallest details if you don't have any clue about the measurements. You'll see below loads of some magic numbers, which came up out of nowhere, after hours (or probably minutes, to be fair) of fine-tuning, and somehow managed to settle.
I will try to explain my only solution to this problem. By the way, this is by far the longest one character-wise, resulting in whopping 1454 characters! If you care about the score, and it only makes sense if you have something below 350 characters (otherwise you'll get a score of 600 for anything else) you should go and use battle tips. To be fair, you should only use them once you are fully aware of what you've done and what you're up to, because those are mainly exploits of the errors, which browser would forgive you, like omitting closing tags.

The solution

Let's start with styling the body tag. We obviously give it a background color first and then a padding, to frame our working space. So, we limit our figure to be 50px away from the top and 130px away from the sides. Keep in mind, that the written numbers include the standard browser margin of 8px. You can, of course, define all elements relative to the whole window using margins, thus reducing the number of characters, but I chose not to do so since there is enough complexity.
The whole figure will consist of five parts:

1. The upper part

This is the part where we define the upward facing tines. It carries the name of bg, short for the background since its background is the same as the one of the body. We limit its size to 140 x 20 and give it a font-size: 0, to make our inline-block divs more readable instead of packing them like sardines in a crushd tin box.
Inside we have four half circles, to be fair, which are looking to the top. Each of them has a size of 20px and darker background color. All apart from the very first one also have margin-left: 20px. Now that look at the solution once again, I think it might have been more elegantly solved by a flexbox. For that, you'd need to give a parent class display: flex and justify-content: space-between, to avoid ugly left margins. Hmm, maybe I'll write more solutions than I planned to.

2. The stripes

At the very beginning, I seriously considered making each one of the stripes an own div. But then a revelation of a repeating-linear-gradient came to and I understood it was nonsense. Instead of styling two repeating divs with respectively a darker and lighter blues, which is the worst, or styling only a darker div and repeating it with margins, which is better than the previous proposal, we take it a level higher. We create striped id of 140 x 70 with a gradient, which goes from the left to the right. Note that the colors are repeating at the beginning and the end of each stop in order to avoid the gradient effect and make it look like an evenly colored line.

3. Tines end

This part is very similar to the upper part. It has half circles, which have a lighter blue as their background and margins between them. The background of the whole line is darker.

4. The bottom

The bottom part is of size 140 x 90 and has rounded corners of 90px. There is nothing spectacular about the bottom part.

5. The stick

Maybe you shouldn't ask me about this last piece.

Magic

We are placing a stick relatively so that we can lift it above the bottom to avoid a weird gap at the conjunction if we were placing our stick statically. It has a size of 20 x 60 and margin-left: 60px. Then we lift it ten pixels by giving it a negative value.

<div class="bg">
    <div class="upward-circle"></div>
    <div class="upward-circle left-margin"></div>
    <div class="upward-circle left-margin"></div>
    <div class="upward-circle left-margin"></div>
</div>
<div id="striped"></div>
<div class="bg darker">
    <div class="downward-circle left-margin"></div>
    <div class="downward-circle left-margin"></div>
    <div class="downward-circle left-margin"></div>
</div>
<div id="bottom"></div>
<div id="stick"></div>

<style>
  body {
    padding: 42px 122px 0;
    background: #6592CF;
  }
  .bg {
    font-size: 0;
    width: 140px;
    height: 20px;
  }
  .darker {
    background: #060F55;
  }
  .left-margin {
    margin-left: 20px;
  }
  #striped {
    width: 140px;
    height: 70px;
    background: repeating-linear-gradient(
      to right,
      #060F55 0px,
      #060F55 20px,
      #6592CF 20px,
      #6592CF 40px);
  }
  #bottom {
    width: 140px;
    height: 90px;
    background: #060F55;
    border-radius: 0 0 100px 100px;
  }
  .upward-circle {
    width: 20px;
    height: 20px;
    background: #060F55;
    border-radius: 20px 20px 0 0;
    display: inline-block;
  }
  .downward-circle {
    width: 20px;
    height: 20px;
    background: #6592CF;
    border-radius: 0 0 20px 20px;
    display: inline-block;
  }
  #stick {
    width: 20px;
    height: 60px;
    z-index: 1;
    position: relative;
    top: -10px;
    background: #060F55;
    margin-left: 60px;
  }
</style>

Finally

And let's try to optimize it! We start it by using a shiny flexbox. By the way, make sure you know how flexbox and grid work if you are applying for a frontend position.

Our bg class now is a flexbox which would evenly distribute its content, creating an appropriate space in between.

.bg {
  width: 140px;
  height: 20px;
  display: flex;
  justify-content: space-between;
}

You can safely remove left-margin classes next to the upward-circle and see exactly the same outcome on that part of our figure. Suddenly, the tine-body conjunction now looks broken. Let's fix that. We reduce our width to 100px and 20px padding from both sides to recreate our figure from before.

.darker {
  width: 100px;
  padding: 0 20px;
  background: #060f55;
}

Now we can remove left-margin class completely from both HTML and CSS. And font-size: 0 as well. 1409 characters and counting. Do you feel the unbearable lightness of being yet? This is not exactly how you reduce your bundle size (you do it by removing left-pad), but that is something to keep in mind.

We can still lose some weight, though. Or, speaking more accurately, width. Since we enclosed our figure with padding from all around, let's just go and delete all that width: 140px everywhere. The elements will just take all the available space. 1355 characters.

There are two colors used throughout the task - light and dark blue. We have to have declared at least once each, but there is definitely room for improvement when you look at the current state. Light blue has to be used for body in order to give us the wanted background. What if we every other element to have a dark blue as a default background?

* * {
  background: #060f55;
}

* * means everything which is inside of the body element would have our dark blue. bg gets broken, but let's remove background: #060F55 from the other elements. That would be .darker, #bottom, .upward-circle and #stick. Now we can fix bg by specifying the lighter blue background: #6592CF. This will break the downward facing half circles and so we set background: #6592CF for darker class. 1343 characters.

upward-circle and downward-circle read like a lot of characters, especially if you reuse them lots of times. Let's extract the common logic and rename the classes. We know, that this is the main shape:

.circle {
  width: 20px;
  height: 20px;
  display: inline-block;
}

and these are the things that give the direction and color:

.up {
  border-radius: 20px 20px 0 0;
}
.down {
  background: #6592cf;
  border-radius: 0 0 20px 20px;
}

In order to shovel away just a little more, we can define border-radius of the up class to be in circle instead, thus eliminating the need of up as a separate class. down will still remain the same. If you remove 4 usages of up class in the markup, you will have only 1223 characters remaining.

Since we know exactly how much space we have in our disposal, having a fixed width and height of 400 x 300 pixels, we can rephrase our stick. We fix the position and set top and left values instead. 1200 characters.

#stick {
  width: 20px;
  height: 60px;
  position: fixed;
  top: 240px;
  left: 190px;
}

I hope you enjoyed the journey just as much as I did. Even though this challenge is basically solved using one solution, I believe this time it was deeper thought sharing. We reduced our solution by 254 characters, in which some crazy CSS hackers can fit 4 solutions of the first challenge, and it is still semantically correct, readable and maintainable. Unless you've told me there is another more elegant solution, we can be proud of ourselves.

Posted on by:

pheeria profile

Olzhas Askar

@pheeria

I want to be able to make things look beautiful.

Discussion

markdown guide