A little over a week ago you may have seen us launch our second Code Challenge – a partnership with our friends at CSSBattle.dev. CSS battles are a relatively new concept – the site launched in April – and it’s not always immediately obvious how they work.
![The default output and editor panels in CSSbattle.](https://uploads.sitepoint.com/wp-content/uploads/2019/06/1561340139default.jpg)
The default output and editor panels in CSSbattle.
In simple terms:
- Your objective is to create a copy of the ‘target’ image using only HTML & CSS
- You can’t use external images
- You can’t use SVG (even inline SVG) or special characters
- All solutions are automatically scored for both accuracy and efficiency (character count)
- The player who recreates the target image with the highest score wins
I have to admit when I first saw the idea, I was a little incredulous. How on earth could anyone create THOSE designs using less than a ‘tweets-worth’ of HTML and CSS? That’s just not possible, surely?
So I tried and mostly failed – but I also learned and gradually began to understand some of the tricks you need. If you’re curious, I thought I’d walk through 4 tips to help you score higher.
Let me be clear: As I write this post, I’m ranked in 24th position for this battle round. I’ve completed every target so far and rank 26th overall, so there are undoubtedly at least two dozen or so players with much better solutions than me. However, I’m happy to share what I know – and take advice from anyone with better ideas.
Tip #1: An empty Output panel is never TRULY empty
The first time you load any target you’ll see something like the image above. Your editor always comes pre-filled with example HTML and CSS providing a rudimentary starting position. However, even if you delete every single character in your editor, your Output panel will still not technically be empty.
Why not? If you Inspect the source of the Output panel (hint: switch off the ‘Slide & Compare’ function for now), you’ll find an <iframe>
that contains two invisible elements – an <html>
and a <body>
element.
As you can see in the image below, you can see they are present with a line of CSS. Of course, you are perfectly free to style these two HTML elements without having to spend any characters creating them.
![A screen showing both HTML and BODY elements with a red dashed outline.](https://uploads.sitepoint.com/wp-content/uploads/2019/06/1561341878two-elements.jpg)
There is always a HTML and a BODY element ready to style.
This doesn’t mean that you never add your own HTML elements – <DIV>
s, <P>
s, <I>
s, etc – but always try to use the free ‘built-in elements’ first.
Tip #2: Choose your Units of Measure Carefully
CSSBattle targets are always 400px wide by 300px high, so you could correctly describe the centerpoint as left:200px
(that’s 10 characters) and top:150px
(9 characters). However, you can just as easily describe that exact position as left:50%
(8 characters) and top:50%
(7 characters). That’s a handy saving of 4 characters.
Percentages don’t always win though. The position top:100px
(9 characters) translates to top:33.33%
(10 characters) – a backwards step. There’s quite a bit of trial and error finding the best fit. Potentially useful measurement units include:
- Pixels:
px
- Percentages:
%
- Rems:
rem
- Ems:
em
- Inches:
in
- Millimeters:
mm
- Picas:
pc
- Points:
pt
- Viewport height units: v
h
- Viewport width Units:
vw
- Quarter of a millimetre:
q
That last unit type – the ‘q’ – is a relatively little-known unit. But as it’s a single character – I find it uncommonly useful in CSS battles. I’ve found 50px translates to 53 q’s.
Also note that some CSS properties will assume you mean pixels if you don’t explicitly declare a unit type. In other words, width:80
renders the same as width:80px
. Height and margin are the same. On the flipside, box-shadow
fails completely if you don’t declare a unit of measure.
Tip #3: CSS is a Cascade – Take full advantage of it.
CSS is really good at ‘inheritance’ and ‘specificity’. Inheritance allows child elements to get their styles from their parents. ‘Specificity’ means broad rules get overwritten by more carefully or recently declared rules.
In CSS the broadest rule is the *
wildcard, which means ‘apply to all elements’. So, the following rule applies a #222 background to everything. If we don’t add any extra HTML, this is a <html>
and a <body>
.
*{background:#222}
If we then follow that with a more specific rule targeting only the <body>
, we just styled the <html>
without having to name it directly – a saving of 3 characters.
*{background:#222}
body{background:#F2994A}
Let’s take it one step further.
In CSS the ‘>’ operator means ‘only when X is a parent of Y’ (i.e x>y{}
). So, if we write:
*>*{...}
… we’re saying ‘only apply this rule to any element that is inside any another element’ – in other words, ANY child element.
As the HTML element is never a child, only the <BODY>
gets that second rule. We save another character.
<style>
*{background:#222}
*>*{background:#F2994A}
</style>
Tip #4: Browsers are tough. Make them work.
Once you’ve taken all the low-hanging fruit, there comes a point where the only practical way to cut characters is to remove code that is technically required but not absolutely critical to the final render. You might say that modern browsers will look kindly on your short and slightly ill-mannered code. This includes but isn’t limited to:
- Deleting the closing
</style>
- Deleting closing HTML tags (i.e
</p>
,</div>
) - Deleting the final closing
}
of your style block - Removing most spaces and carriage returns. Trial and error is your friend here.
Of course, it doesn’t make sense to employ this kind of extreme optimization in production CSS. You’d be compromising the reliability of your code for a negligible saving. But CSSBattles will teach you more about how browsers think and what they do and don’t like.
So, Is CSSBattle encouraging bad coding habits?
I’ve heard a few people mention this as a potential downside. In fact, CSS elder statesman Eric Meyer recently raised the question in the CSSBattle.dev Spectrum feedback:
Is the reliance on exploiting parser wrinkles (particularly regarding separation whitespace) to get lower scores intentional, or a side effect?
–Eric Meyer
I don’t think so. To me, this is a way to test, experiment and ultimately come to a deeper understanding of CSS than you can by writing normal, robust production code.
You could make a good comparison japanese haiku poetry. Haiku is a format built upon hard limits – the arbitrary limitations of 3 lines and 17 syllables.
Even the world’s great haiku masters don’t expect to speak or write each day in carefully constructed haiku. However, that doesn’t mean we can’t learn important lessons in word selection, rhythm, balance, and beauty when we read (or write) haiku.
Writing good ‘CSS Battles code’ isn’t the same as writing good ‘production code’ – but it WILL teach you lessons you couldn’t get elsewhere.