I just saw that my previous article on magical kittencorns and CSS animations worked out to an 18 minute read. Which is apparently terrible for getting people to read the whole thing. Good thing I’m the one reading my own articles, huh?

Anyway, this is a really short one, which was borne out of a discussion with my mate, Wei, about use of padding in a flex formatting context. Because that’s what friends talk about in casual conversation.

But I think it is a fairly common problem which people may run into so here’s a write-up.

Scenario

If you have tried to apply padding to a flex container with an horizontal overflow behaviour of scroll, you might notice that the padding is not applied to the flex end side of your container.

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

This is because the available space allocated to flex items by the browser under such circumstances is: the width of flex container's containing block minus its margin, border and padding in the horizontal direction.

The relevant section of the specification is [CSS Flexible Box Layout Module Level 1: 9.2 Line Sizing](https://www.w3.org/TR/css-flexbox-1/#line-sizing)

Update:
Konstantin Rouda and Šime Vidas raised the point that my original explanation didn’t really explain why there is start padding but no end padding. And upon further digging, I found a long standing dispute about how overflow content should be handled while considering the constraints of Web-compat.

This is not an issue that only affects Flexbox layouts, it affects scroll containers with block and inline children differently as well. CSS2.1 was not clear about overflow, and that probably resulted in different browser vendors implementing different behaviour. For example, Webkit had (has?) different policies for block children and inline children.

From the GitHub issue [css-overflow-3] Clarify padding-bottom in overflow content, fantasai commented that:

I think historically the issue is that browsers didn’t want to trigger scrollbars for overflow: auto unless visible content was overflowing the inner border edge, so they didn’t count padding.

Things have not been resolved yet, and anyone who is interested can read through the following relevant links:

However, having items in a scrolling container with padding is a relatively common situation and there are a couple of workarounds to achieve the desired effect. Both workarounds are sort of hacks though. Here’s the markup for a basic flex container with some items in it.

<div class="flex">
  <div class="flex__item card">
    <img src="http://placekitten.com/150/150">
    <div class="card__txt">
      <h3>Sleep more</h3>
    </div>
  </div>
  <div class="flex__item card">
    <img src="http://placekitten.com/150/150">
    <div class="card__txt">
      <h3>Sleep more</h3>
    </div>
  </div>
  <!–– repeat for like 10 more cards ––>
</div>

Using border

One option is to style up the border so it looks like padding around the items in the container.

.border {
  border: 1em #4abc41 solid;
}

A potential downside to this solution is the position of the scrollbar. Depending on the operating system, this may or may not be an issue. For example, on Windows (screenshot shown below), it is fairly obvious. On Android, the scrollbar is barely noticeable.

Border solution rendered on Windows machine

I’d like to take this opportunity to talk about the CSS Scrollbars Module Level 1 specification which is currently an Editor’s Draft. It introduces 2 new CSS properties for scrollbar styling, scrollbar-color and scrollbar-width. Firefox has supported them since version 64.

More information written up in Issue № 1022 of Web Platform News.

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

Using the ::after pseudo-element

Another option is to utilise the ::after pseudo-element on the flex container. ::before and ::after are generated content, and are inserted just inside their associated element. In other words, it will be rendered as a child element inside the flex container.

.pseudo-elem {
  padding: 1em;
  
  &::after {
    content: '';
    padding: 0.5em;
  }
}

You do have to make sure that the padding on the ::after pseudo-element is half that of the padding used on the flex container, because padding is applied all around the pseudo-element. But if you go with padding-left or padding-right, then you can use the same value as the padding on the flex container.

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

2 rabbits taking a nap

Sleep more

Wrapping up

I promised this would be short. Anyway, if you want to take a look at the code and mess around with it. Or even better, add to the list of workarounds, please feel free to do so. And ping me with your solution!

See the Pen Flex container padding hack by Chen Hui Jing (@huijing) on CodePen.