Search code examples
cssangularprimeng

Style containers that (don't) have a certain child class


So I am building an angular application using primeng to build the ui. I am trying to restyle the p-menu component, mainly how the list items look like, problem is that I am trying to style the items that are not active, but the active class is only added to the link and not the list item. Which means that I am not able to style the list item since :has is not supported.

I have tried to style it using 2 different methods, one is to style all listitems the normal way and the ones that has an anchor that is active to style it differently. The other method is the opposite by styling everything as active and to exclude those that don't have an active anchor.

I tried to verify what was working and what not, just by adding margin:

.p-menu .p-menuitem:not(.p-menuitem .p-menuitem-link-active) {
  margin-left: 30px;
}
.p-menu .p-menuitem:has(.p-menuitem-link-active) {
  margin-left: 60px;
}

But none of them are working correctly, any ideas how to style this?

Thanks in advance!

Update 1:

This is the html that gets generated:

<p-menu _ngcontent-igv-c109="" class="ng-tns-c106-2 ng-star-inserted" ng-reflect-model="[object Object]">
  <div class="ng-trigger ng-trigger-overlayAnimation ng-tns-c106-2 ng-animate-disabled p-menu p-component ng-star-inserted" ng-reflect-ng-class="[object Object]">
    <ul class="p-menu-list p-reset ng-tns-c106-2">
      <li class="p-submenu-header ng-tns-c106-2 ng-star-inserted" ng-reflect-ng-class="[object Object]">
        <span class="ng-tns-c106-2 ng-star-inserted">Categories</span>
      </li>
      <li class="ng-tns-c106-2 p-menuitem ng-star-inserted" ng-reflect-item="[object Object]" ng-reflect-ng-class="[object Object]">
        <a role="menuitem" pripple="" class="p-menuitem-link p-ripple ng-star-inserted" ng-reflect-router-link="/manage/buildings" ng-reflect-router-link-active="p-menuitem-link-active" ng-reflect-router-link-active-options="[object Object]" ng-reflect-ng-class="[object Object]" tabindex="0" href="/manage/buildings">
          <span class="p-menuitem-text ng-star-inserted">
            Buildings
          </span>
        </a>
      </li>
      <li class="ng-tns-c106-2 p-menuitem ng-star-inserted" ng-reflect-item="[object Object]" ng-reflect-ng-class="[object Object]">
        <a role="menuitem" pripple="" class="p-menuitem-link p-ripple ng-star-inserted" ng-reflect-router-link="/manage/rooms" ng-reflect-router-link-active="p-menuitem-link-active" ng-reflect-router-link-active-options="[object Object]" ng-reflect-ng-class="[object Object]" tabindex="0" href="/manage/rooms">
          <span class="p-menuitem-text ng-star-inserted">Rooms</span
        </a>
      </li>
      <li class="ng-tns-c106-2 p-menuitem ng-star-inserted" ng-reflect-item="[object Object]" ng-reflect-ng-class="[object Object]">
        <a role="menuitem" pripple="" class="p-menuitem-link p-ripple ng-star-inserted p-menuitem-link-active" ng-reflect-router-link="/manage/devices" ng-reflect-router-link-active="p-menuitem-link-active" ng-reflect-router-link-active-options="[object Object]" ng-reflect-ng-class="[object Object]" tabindex="0" href="/manage/devices">
          <span class="p-menuitem-text ng-star-inserted">
            Devices
          </span>
        </a>
      </li>
    </ul>
  </div>
</p-menu>

I want to style the li as the following picture (coloring will be different): So I want to make all regular li to be more towards the right by using margin-left and the active one will be as normal towards the left so no margin-left is required or atleast not as much as the others.

Custom menu


Solution

  • Although CSS won't go 'back up' to let you style an ancestor, you can put a pseudo element on an element (the anchor in this case) and position that absolute and let it take on the dimensions of the li if that is positioned.

    This snippet just moves all the relevant lis 60px with margin-left then moves the active one to 30px but also puts a pseudo before element on the link which extends back a bit and colors that.

    Obviously you will want to play with the positioning to get it right depending on what the other styles are doing.

    ul {
      list-style-type: none;
    }
    
    li.p-menuitem {
      position: relative;
      height: 30px;
    }
    
    .p-menuitem-link {
      margin-left: 60px;
    }
    
    .p-menuitem-link.p-menuitem-link-active {
      margin-left: -30px;
    }
    
    .p-menuitem-link-active::before {
      content: '';
      position: absolute;
      width: 120%;
      height: 120%;
      background-color: beige;
      top: 0;
      left: -10px;
      border-radius: 30px 0 0 30px;
      z-index: -1;
    }
    <p-menu _ngcontent-igv-c109="" class="ng-tns-c106-2 ng-star-inserted" ng-reflect-model="[object Object]">
      <div class="ng-trigger ng-trigger-overlayAnimation ng-tns-c106-2 ng-animate-disabled p-menu p-component ng-star-inserted" ng-reflect-ng-class="[object Object]">
        <ul class="p-menu-list p-reset ng-tns-c106-2">
          <li class="p-submenu-header ng-tns-c106-2 ng-star-inserted" ng-reflect-ng-class="[object Object]">
            <span class="ng-tns-c106-2 ng-star-inserted">Categories</span>
          </li>
          <li class="ng-tns-c106-2 p-menuitem ng-star-inserted" ng-reflect-item="[object Object]" ng-reflect-ng-class="[object Object]">
            <a role="menuitem" pripple="" class="p-menuitem-link p-ripple ng-star-inserted" ng-reflect-router-link="/manage/buildings" ng-reflect-router-link-active="p-menuitem-link-active" ng-reflect-router-link-active-options="[object Object]" ng-reflect-ng-class="[object Object]"
              tabindex="0" href="/manage/buildings">
              <span class="p-menuitem-text ng-star-inserted">
                Buildings
              </span>
            </a>
          </li>
          <li class="ng-tns-c106-2 p-menuitem ng-star-inserted" ng-reflect-item="[object Object]" ng-reflect-ng-class="[object Object]">
            <a role="menuitem" pripple="" class="p-menuitem-link p-ripple ng-star-inserted" ng-reflect-router-link="/manage/rooms" ng-reflect-router-link-active="p-menuitem-link-active" ng-reflect-router-link-active-options="[object Object]" ng-reflect-ng-class="[object Object]"
              tabindex="0" href="/manage/rooms">
              <span class="p-menuitem-text ng-star-inserted">Rooms</span
            </a>
          </li>
          <li class="ng-tns-c106-2 p-menuitem ng-star-inserted" ng-reflect-item="[object Object]" ng-reflect-ng-class="[object Object]">
            <a role="menuitem" pripple="" class="p-menuitem-link p-ripple ng-star-inserted p-menuitem-link-active" ng-reflect-router-link="/manage/devices" ng-reflect-router-link-active="p-menuitem-link-active" ng-reflect-router-link-active-options="[object Object]" ng-reflect-ng-class="[object Object]" tabindex="0" href="/manage/devices">
              <span class="p-menuitem-text ng-star-inserted">
                Devices
              </span>
            </a>
          </li>
        </ul>
      </div>
    </p-menu>