Building long HTML class attributes with arrays
November 20, 2021 · Chris Peters
Sometimes class values in our HTML attributes can go on and on. Arrays can help us do it with style.
Often, I run across code that builds a long HTML class
attribute value like
this:
<div class="banner color-<?= $color ?> bg-color-<?= $bg_color ?> text-<?= $align ?> pb-<? if ($padding_bottom) : ?><?= $padding_bottom ?><? else : ?>pb-0<? endif ?>"> | |
It goes on for days and days... | |
</div> |
This is a simplified version of the horror, and it already requires quite a bit of mental processing and horizontal scrolling to figure out what’s going on.
Add in more complex if
/elseif
/else
statements for some of the possible
class
names, and it gets even worse.
OK, I just have to put in what I really see in many codebases:
<div class="banner color-<?php echo $color; ?> bg-color-<?php echo $bg_color; ?> text-<?php echo $align; ?> pb-<?php if ($padding_bottom) : ?><?php echo $padding_bottom; ?><?php else : ?>pb-0<?php endif; ?>"> | |
It goes on for days and days... | |
</div> |
(Can you die from reading PHP code like that? Because I feel like you could die from reading PHP code like that.)
Arrays to the rescue
Fortunately, virtually all programming languages have some way of joining arrays together as strings.
PHP’s version of this is called implode
, which allows us to pass in an
array of class
names and glue them together with a space as a $separator
:
<div class="<?= implode(' ', [ | |
'banner', | |
"color-$color", | |
"bg-color-$bg_color", | |
"text-$align", | |
'pb-' . $padding_bottom ?: '0', | |
]) ?>"> | |
It's so much easier to read a list vertically. | |
</div> |
And the same trick applies for React/JSX using JavaScript’s own
Array.prototype.join
:
<div className="{[ | |
'banner', | |
`color-${color}', | |
`bg-color-${bgColor}', | |
`text-${align}`, | |
`pb-${paddingBottom ? paddingBottom : '0'}`, | |
].join(' ')}"> | |
It is so much easier to read a list vertically. | |
</div> |
Or how about Embedded Ruby?
<div class="<%= [ | |
'banner', | |
"color-#{color}", | |
"bg-color-#{bg_color}", | |
"text-#{align}", | |
"pb-#{padding_bottom || '0'}", | |
].join(' ') %>"> | |
It is so much easier to read a list vertically. | |
</div> |
Splitting out even greater complexity with the array
Because we’re now using an array to build our class
list, we can isolate any
logic that gets more complex than this before adding it to the HTML markup.
Here’s another example in PHP, where perhaps we want to add in a value to the middle of the array, but only if certain logic applies:
<?php | |
function build_banner_class(int $age) : array { | |
$banner_class = ['banner']; | |
if ($age >= 21) { | |
$banner_class[]= 'banner--boogie'; | |
} | |
$banner_class = array_merge($banner_class, [ | |
"color-$color", | |
"bg-color-$bg_color", | |
"text-$align", | |
]); | |
return $banner_class; | |
} | |
?> | |
<div class="<?= implode(' ', build_banner_class(14)) ?>"> | |
Let's watch some iCarley. | |
</div> |
I hope you also welcome the increased simplicity, even if it does add a few extra lines of code. While it may be a new pattern for some of you, I promise you that you can get used to it rather quickly.