7

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.

11
  • To enhance the shape, you can experiment with additional CSS properties like border-radius, transform, and box-shadow to fine-tune the curves and shadows. keep in mind that css has limitation i hope this can be helpful Commented Jun 23, 2023 at 0:10
  • 1
    @ELMEHDIACHAHED I'm afraid that is not useful at all. If I could find such a combination I wouldn't have to ask. Commented Jun 23, 2023 at 0:14
  • 2
    @InSync In that case you should edit the title of your question to be explicit, e.g. "How can I recreate the 2020 Google Maps logo using only CSS box properties and built-in functions without any SVG?" - because otherwise everyone's going to say "use background-image: url("data:{inline SVG logo}");). Commented Jun 23, 2023 at 1:16
  • Honestly I prefer your sharp-corner version over Google Maps' official logo :) Commented Jun 23, 2023 at 1:18
  • That does look nice on its own might, indeed :) Edited the title to clarify the problem. Commented Jun 23, 2023 at 1:21

2 Answers 2

3

An approximation with one element that should work in all the browsers:

.logo {
  width: 200px; /* control the size */
  aspect-ratio: .7;
  background:
   linear-gradient(130deg,#0000 53%,#34a853 53.5%),
   conic-gradient(from 40deg at 36% 26%, #4285f4 25%,#fbbc04 0 50%,#ea4335 0 75%, #1a73e8 0);
  -webkit-mask:
    radial-gradient(#000 69%,#0000 71%) 
     bottom/10% 9% no-repeat,
    radial-gradient(92% 173% at 100% 116%,#0000 98%,#000) 
     100% 97%/50% 18% no-repeat,
    radial-gradient(92% 173% at 0%   116%,#0000 98%,#000) 
     0%   97%/50% 18% no-repeat,
    conic-gradient(from -35deg at 50% 90%,#000 70deg,#0000 0)
     bottom/100% 43% no-repeat,
    radial-gradient(#0000 27%,#000 28% 70%,#0000 71%)
     top   /100% 70% no-repeat;
  
  display: inline-block;
}

html {
  min-height: 100%;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px);
  text-align: center;
}
<div class="logo"></div>

<img src="https://upload.wikimedia.org/wikipedia/commons/a/aa/Google_Maps_icon_(2020).svg" width="200">

Sign up to request clarification or add additional context in comments.

1 Comment

Looks a bit ruggy. Could you smooth it out?
1
+50

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:

enter image description here


:root {
    --1-3: calc(30%);
  --2-3: calc(70%);
    --sqrt-2: 1.41421356237;
    --inner-radius: calc(18.4%);

    --red: #ea4335;
    --yellow: #fbbc04;
    --green: #34a853;
    --blue: #1a73e8;
    --azure: #4285f4;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
}

#wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2em;
    margin: 1em;
}

#wrapper > div {
    border-radius: 1em;
    background: linear-gradient(90deg, #c0392b, #8e44ad);
  overflow: hidden;
}
#wrapper > div > h2 {
  font-family: sans-serif;
    text-align: center;
  background-color: white;
  border-radius: 0.25em;
  width: 90%;
  margin-left: auto;
  margin-right: auto;
}

#image > img {
  transform-origin: 50% 35%;
  /*transform: rotate(50deg);*/
}

#icon {
    aspect-ratio: 1 / 1;
  background-image:
        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)
        );
    
    background-position-x: 0, calc(100% - 1px);
    background-position-y: 0, 0;
    
    background-size: 50% 100%;
    background-repeat: no-repeat;

    -webkit-mask-image:
    /* The radius of the circle at 100% is actually the corners of the bounding rect, not the perpendicular top+bottom/side edges, hence the weird numbers. */
    radial-gradient(
      circle at center,
      transparent 28.2%,
      black       calc(28.2% + 1px),
      black       70%,
      transparent calc(70.0% + 1px)
    );
    
    rotate: -50deg;
  
  z-index: 10;
}

#tip {
  aspect-ratio: 26 / 25;
  width: 100%;
  background-color: #47A756;
  margin-top: -14.2%; /* this is relative to the #tip element's *width* btw. */
  z-index: 5;
  background-image:
    linear-gradient(
      130deg,
      var(--yellow) 0% 25.5%,
      var(--green) 25.5%
    );
  
  background-size: cover;
  background-repeat: no-repeat;

  -webkit-mask-repeat: no-repeat;
  -webkit-mask-image:
    radial-gradient( ellipse 127.3% 100% at -85.62% 60.5%, transparent 0%, transparent 100%, black 100% ),
    radial-gradient( ellipse 127.3% 100% at 185.62% 60.5%, transparent 0%, transparent 100%, black 100% ),
    linear-gradient( to bottom, black 55%, transparent 50% ),
    radial-gradient( ellipse 8.4% 8.8% at 50% 55%, black 100%, transparent 100% );

/* https://tympanus.net/codrops/css_reference/mask-composite/ */
  -webkit-mask-composite:
    source-in,
    source-in,
    source-over;
}
<div id="wrapper">
    
  <div id="image">
    <h2>Google Maps Logo SVG</h2>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/aa/Google_Maps_icon_(2020).svg" alt="Google Maps icon"/>
    </div>
    
  <div id="attempt">
    <h2>Image-Mask Abuse</h2>
    <div id="icon"></div>
    <div id="tip"></div>
    
  </div>
</div>

3 Comments

Looks acceptable. I'm starting a bounty as soon as SO lets me, and if there's no better answer I'll mark this as accepted as well as giving it the bounty.
"...I haven't tested in any other browsers" - this is how it looks in Firefox (114.02/Ubuntu 23.04): i.sstatic.net/Jp5ID.png (and that screenshot is after I correct the apparent margin-top typo in the #tip rule-set)).
@DavidThomas lol

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.