<div class="info">
	<h1><p class="chip">Colored Bubbles</p> Colored Bubbles</h1>
	<p>Here's a little script to generate automatically colored contact bubbles, just like the ones in Material Design.<br>
		The colors are generated from the elements contents.</p>
	<p>Here are some bubbles for:</p>
</div>

<ul class="bubbles__list">
	<li class="bubbles__entry"><p class="chip" aria-label="Anne Sophie's user picture">Anne Sophie</p> Anne Sophie</li>
	<li class="bubbles__entry"><p class="chip" aria-label="Burt's user picture">Burt</p> Burt</li>
	<li class="bubbles__entry"><p class="chip" aria-label="Caroline's user picture">Caroline</p> Caroline</li>
	<li class="bubbles__entry"><p class="chip" aria-label="Empty user picture"></p> And he who musn't be named</li>
	<li class="bubbles__entry"><p class="chip"><img src="https://loremflickr.com/100/100/cat"></p> Works with pictures!
        </ul>
.info {
	margin-bottom: 1em;
	font-family: sans-serif;
	line-height: 1.5em;
	color: #333;
}

.bubbles {	
	&__entry {
		margin: 1em 0;
		font-family: sans-serif;
	}
}

.chip {
	--chip-size: 48px;
	--bg-color: gray;
	
	display: inline-block;
	box-sizing: border-box;
	width: var(--chip-size);
	height: var(--chip-size);
	border-radius: 50%;
	font-family: sans-serif;
	white-space: nowrap;
	font-size: 0;
	font-weight: normal;
	line-height: var(--chip-size);
	color: white;
	background: var(--bg-color);
	overflow: hidden;
	cursor: default;
	text-align: center;
	vertical-align: middle;
	
	&::first-letter {
			font-size: calc(var(--chip-size) / 2);
	}
	
	&:empty::before {
		content: "?";
		font-size: calc(var(--chip-size) / 2);
	}
	
	> img {
		width: 100%;
		height: 100%;
		object-fit: cover;
	}
}
View Compiled
class Chip {
	constructor(props) {
		this.$el = props.el;
		this.string = this.$el.innerHTML;
		this.propertyName = props.propertyName || '--bg-color';

		this.addColor();
	}

	addColor() {
		this.$el.style.setProperty(this.propertyName, this.generateColor());
	}

	generateColor() {
		let hsl = [
			this.hash(this.string),
			this.string.length > 0
			? "100%"
			: "0%",
			"42%"
		];

		return "hsl(" + hsl.join() + ")";
	}

	hash() {
		let hash = 0;

		for (let i = 0; i < this.string.length; i++) {
			hash = Math.abs(Math.sin(this.string.charCodeAt(i) + hash) * 360)
		}
		
		return hash;
	}
}

for (let $chip of document.querySelectorAll('.chip')) {
	new Chip({
		el: $chip
	});
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.