When using customer.io, interface elements will layer on top of or behind other elements. If you click "delete", a modal might take over the entire screen. If you interact with a select input, a dropdown appears. Follow these guidelines to determine the elevation of elements in our interface.
We can make Customer.io feel more natural. This happens in the real world! We see this everywhere with light interacting with objects and casting shadows. We can mimic nature by establishing a main "light source" (👋 sun) for the interface. Then we can define how the resulting shadows should appear.
We can provide contrast and focus. This can be done without using shadows. A lighter fill on top of a dark fill can create a sense of depth by appearing raised (the inverse can appear inset). A card in our interface should garner more attention than it's background. On a white background, that white card would get lost in the background.
We can indicate interactivity. A common interface pattern is making a button appear raised from the surface. This is what we're used to in the real world. Buttons are something we "press." We can mimic that feeling by making it raised by default and then inset when it's being pressed. Inset text inputs are also common and even the default in most browsers. This inset appearance communicates you can type in the box.
We can highlight importance. Raising, or lowering, elements can help communicate their importance. Elements on the same surface have a similar hierarchy. When a global error occurs, that alert should be prominent. We can put a shadow behind to give it the appearance of being on top of the interface. This is often combined with reducing the opacity of the rest of the screen to provide more focus (e.g. modals).
We can show a sense of control. If you take a look at a MacOS toolbar (e.g. Finder), you'll find a shadow being cast by the header on the content underneath. A common interface pattern is indicate control by having a layer on top of the content. That top layer has navigation or actions that affect the layers underneath it.
There are two primary sources of light in our environment: direct and ambient.
Direct light comes for a single source, such as the sun or a ceiling light. This creates a larger, softer shadow with a large blur radius and large offset. For Customer.io, our direct source of light comes from the top left. This aligns with the app frame using both the top and left sides of the window.
Ambient light appears from all angles. This creates a smaller, dark shadow with a small blur radius and small offset. This shadow disappears as an object moves further from the surface.
We use subtle shadows to represent direct and ambient light. Our goal is to provide clarity between elements, not create distraction.
Each element in the interface has a level of elevation. This starts with the background of the interface and building on top of it.
Our interface has raised elements like buttons, dropdowns, or modals. These elements appear at varying degrees of elevation. A button will be one level above the surface it's on. A dropdown will be a level above the entire interface. A modal will be multiple levels above the interface.
Our interface has inset elements like text inputs, search inputs, or a button when it's being pressed. These elements all appear one level below the surface it's on.
Some elements, like a toggle, have a combination of raised and inset elements. The toggle's background is inset one level below the surface. The toggle's button is raised one level above the surface. This combination communicates that I can move the toggle's button within its background.
When a user interacts with an element, the elevation level may change. This helps communicate functionality and provide appropriate feedback to the user.
Take a button in our interface. By default its appears raised to communicate it can be pressed. Then, when it's being pressed, it appears inset to the surface.
Another example of changing elevation is using our drag n' drop functionality. When you click and drag an element, it appears above the surface. This communicates you've picked up the element and are holding it above the other objects. Now the dragged element avoids interfering or "hitting" other objects.
Shadows help communicate the elevation of an object relative to other layers. They also help indicate the edges of an object's surface.
When using shadows:
- Use a positive x-offset and y-offset value for shadows because our light source is in the top left.
- Don't use shadows for style because it will inherently convey a sense of elevation.
The color or opacity of a surface can indicate its elevation. When an object is darker than background, it appears inset. When it's lighter than background, it appears raised. White cards on the gray-100 app background have this effect.
Overlays indicate overlap. We use overlays with modals to further communicate the modal is on top of the interface. On their own, overlays don't communicate the elevation of the objects on top. The object on top still needs a shadow to communicate its increased elevation (and importance!).
Our interface has two types of elevation. There is elevation relative to the interface and elevation relative to the surface.
For objects relative to the interface, there are four different elevation levels. The app background is the bottom most layer. The app frame and cards are built on a layer above that. The next level up includes objects that need to appear above both those layers. If a tooltip was triggered on the app background or within a card, it should appear above both layers. The top most layer includes modals and the dragging state of items.
For objects, relative to the surface, they appear above or below the layer they're on. For example, a button could be on the app background, a content card, a tooltip, or a modal. It should appear on top of whatever layer it's on. The same applies for an input or object that should appear inset the layer it's on.