Playing with Multiple Siblings

programming css selectors

Posted: 2023-02-06

Today I dabbled a bit more with CSS to fix an issue which hindered the smooth scrolling with the sticky navbar on this site. The navbar works by changing the display property of the navbar when the user scrolls to position: fixed;. Elements with this display property are taken out of the website flow and consecutive elements are hence moved up to fill the empty space. The change is done through a JS-script which adds the 'sticky' class to the navbar.

.sticky + main {
    padding-top: 7rem;

I had the above adhoc solution to this which I probably found on Stackoverflow but had never taken the time to properly understand. The solution uses the adjacent sibling combinator (+) to add a padding-top to the subsequent element (in this case main) when the 'sticky' class is added to the above element (the navbar). This solution worked in most cases but is reliant on the first element after the navbar being a main element.

However, this is not always the case. The ([alert system] used by the site introduces a <label> element between the navbar and the contents of the page which renders the above solution useless. After quite a bit of tinkering with changing the properties of the alerts and adding the padding to the labels through .sticky + label I decided to try and extend the selector to the below solution:

.sticky + main,
.sticky + label + main { /* <-- multiple siblings */
    padding-top: 7rem;

This selector is very specific in only targeting the <main> element if it has a <label> element as well as an element with the 'sticky' class preceding it; in that specific order. To cover the case where no alert has yet to be shown I kept the old selector giving it the same styling. Now we all can enjoy a smoother experience.