<!-- Not an accessible component, don't use in production. See popover section of this article (una.im/radial-menu) for accessibility needs -->
<div class="menu">
<button class="menu-toggle">
<span aria-hidden="true">➕</span>
<span class="sr-only">menu trigger</span>
</button>
<ul class="menu-items">
<li class="item">
<button>
<span aria-hidden="true">♥️</span>
<span class="sr-only">add to favorites</span>
</button>
</li>
<li class="item">
<button>
<span aria-hidden="true">💾</span>
<span class="sr-only">save to collection</span>
</button>
</li>
<li class="item">
<button>
<span aria-hidden="true">🔗</span>
<span class="sr-only">copy link</span>
</button>
</li>
<li class="item">
<button>
<span aria-hidden="true">✉️</span>
<span class="sr-only">email</span>
</button>
</li>
<li class="item">
<button>
<span aria-hidden="true">🛒</span>
<span class="sr-only">add to cart</span>
</button>
</li>
</ul>
</div>
@import url('https://fonts.googleapis.com/css2?family=Noto+Emoji:wght@600&display=swap');
:root {
--btn-size: 2.5rem;
--extra-space: 1.2rem;
}
/* Where the magic happens */
.item {
--radius: calc(var(--btn-size) + var(--extra-space));
background-color: var(--bg);
transform: translateX(calc(cos(var(--angle)) * var(--radius)))
translateY(calc(sin(var(--angle) * -1) * var(--radius)))
rotate(0deg);
transition: all 0.3s var(--delay) ease;
}
/* Every item gets a background, angle, and delay */
.item:nth-child(1) {
--bg: pink;
--angle: 0deg;
--delay: 0s;
}
.item:nth-child(2) {
--bg: thistle;
--angle: 45deg;
--delay: 0.1s;
}
.item:nth-child(3) {
--bg: paleturquoise;
--angle: 90deg;
--delay: 0.2s;
}
.item:nth-child(4) {
--bg: lightgreen;
--angle: 135deg;
--delay: 0.3s;
}
.item:nth-child(5) {
--bg: peachpuff;
--angle: 180deg;
--delay: 0.4s;
}
.menu:not(:focus-within) .item {
--radius: 0;
--angle: 0;
rotate: 45deg;
}
/* rotate the "plus" */
/* .menu-toggle > div {
transition: transform 0.3s;
}
.menu:focus-within .menu-toggle > div {
transform: rotate(90deg);
} */
/* Blah blah */
.item {
border-radius: 50%;
width: var(--btn-size);
aspect-ratio: 1/1;
}
.menu-toggle {
border-radius: 50%;
width: var(--btn-size);
aspect-ratio: 1/1;
background: darksalmon;
z-index: 1;
}
/* Grid piles */
.menu,
.menu-items,
body,
.item {
display: grid;
place-content: center;
}
.menu > *,
.menu-items > *,
body > *
.item button {
grid-area: 1/1;
}
/* Resets, etc. */
/* visually-hidden ala https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html */
.sr-only {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
button {
border: none;
background: none;
font-family: 'Noto Emoji';
color: #222;
font-size: 1.25rem;
}
button:focus-visible {
outline: 2px dashed deeppink;
border-radius: 50%;
aspect-ratio: 1/1;
}
body {
height: 100vh;
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.