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.
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>
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.
Top comments (13)
I have used box-shadow.
My solution, based on your:
Nice!! I only use box-shadow for fork pointed, other part are too abstract when use box-shadow.
By using flexbox make it easy and simple
Hey, can you tell me about your div placement corresponding to the solution you have provided?
Thanks in advance!
HTML code is not showing in the comment. How can I show the HTML code?
body{
margin:0;
background:#6592CF;
}
#rect {
width: 140px;
height: 150px;
background: #060F55;
position:absolute;
top:100px;
right:130px;
border-radius:10px 10px 70px 70px;
}
#srect{
width:20px;
height:50px;
background:#060F55;
position:absolute;
top:250px;
right:190px; //Note
}
#db1,#db2,#db3,#db4,#lb1,#lb2,#lb3{
width:20px;
height:120px;
border-radius:10px 10px 10px 10px;
position:absolute;
}
#db1,#db2,#db3,#db4{
top:50px;
background:#060F55;
}
#lb1,#lb2,#lb3{
background:#6592CF;
top:40px;
}
#db1{
right:250px
}
#db2{
right:210px;
}
#db3{
right:170px;
}
#db4{
right:130px;
}
#lb1{
right:230px;
}
#lb2{
right:190px;
}
#lb3{
right:150px;
}
body{
background: #6592CF;
}
.botrec{
background: #060F55;
height: 60px;
width:20px;
margin-top: 245px;
margin-left: 182px;
}
.circle{
background: #060F55;
height: 140px;
width: 140px;
border-radius: 100px;
margin-top: -195px;
margin-left: 122px;
}
.dbra{
background: #060F55;
height: 140px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -200px;
margin-left: 122px
}
.bra{
background: #6592CF;
height: 110px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -140px;
margin-left: 142px;
}
.dbrb{
background: #060F55;
height: 110px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -110px;
margin-left: 162px;
}
.brb{
background: #6592CF;
height: 110px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -110px;
margin-left: 182px;
}
.dbrc{
background: #060F55;
height: 110px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -110px;
margin-left: 202px;
}
.brc{
background: #6592CF;
height: 110px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -110px;
margin-left: 222px;
}
.dbrd{
background: #060F55;
height: 140px;
width: 20px;
border-radius: 100px / 100px;
margin-top: -110px;
margin-left: 242
}
body{
background:#6592CF;
display:flex;
align-items:center;
justify-content:center;
}
.fork-top >*{
display:flex;
gap:20px;
position:relative;
top:-45
}
div {
width: 20px;
height: 110px;
background: #060F55;
border-radius: 100vh 100vh 0 0;
}
.out-pronge{
position:absolute;
top:50;
left:150;
}
.out-pronge *{
background:#6592CF;
border-radius: 100vh;
}
.base i{
position:absolute;
width:140px;
height:100px;
bottom:50;
z-index:-1;
left:50%;
transform: translate(-50%);
background: #060F55;
border-radius: 0 0 100vh 100vh;
}
.base .b{
bottom:-10;
width:20px
}
1 div solution:
I used a grid:
A great read, yet again!