英文:
How to recreate 2020 Google Maps icon's shape without SVG?
问题
我正在尝试重新创建Google地图的图标(2020年)。彩色背景和中间的洞看起来很容易:我只需要一些渐变和一个蒙版。
以下是显示我当前努力的代码片段(以及一个CodePen链接,如果你想尝试它):
: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>
然而,我无法理解其独特的形状。是否可能仅使用CSS创建这样的形状?
显然,我不寻求基于SVG的解决方案。我正在做这个作为一个个人项目,所以我只需要在至少一个浏览器中能够工作的东西。
英文:
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):
<!-- begin snippet: js hide: true -->
<!-- language: lang-css -->
: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;
}
<!-- language: lang-html -->
<div id="wrapper">
<div id="icon"></div>
</div>
<!-- end snippet -->
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.
答案1
得分: 2
这是我尽力想出的最佳方法,通过滥用多个radial-gradient
、-webkit-mask-image
、-webkit-mask-image-composite
,不幸的是,为了实现“尖尖部分”,我使用了一个兄弟元素,而不是能够扩展原始的#icon
,也不能使用::after
元素(因为::after
元素会被其父元素的蒙版剪裁)。
(我想这可以重新组织,使顶部的圆形部分使用::before
,尖尖部分使用::after
,否则#icon
仅作为其两个伪元素子元素的容器和边界,但这是留给读者的练习)。
这是在Chrome中的效果。我还没有在其他浏览器中进行测试:
: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>
<details>
<summary>英文:</summary>
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][1]][1]
---------------
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
: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;
}
<!-- language: lang-html -->
<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>
<!-- end snippet -->
[1]: https://i.stack.imgur.com/eujIk.png
</details>
# 答案2
**得分**: 2
以下是您要翻译的内容:
```html
一个在所有浏览器中应该有效的具有一个元素的近似方法:
<!-- 开始代码片段:js 隐藏:false 控制台:true babel:false -->
<!-- 语言:lang-css -->
.logo {
width: 200px; /* 控制大小 */
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;
}
<!-- 语言:lang-html -->
<div class="logo"></div>
<img src="https://upload.wikimedia.org/wikipedia/commons/a/aa/Google_Maps_icon_(2020).svg" width="200">
<!-- 结束代码片段 -->
请注意,这里只包括了代码部分,没有翻译代码部分之外的内容。
英文:
An approximation with one element that should work in all the browsers:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
.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;
}
<!-- language: lang-html -->
<div class="logo"></div>
<img src="https://upload.wikimedia.org/wikipedia/commons/a/aa/Google_Maps_icon_(2020).svg" width="200">
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论