Skip to main content

Add Author Placeholder in Docusaurus

Add anavatar placeholder like this author.

Create a function getInitial()

Create and export this helper function to extract first letter.

src/utils/index.ts
export function getInitial(fullName: string): string {
const words = fullName.trim().split(/\s+/);

if (words.length === 0) return '';

const firstInitial = words[0][0].toUpperCase();
const lastInitial = words.length > 1 ? words[words.length - 1][0].toUpperCase() : '';

return firstInitial + lastInitial;
}

Swizzle a component

We have to swizzle Blog/Components/Author to get a copy of @theme.

pnpm run swizzle @docusaurus/theme-classic Blog/Components/Author --eject

Ternary conditional rendering

This section has 2 parts. First, convert a short-circuit conditional rendering into a ternary operator conditional rendering at imageUrl with a return of null.

src/theme/Blog/Components/Author/index.tsx
// Old
{
imageURL && (
<MaybeLink href={link} className="avatar__photo-link">
<img className={clsx('avatar__photo', styles.authorImage)} src={imageURL} alt={name} />
</MaybeLink>
);
}

// New
{
imageURL ? (
<MaybeLink href={link} className="avatar__photo-link">
<img className={clsx('avatar__photo', styles.authorImage)} src={imageURL} alt={name} />
</MaybeLink>
) : null;
}

Secondly, we will replace null with this code.

src/theme/Blog/Components/Author/index.tsx
<MaybeLink href={link}>
<div className={clsx(styles.authorImage)}>
<div className={clsx(styles.avatarPlaceholder)}>
<span className={clsx(styles.avatarText, styles.authorName)}>{getInitial(author.name)}</span>
</div>
</div>
</MaybeLink>
warning

Don't forget to import getInitial() from utils.

import { getInitial } from '@site/src/utils';
View full code here.
src/theme/Blog/Components/Author/index.tsx
{
imageURL ? (
<MaybeLink href={link} className="avatar__photo-link">
<img className={clsx('avatar__photo', styles.authorImage)} src={imageURL} alt={name} />
</MaybeLink>
) : (
<MaybeLink href={link}>
<div className={clsx(styles.authorImage)}>
<div className={clsx(styles.avatarPlaceholder)}>
<span className={clsx(styles.avatarText, styles.authorName)}>{getInitial(author.name)}</span>
</div>
</div>
</MaybeLink>
);
}

New CSS class

We have to add a new CSS classes. The first one is in custom.css and the others in styles.module.css.

src/css/custom.css
:root {
--ifm-avatar-placeholder-background: var(--ifm-color-primary);
}
src/theme/Blog/Components/Author/styles.module.css
.avatarPlaceholder {
aspect-ratio: 1;
background: var(--ifm-avatar-placeholder-background);
border-radius: 3.40282e38px;
justify-content: center;
align-items: center;
width: var(--ifm-avatar-photo-size);
display: flex;
overflow: hidden;
}

.avatarText {
color: var(--ifm-font-color-base-inverse); /* OR var(--ifm-font-color-base) if you want light-theme color*/
font-weight: 700;
}

We don't have to create styles.authorImage nor styles.authorName because they will interit style from Docusaurus theme classic.


  • --ifm-avatar-placeholder-background is a background of avatar placeholder. The default is your main theme color.
  • --ifm-avatar-photo-size is width and height of avatar placeholder and is passed by .authorImage classname.
  • font-size value is passed by .authorName classname.
  • --ifm-font-color-base and --ifm-font-color-base-inverse contain a text color for light and dark mode.