I’m trying to recreate Google Maps’s icon (2020). The colorful background and the donut hole are easy enough: I just need some gradients and a mask.
Here’s a snippet that shows my current efforts (and a codepen, if you want to play with it):
:root {
--1-3: calc(100% / 3);
--2-3: calc(100% / 3 * 2);
--sqrt-2: 1.4142135624;
--hole-diameter: calc(100% / var(--sqrt-2) / 3);
--red: #ea4335;
--yellow: #fbbc04;
--green: #34a853;
--blue: #1a73e8;
--azure: #4285f4;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
#wrapper {
margin: 3em auto;
width: 10em;
background: linear-gradient(90deg, #c0392b, #8e44ad);
}
#icon {
--mask: radial-gradient(
circle at center,
transparent calc(var(--hole-diameter) - 1px),
#000 calc(var(--hole-diameter) + 1px)
);
border-radius: 50% 50% 50% 0;
aspect-ratio: 1 / 1;
background:
linear-gradient(
180deg,
var(--red) var(--1-3),
var(--yellow) var(--1-3) var(--2-3),
var(--green) var(--2-3)
),
linear-gradient(
180deg,
var(--blue) var(--1-3),
var(--azure) var(--1-3) var(--2-3),
var(--green) var(--2-3)
) calc(100% - 1px);
background-size: 50% 100%;
background-repeat: no-repeat;
-webkit-mask: var(--mask);
mask: var(--mask);
rotate: -45deg;
}
<div id="wrapper">
<div id="icon"></div>
</div>
However, I can’t wrap my head around its peculiar shape. Is it possible to create such a shape with CSS only?
It should be obvious that I’m not looking for an SVG-based solution. I’m doing this as a pet project, so I just need something that works in at least one browser.
2
Answers
Here’s the best I could come up with, by abusing multiple
radial-gradient
,-webkit-mask-image
,-webkit-mask-image-composite
and, unfortunately: a sibling-element for the "pointy-bit" instead of being able to extend the original#icon
, nor use an::after
element (as the::after
element will be clipped by the mask of its parent).(I suppose this could be re-organized to make the circular part at the top use
::before
and the pointy-bit use::after
and otherwise have#icon
serve only as a container and bounds for its two psedoelement children, but that’s an exercise left for the reader).This is how it looks in Chrome. I haven’t tested in any other browsers:
An approximation with one element that should work in all the browsers: