Blog

May 30, 2016

Styling for a dynamic number of element

  • #programming
  • #styling
Styling for a dynamic number of element

We recently ran into a small conundrum while working to scale the height of the container using a set number of pixels in proportion with the number of elements contained (1-100)

containerHeight = elementHeight * ceiling(elementCount / elementCountPerRow)

Obviously, we can do it in Javascript:

document.querySelector('.element-container').style = `height: ${elementHeight * (elementCount/elementCountPerRow)}px`;

However, we follow the practice of keeping our CSS and JS separated.

Another option is to do the calculation in our server-side language, PHP in this case.

<div class="element-container" style="height: <?php
    echo ($elementHeight) * ($elementCount/$elementCountPerRow);
?>px;">
    ...
</div>

Although this means that we have to store our element height in PHP and we are still mixing technologies and we don’t want to do that.

In CSS3, we can do basic arithmetic using calc() but we need to use a hardcoded number so it doesn’t really help us.

The experimental feature attr() would be perfect, we could pass the element count to calc() but it won’t be viable before at least 2017 so we can forget about it for now.

So plain CSS is out of the question, what about SASS?

We can generate selectors using "#{$someVar}" so lets create a selector for all possible elementCount i.e. 1 to 100.

@for $elementCount from 1 through 100 {
    .element-container[data-count="#{$elementCount}"]{
        height: $elementHeight * ceil($elementCount/$elementCountPerRow);
    }
}

And we need to give the count to an element attribute.

<div class="element-container" data-count="<?php echo $elementCount; ?>">
    ...
</div>

The data-count attribute is not beautiful to look at but it is the least compromising solution available.

We got lucky with a small range to cover (1-100) so our outputted CSS stays under 1KB.

This seems to be as good as it gets while we wait for attr() to be the accepted solution.

Philippe