TQ
dev.com

Blog about software development

Subscribe

Generate avatars with initials in PHP

19 Aug 2022 - by 'Maurits van der Schee'

For a mobile app I'm doing some front-end development and the design includes a lot of avatars. Unfortunately we don't have any avatars of our users. Fortunately we do have their names and I've learned from Outlook and Trello that you can make great avatars with a user's initials. In this post I show how to do this using PHP.

Our goal

The target is to create the following avatar with initials "MS" for my name "Maurits van der Schee":

MS

Code:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="display:block;">
  <circle r="50" cy="50" cx="50" style="fill:#8e24aa"></circle>
  <text x="50" y="50" dominant-baseline="central" text-anchor="middle" 
    style="font-size:45px;fill:white;">MS</text>
</svg>

Note that we set "display:block" on the SVG element to avoid a spurious margin. We use a "viewBox", so that the SVG is automatically scaled. Be careful to scale the SVG by setting a CSS "width" on the container, using "height" won't work.

Convert a name to initials

The following code converts "Maurits van der Schee" to "MS":

function getCapitals(string $name): string
{
    $capitals = '';
    $words = preg_split('/[\s-]+/', $name);
    $words = [array_shift($words), array_pop($words)];
    foreach ($words as $word) {
        if (ctype_digit($word) && strlen($word) == 1) {
            $capitals .= $word;
        } else {
            $first = grapheme_substr($word, 0, 1);
            $capitals .= ctype_digit($first) ? '' : $first;
        }
    }
    return strtoupper($capitals);
}

Some test cases:

Maurits van der Schee => MS
M.E. van der Schee => MS
Maurits 2 => M2
Maurits 1234 => M
maurits test => MT
Maurits-Eduard => ME

Note that there is an exception for a single digit word.

Select a good color

We want a random color that is always the same for the same name. Therefor we use a hash function to create a unique number that we then convert to an index using a modulo operator, see:

function getColor(string $name): string
{
    // level 600, see: materialuicolors.co
    $colors = [
        '#e53935', // red
        '#d81b60', // pink
        '#8e24aa', // purple
        '#5e35b1', // deep-purple
        '#3949ab', // indigo
        '#1e88e5', // blue
        '#039be5', // light-blue
        '#00acc1', // cyan
        '#00897b', // teal
        '#43a047', // green
        '#7cb342', // light-green
        '#c0ca33', // lime
        '#fdd835', // yellow
        '#ffb300', // amber
        '#fb8c00', // orange
        '#f4511e', // deep-orange
        '#6d4c41', // brown
        '#757575', // grey
        '#546e7a', // blue-grey
    ];
    $unique = hexdec(substr(md5($name), -8));
    return $colors[$unique % count($colors)];
}

The colors are taken from the script that colors the Emoji One colored circles as published on Wikimedia.

Inline SVG or data URI?

Instead of using inline SVG generated by PHP you may also use a Base64 encoded data URI containing svg+xml. The advantage of inline SVG is that it will inherit the font of the container, while a data URI solution must specify a font to ensure consistent rendering. The data URI solution may be easier to integrate or turn into a service (as some have done).

Is PNG better than SVG?

PNG is more expensive to render and will likely result in larger file size. PNG will result in 100% consistent rendering on all platforms, while SVG may have small differences due to the different SVG rendering engines used. Since SVG is a vector format you can use a single file at all sizes, while the PNG must be rendered at specified size (in pixels).

HTML/CSS instead of SVG

We can also use HMTL+CSS instead of SVG. To do so we need to use the following PHP code:

<div class="initials-avatar large" 
  style="background: <?= getColor($name); ?>;">
    <?= getCapitals($name); ?>
</div>

And also load the related CSS code:

.initials-avatar {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    text-align: center;
    vertical-align: middle;
    border-radius: 50%;
    line-height: 1;
    background: grey;
    color: white;
}
.initials-avatar.large {
    width: 100px;
    height: 100px;
    font-size: 45px;
}

This looks like:

MS

This last solution (PHP + HTML/CSS) is my favorite.

Future work

I have submitted the ideas in this post as issues on Edward Jibson's excellent avatar repository and I will also explore the possibility of making initials avatars using HTML/CSS+Javascript as explored by Felipe Pucinelli on CodePen.

Edit: I created a CodePen too.

Links


PS: Liked this article? Please share it on Facebook, Twitter or LinkedIn.