CSS Multiple Adjacent Siblings

Ever need to style an element, but only if another sibling element was present?

I hit just that scenario this morning. I’m working on a site that has a landing page for four different sections of the website. For the most part the layout of the landing pages are the same, except one or two that does not contain an area for bugs1. At the large screen views, I want the .bugs container to be the first of three columns, followed by .col1 which usually contains events, and then .col2 which usually contains news.

At the default, small screen view these containers all stack.

Mobile stacked containers

By the time we hit a portrait tablet screen size, .col1 and .col2 are side by side with the .bugs container above them at full width.

Tablet stacked containers with two columns

To achieve this I am simply adding the following to my CSS at this media query

.col1, .col2 { width:50%; }

Please note, I’m not getting into detail on how I have these containers oriented horizontally. The easiest is to add a float parameter to each container. However, I tend to use a display:inline-block approach, which I feel has more versatility.

By the time we are hitting our larger screens and landscape tablet sizes, all three containers are side by side as three columns.

Large screen view with three columns

Currently my CSS looks like this for these three containers:

.bugs { width:20%; }
.col1,
.col2 { width:40%; }

This works out quite well as a good reorientation of the layout for these containers. As I said though, I have a couple pages that don’t have the .bugs containers and otherwise have the same skeletal markup. In those cases, I want to keep the widths on .col1 and .col2 at 50%. At the same time I don’t want to modify my markup on these pages if I can accomplish this with just CSS, which I can.

This is where CSS’s adjacent sibling selector come in. Essentially, this is a way to style an element, but only if it is immediately after another element. CSS-Tricks has a great rundown explaining the different child and sibling selectors available. A good way to think about the adjacent sibling selector is with an if statement. So, if .element-a is followed by .element-b then style .element-b like this.

In the situation I’m working with here is how I approached styling .col1 and .col2 if the .bugs container was present:

.bugs { width:20%; }
.bugs + .col1,
.bugs + .col1 + .col2 { width:40%; }

This is in my media query targeting screens larger than 1000px wide. This changes the widths for .col1 and .col2, but only if the .bugs container is present and proceeding them. Otherwise .col1 and .col2 retain the width:50%; from the previous media query. Also, notice in line three that we have multiple adjacent sibling selectors for one element. Without this then .col2 would still have the width:50%. Nor could we use .bugs + .col2 because those elements have .col1 between them in the markup, which negates the adjacent sibling selector.

I was pleasantly surprised to find that it was possible to have multiple adjacent sibling selectors. What makes it more useful is after a quick jump in BrowserStack, I found that the multiple adjacent sibling selectors work as far back as IE7.

  1. That is miscellaneous links and call to action buttons. 🢕