Skip to main content
About This Component

A main dialogue box container houses all of the content and initially contains the class "inactive". We will use this container to toggle the "inactive" class via JS and set conditional properties based on the existence of this class for all items in the container via CSS. The high-level structure consists of a top bar, an avatars section which contains a grid of images and text, a CTA, and a dropdown icon/counter which we dynamically count via JS.

The CSS immediately contains some :root variables since we use these particular values in multiple locations, making them easy to globally update if needed. The dialogue box has no defined size, and naturally follows a shrink fit to its contents. This is important as we want to retain the ability to add more or less grid items as desired. A fixed dialogue box size would inhibit us from doing so.

To achieve the desired initial collapsed and stacked effect, we must build this component backwards - starting from the expanded state. Then, we use conditional targeting, such as ".dialogue-box.inactive .top-bar", for example, to apply properties on top of their default styling only when the dialogue box has the class of "inactive".

The avatars section is set to display grid so we can add or remove items as desired. It is a bit trickier to go the grid route than display flex, as we need to overlap the first three items in the collapsed state, but we must do grid so the items remain responsive on smaller sizes and allow for additions/subtractions.

To hide all grid items after the first four in the collapsed state, we can select them by using ".avatars ul li:nth-child(n + 5)" and set a max-height: 0, opacity: 0, and pointer-events: none. Additionally, since we will be using an elastic animation ease, we will apply a transform: scaleY(0) to all items that will not be shown in the collapsed state. This is a little trick that will allow the contents of the object to stretch and shrink with the easing, whereas if we just used height, the items would just get masked vertically until they disappeared. There is nothing inherently wrong with transitioning only heights, but scaling the items on the Y axis gives us a much more complete and satisfying animation.

To stack the four avatar items that still show on collapse, we use the following: .dialogue-box.inactive .avatars ul li:nth-child(2) {transform: translateX(calc(var(--avatar-image-size) * -0.25));}

We then apply the same approaches to the remaining two avatars, incrementing by .25 of a shift each time (-0.25, -0.5, -.75, etc.)

A media query of 650px reduces the amount of grid items shown, both initially to 3 items and expanded to 6 items max. Grid items can still be added, but mobile will only show up to six total. Again, we achieve this using "li:nth-child(n + 4):nth-child(-n + 6)" to select items 4-6, then setting display: none to any items past 6 "li:nth-child(n + 7)".

Lastly, a click event listener in JavaScript listens for clicks on the dropdown selector, the collapsed state avatars, and the X button in the expanded state. When clicked, JavaScript toggles "inactive" classes on the main dialogue box container and the dropdown selector. Since we have all of our properties set up in CSS contingent on whether these "inactive" classes exist, we do not need complex JS or additional animation libraries - just thoughtful CSS, a few event listeners / if statements, and a couple of class toggles.

Team Members
  • Avatar for Shawn
    Shawn
  • Avatar for Zoe
    Zoe
  • Avatar for Grant
    Grant
  • Avatar for Maya
    Maya
  • Avatar for Kate
    Kate
  • Avatar for Owen
    Owen
  • Avatar for Nora
    Nora
  • Avatar for Eli
    Eli