Default Avatars With User Initials
- Fallback for user avatar
- Circle with center-aligned content both vertically and horizontally using flex; and
- Inject user initials using content attribute of pseudo element :before
Background
For my projects that have restricted features, especially projects that involve displaying data, I generally have user profiles that accept a user-supplied profile picture. Usually this is used to display the logged-in user in the header or to indicate in data tables which user is associated with certain records, actions, privileges, etc. However, I generally don't structure user profile models with profile pictures as a required field. Therefore, I need a fallback option for when the profile picture hasn't been set that still conveys useful information and looks nice.
HTML
<div class="avatar-container">
<button class="avatar" type="button">
<span data-letters="AB"></span>
</button>
<button class="avatar">
<span data-letters="AB"></span>
</button>
<button class="avatar">
<span data-letters="AB"></span>
</button>
<button class="avatar">
<span data-letters="AB"></span>
</button>
</div>
Here we have a handful of button elements with the class "avatar", a child span element with a data-<label> attribute, and a value for the data attribute representing our example user's initials. Ignore the container and the multiple avatars. I added a couple variations to demonstrate different gradients and positioned them in a flexbox container to organize them neatly. In production, you'll have a single avatar per user and it will be nested in a nav or perhaps a table.
For my purposes, I'm starting with button elements for my avatars because my most common use case is a nav button that displays a dropdown with options like, "profile," "log out," and so on. If I was only using an avatar to indicate possession or relation to a record or action, such as with a data table, I would use a div instead of a button. I just need an element that respects "width" and "height" properties since the circle's size is fixed.
With the attribute "data-letters," we're storing the user's initials to be later injected as content with css. The syntax for this is "data-<lable>." I'm choosing the "letters" part. You can call it "initials," "foo," "bar," or whatever you'd like.
CSS
.avatar {
/* button */
border: none;
font-family: inherit;
cursor: pointer;
outline: inherit;
height: 4rem;
width: 4rem;
border-radius: 50%;
color: #fff;
/* center the data within */
display: flex;
align-items: center;
justify-content: center;
}
/* initials */
.avatar > span[data-letters]::before {
content: attr(data-letters);
font-size: 1.3rem;
}
/* background gradients */
.avatar:nth-child(1) {
background: linear-gradient(to right top, #4B31A1, #B32993)
}
.avatar:nth-child(2) {
background: linear-gradient(to right top, #970008, #FF6F91)
}
.avatar:nth-child(3) {
background: linear-gradient(to right top, #008B72, #54FBDD);
}
.avatar:nth-child(4) {
background-image: linear-gradient(to right top, #2E3192, #1BFFFF)
}
/* display for this pen */
html {
font-family: sans-serif;
}
.avatar-container {
display: flex;
flex-wrap: wrap;
gap: 25px;
margin-bottom: 1rem;
}
.avatar-container > * {
flex: 0 0 auto;
}
The CSS to accomplish this is relatively simple. First, I adjust a couple of properties to prevent default button styles from interfering. Next, I'm styling my ".avatar" element with fixed width and height properties as well as a "border-radius" property of 50% to accomplish the circle shape. Then, I establish by avatar as a flexbox with vertical and horizontal center alignment to position the content in the center of the shape.
To capture the initials and then inject them into view, I use the "content" property of the pseudo element ::before. In CSS, there exists a function attr() that retrieves an attribute's value. I use this function to grab the initials and then pass them to the "content" property.
Last, I add a background gradient to make the shape a little more visually interesting. I'm using the nth-child selector to apply the different gradients in this example. In practice, I would assign each gradient to its own class and conditionally inject the class dependent on a stored user preference. That way, you allow a user to choose their own default avatar.
When setting the initials to the content property, the selector "span[data-letters]::before" can be used without "[data-letters]." For example ".avatar > span::before" would also work. The "[data-letters]" component adds an additional layer of specificity to the selector where direct child spans to parent with class "avatar" will only be selected if the span contains the "data-letters" attribute.
Result
See the Pen default-avatars by Ian Waldron (@Ian-Waldron) on CodePen.
Final Thoughts
The above is a simple and easy way to give users a default option for a user avatar. Please note, the shapes are much larger than I would actually use in production. I sized them up to 4rem for presentation purposes. Something around 2rem to start and expand with screen size would be more appropriate. Enjoy.