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>
view raw poor.php hosted with ❤ by GitHub

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>
view raw implode.php hosted with ❤ by GitHub

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>
view raw join.js hosted with ❤ by GitHub

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>
view raw join.erb hosted with ❤ by GitHub

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.

About Chris Peters

With over 20 years of experience, I help plan, execute, and optimize digital experiences.

Leave a comment