External Publication
Visit Post

Close thy enemy

Donnie D'Amato January 9, 2023
Source
You’ve seen it before, an ‘x’ at the corner of a surface which will allow the user to exit that surface. In design, it seems simple to just place the button at the top corner. To engineer this, we have a few options: Absolute Position The first option most folks might consider is something like the following: Many design system component libraries use this approach: Ant Design System Base Web (Uber) Carbon Design System (IBM) Chakra UI Github Primer Reach UI Stacks (StackOverflow) The problem with this approach is the way that works. When applying to an element, it takes that element out of the normal flow of the document. This means that other elements cannot interact with this element. In some configurations for the above components, the content (usually the title) could appear visually layered below the close button. Even if you think you control the content, assume that you don’t. User preferences can influence the content display, either by size, translation, or otherwise. Be prepared for the content to vary. Some implementations solve this for by providing enough padding to the content area so the button never collides. However, this often results in an imbalance of padding and may not be desirable from design. Flex header Another method is to add the button as a flex child to a header of the surface. Here’s a list of components across design systems using this approach: Atlassian Design Microsoft Fluent Twilio Paste Shopify Polaris Shoelace UI While this avoids a collision between the button and content, it also requires that the header exist which will be at least the height of the close button. In cases where additional header content doesn’t exist this displays a large forehead before the content. So if the surface doesn’t have a title, the amount of space might not be desirable by design. Certainly, if design is attempting to curate the title, this might have some control. However, incorrect alignment could also result in the close button centering within the header instead of pinning to the corner. Unique alternatives There are some other approaches. Salesforce Lightning includes the button outside the modal which might not work for other surfaces. Their alert component uses the technique as an example which will have similar problems as described above. Adobe Spectrum avoids the ‘x’ button entirely and provides an explicit action to close the surface. However, their alert component suffers from problems using the icon accessory in relation to the title in this similar layout. The “buoyant” approach Let’s be clear about some requirements. If design is expecting a close button to appear at the top corner: Padding around the surface should be visually consistent. The close button should never move from the corner. The content in the surface should not collide with the close button. These requirements are meant for surfaces that are text heavy. A surface which has a full-bleed media (eg., image or video) which spans the width of the surface will have other problems. The normal treatment would probably work well in this case and then ensuring that the button has sufficient contrast against the media it appears above. We can leverage two features of CSS to get an intended result. Recent relative ancestor In order to get an element to be positioned relative to another, we need to create a relationship. In the case of this relation doesn’t need to be between a direct parent and child. It can be any ancestor. This means we can have a distant child be positioned to ancestor located up the tree. This is no different from the methods we’ve critized above except that the element is a child of another element; our secret sauce… Floats! The way we get text to wrap around elements is by using the property. We’ll float the button toward the right, so that content moves around it. While we’d like to use CSS Logical Properties for the float, they aren’t well supported. You’ll probably need to adjust the type of float based on the . Then our HTML should be setup in the following manner: You’ll need a bunch of other styles to finesse the size of the floating element and button in relation to the content. The final result should look something like this: See the Pen buoyant button by Donnie D’Amato (@fauxserious) on CodePen. Let me explain what’s going on here. In the demo above, the blue box represents the element dimensions. Note that because we’re using for the element child, it’s not visually inside the but instead positioned relative to the surface. We set the dimensions of the so that the content won’t collide with the dimensions of the and instead wraps around it. You can remove the attribute from the element to see the final result without the blue box. I’m using a custom element so that it is easy to edit the content without accidentally altering the markup meant for the buoyant button. Try removing the title, editing the content, or resizing the window. The content should never collide with the button and always sit at the top corner. #make-floats-great-again

Discussion in the ATmosphere

Loading comments...