csspopover-api

How to apply style to a popover parent element when popover is opened


was uing html popover API and nested css declaration with anchor positioning.

my requirement is when popover is open; how apply some style to the element which have popover attribute, denote as popover parent element

currently when we hover on this parent element, it rotate and I want that when popover is open, parent element should be keep on same position and also we should not be able to interact with that, currently even backdrop is there, we can still hover on it.

tried ::popover-open but unable to underatnd where to write what in nested css pattern

here is the sample code

.container__setting {
  container: setting/inline-size;
  .setting__trigger {
    anchor-name: --setting;
    position: fixed;
    top: 82px;
    right: 32px;
    width: max-content;
    height: auto;
    border-radius: 10%;
    background-color: unset;
    border: solid;
    cursor: pointer;
    display: flex;
    font-size: 4rem;
    transition: transform 330ms ease-in-out;
    &::after {
      content: '🕸';
    }
    
    &:hover {
      transform: scale(1.05) rotate(45deg);
    }
    
  }

  .setting__panel {
    position: fixed;
    position-anchor: --setting;
    top: calc(anchor(bottom) + 15px);
    right: calc(anchor(left) + 10px);
    justify-self: anchor-center;
    width: 20rem;
    height: 20rem;
    background-color: hwb(20 10% 40%);
    border-radius: 4px;
    padding: 10px;
    transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
    color: color(xyz, 0, 0, 1);
    &::backdrop {
      background-color: hsl(0 0% 10% / 0.5);
      backdrop-filter: blur(2px);
    }


    .control__group {
      display: grid;
      grid-auto-flow: row;
      gap: 0.5rem;

    /* Control Buttons */
    & button, & select {
      background-color: color(xyz 0.05 0.05 0.09);
      color: white;
      border: none;
      padding: 14px 24px;
      cursor: pointer;
      transition: var(--transition);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 10px;
      font-weight: 600;
      font-size: 1rem;
      letter-spacing: 0.01em;
      
      &:hover:not(.close) {
        background-color:  color(xyz 0.02 0.01 0.02);
        transform: translateY(-3px);
      }
      &.close {
        width: 2rem;
        height: 3rem;
        outline: 1px dashed green;
        justify-self: end;
        &:hover {
          font-size: 30px;
        }
      }
    }
  }
   & [popover] {
    position: fixed;
    inset: unset;
    width: fit-content;
    height: fit-content;
    right: 0;
    bottom: 0;
    margin: auto;
    overflow: auto;
    color: CanvasText;
    background-color: Canvas;
    padding: 1rem;
    border: solid;
    border-radius: 1rem;
    opacity: 0;
    visibility: hidden;
    transition: translate 0.7s ease-out,
      display 0.7s ease-out allow-discrete,
      overlay 0.7s ease-out allow-discrete,
      height 0.5s ease-in-out;
    translate: 0 -2rem;


    &:popover-open {
      opacity: 1;
      visibility: visible;
      translate: 0 0;
      right: 40px;
      bottom: 0;
      translate: 0 0;
      height: 40px;
      @starting-style {
        opacity: 0;
        visibility: hidden;
      }
    }
  }


}
<div class="container__setting">
  <button class="setting__trigger" popovertarget="options" popovertargetaction="show"></button>
  <div class="setting__panel" id="options" popover="hint">
    <div class="control__group">
      <button id="close" class="close" popovertarget="options" popovertargetaction="hide">X</button>
      <button id="new" class="add">Add New </button>
      <button id="shuffle" class="shuffle"> Shuffle </button>
    </div>
  </div>
</div>

update

tried as per suggestion, and it worked but writing inside element's nested block does not work; below is working example (yes a syntax is also bit different).

    .container__setting {
      .setting_trigger {
        // some css properties
    
        // writing inside  does not work
      }
    
      // writing outside but inside parent selector works
      &:has([popover]:popover-open) .setting__trigger {
        background-color: blue;
        transform: scale(1.05) rotate(45deg);
      }
    }

aleternative nested syntax also works as below

.container__setting {
  &:has(:popover-open) {
     .setting__trigger {
        background-color: green;
        transform: scale(1.05) rotate(45deg);
      }
  }
}

Solution

  • You can use :has pseudo-class to show keep the transform on the button when .container__setting has a child with the :popover-open pseudo-class:

    &:has(:popover-open) .setting__trigger, .setting__trigger:hover {
      transform: scale(1.05) rotate(45deg);
    }
    

    .container__setting {
      container: setting/inline-size;
    
      .setting__trigger {
        anchor-name: --setting;
        position: fixed;
        top: 82px;
        right: 32px;
        width: max-content;
        height: auto;
        border-radius: 10%;
        background-color: unset;
        border: solid;
        cursor: pointer;
        display: flex;
        font-size: 4rem;
        transition: transform 330ms ease-in-out;
    
        &::after {
          content: '🕸';
        }
      }
      
      &:has(:popover-open) .setting__trigger, .setting__trigger:hover {
        transform: scale(1.05) rotate(45deg);
      }
    
      .setting__panel {
        position: fixed;
        position-anchor: --setting;
        top: calc(anchor(bottom) + 15px);
        right: calc(anchor(left) + 10px);
        justify-self: anchor-center;
        width: 20rem;
        height: 20rem;
        background-color: hwb(20 10% 40%);
        border-radius: 4px;
        padding: 10px;
        transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
        color: color(xyz, 0, 0, 1);
    
        &::backdrop {
          background-color: hsl(0 0% 10% / 0.5);
          backdrop-filter: blur(2px);
        }
    
    
        .control__group {
          display: grid;
          grid-auto-flow: row;
          gap: 0.5rem;
    
          /* Control Buttons */
          & button,
          & select {
            background-color: color(xyz 0.05 0.05 0.09);
            color: white;
            border: none;
            padding: 14px 24px;
            cursor: pointer;
            transition: var(--transition);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 10px;
            font-weight: 600;
            font-size: 1rem;
            letter-spacing: 0.01em;
    
            &:hover:not(.close) {
              background-color: color(xyz 0.02 0.01 0.02);
              transform: translateY(-3px);
            }
    
            &.close {
              width: 2rem;
              height: 3rem;
              outline: 1px dashed green;
              justify-self: end;
    
              &:hover {
                font-size: 30px;
              }
            }
          }
        }
    
        & [popover] {
          position: fixed;
          inset: unset;
          width: fit-content;
          height: fit-content;
          right: 0;
          bottom: 0;
          margin: auto;
          overflow: auto;
          color: CanvasText;
          background-color: Canvas;
          padding: 1rem;
          border: solid;
          border-radius: 1rem;
          opacity: 0;
          visibility: hidden;
          transition: translate 0.7s ease-out,
            display 0.7s ease-out allow-discrete,
            overlay 0.7s ease-out allow-discrete,
            height 0.5s ease-in-out;
          translate: 0 -2rem;
    
    
          &:popover-open {
            opacity: 1;
            visibility: visible;
            translate: 0 0;
            right: 40px;
            bottom: 0;
            translate: 0 0;
            height: 40px;
    
            @starting-style {
              opacity: 0;
              visibility: hidden;
            }
          }
        }
    
    
      }
    <div class="container__setting">
      <button class="setting__trigger" popovertarget="options" popovertargetaction="show"></button>
      <div class="setting__panel" id="options" popover="hint">
        <div class="control__group">
          <button id="close" class="close" popovertarget="options" popovertargetaction="hide">X</button>
          <button id="new" class="add">Add New </button>
          <button id="shuffle" class="shuffle"> Shuffle </button>
        </div>
      </div>
    </div>

    Another option is to place the .setting__panel element in the HTML before the .setting__trigger and use a sibling combinator (+ or ~) to affect the button when the popover is open:

    .setting__panel:popover-open+.setting__trigger,
    .setting__trigger:hover {
      transform: scale(1.05) rotate(45deg);
    }
    

    .container__setting {
      container: setting/inline-size;
    
      .setting__trigger {
        anchor-name: --setting;
        position: fixed;
        top: 82px;
        right: 32px;
        width: max-content;
        height: auto;
        border-radius: 10%;
        background-color: unset;
        border: solid;
        cursor: pointer;
        display: flex;
        font-size: 4rem;
        transition: transform 330ms ease-in-out;
    
        &::after {
          content: '🕸';
        }
      }
      
      .setting__panel:popover-open + .setting__trigger, .setting__trigger:hover {
        transform: scale(1.05) rotate(45deg);
      }
    
      .setting__panel {
        position: fixed;
        position-anchor: --setting;
        top: calc(anchor(bottom) + 15px);
        right: calc(anchor(left) + 10px);
        justify-self: anchor-center;
        width: 20rem;
        height: 20rem;
        background-color: hwb(20 10% 40%);
        border-radius: 4px;
        padding: 10px;
        transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
        color: color(xyz, 0, 0, 1);
    
        &::backdrop {
          background-color: hsl(0 0% 10% / 0.5);
          backdrop-filter: blur(2px);
        }
    
    
        .control__group {
          display: grid;
          grid-auto-flow: row;
          gap: 0.5rem;
    
          /* Control Buttons */
          & button,
          & select {
            background-color: color(xyz 0.05 0.05 0.09);
            color: white;
            border: none;
            padding: 14px 24px;
            cursor: pointer;
            transition: var(--transition);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 10px;
            font-weight: 600;
            font-size: 1rem;
            letter-spacing: 0.01em;
    
            &:hover:not(.close) {
              background-color: color(xyz 0.02 0.01 0.02);
              transform: translateY(-3px);
            }
    
            &.close {
              width: 2rem;
              height: 3rem;
              outline: 1px dashed green;
              justify-self: end;
    
              &:hover {
                font-size: 30px;
              }
            }
          }
        }
    
        & [popover] {
          position: fixed;
          inset: unset;
          width: fit-content;
          height: fit-content;
          right: 0;
          bottom: 0;
          margin: auto;
          overflow: auto;
          color: CanvasText;
          background-color: Canvas;
          padding: 1rem;
          border: solid;
          border-radius: 1rem;
          opacity: 0;
          visibility: hidden;
          transition: translate 0.7s ease-out,
            display 0.7s ease-out allow-discrete,
            overlay 0.7s ease-out allow-discrete,
            height 0.5s ease-in-out;
          translate: 0 -2rem;
    
    
          &:popover-open {
            opacity: 1;
            visibility: visible;
            translate: 0 0;
            right: 40px;
            bottom: 0;
            translate: 0 0;
            height: 40px;
    
            @starting-style {
              opacity: 0;
              visibility: hidden;
            }
          }
        }
    
    
      }
    <div class="container__setting">
      <div class="setting__panel" id="options" popover="hint">
        <div class="control__group">
          <button id="close" class="close" popovertarget="options" popovertargetaction="hide">X</button>
          <button id="new" class="add">Add New </button>
          <button id="shuffle" class="shuffle"> Shuffle </button>
        </div>
      </div>
      
      <button class="setting__trigger" popovertarget="options" popovertargetaction="show"></button>
    </div>