Can anyone help me understand what this css is doing?

I am looking at this codepen of a responsive hamburger menu to try to understand how it’s implemented. I’ve been messing around and breaking stuff to try to see how everything works. Most of the stuff I could figure out, for example the general sibling combinator selector ~ was new to me. It’s pretty neat how you can use this in combination with the :checked pseudo-class selector to achieve a javascript-like effect.

But I came across something I just can’t figure out and that is this bit of css here:

.header .menu-btn:checked ~ .menu-icon:not(.steps) .navicon:before,
.header .menu-btn:checked ~ .menu-icon:not(.steps) .navicon:after {
  top: 0;
}

the steps class is never given to any elements in the html. When I search for a built in steps class (like “sr-only”) I can’t find anything about it on MDN or elsewhere.

If I remove this bit of css it breaks the “X” on the hamburger menu, turning it into more of a sideways V. I can see that it is setting the top margin to 0 to make the X display properly but I don’t understand how or what the not(.steps) bit is doing. I even tried inspecting the page element to see if somewhere something was being assigned this “steps” class but I can’t find anything. Does anyone know what’s happening here?

It looks like SASS, SCSS or some other css framework.

But if you check the settings on the CSS there are no external libraries or preprocessors.

Parentheses are not valid operators in CSS selectors.

Well, turns out if I remove only the :not(.steps) part it behaves the same. This must be some leftover unused code.

check out css pseudo-classes

Pseudo selectors give very fined grained control over selections in an abstract way.

The parentheses are part of the not pseudo-class.

Let’s try to break it down:

.header .menu-btn:checked ~ .menu-icon:not(.steps) .navicon:after {
  top: 0;
}

The comma splits this into two elements that are being selected, and applying “top: 0” to both of them.

“top: 0” positions the element at the top of its container.

As far as the selectors:

  1. Inside .header
  2. Inside (that thing with the general sibling combinator)*
  3. both before .navicon AND after 'navicon
  • #2 refers to the element that is after .menu-btn:checked, that is of the class .menu-icon but is NOT of the class .steps

I don’t have enough information to say how it causes the effect you describe, but top: 0 changes the position of whatever is being selected to the top of the container.

One thing you might do is change the color of the thing that’s being moved around, and then when you break it, you see where it goes.

Hey thanks for the reply and the breakdown. The issue wasn’t that I didn’t know what the selector was targeting but rather that the .steps class was never used in the html (you can see the codepen in the OP, there’s only 10 or so lines of html). Since .menu-icon:not(.steps) is selecting all elements with class menu-icon that also does not have the class steps, and there are no elements with the steps class, it’s the same as just using .menu-icon

And correct me if I’m wrong but I think the selectors work like this:

  1. Inside header
  2. Look at the element with class .menu-btn when it is checked
  3. Inside elements that appear sequentially after said checked element that also have the class .menu-icon and do not have class steps and also share the same parent element as the checked element. Long way of saying “is a sibling of and appears after in the html”.
  4. Inside elements with class navicon, look at the pseudo :after element