Created
July 3, 2024 14:41
-
-
Save chrishow/079f389e7096f0fa1efac086893ddf8a to your computer and use it in GitHub Desktop.
Octopus not SVG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class=container> | |
<ol class='in items'> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
<li>Item</li> | |
</ol> | |
<div class=head> | |
Lorem Ipsum | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const itemLists = document.querySelectorAll('.items'); | |
itemLists.forEach((itemList) => { | |
const items = itemList.querySelectorAll(':scope > li'); | |
const numItems = items.length; | |
itemList.style.setProperty('--itemCount', numItems); | |
console.log('numItems: ', numItems); | |
items.forEach((item, i) => { | |
const arm = document.createElement('div'); | |
arm.style.setProperty('--index', i+1); | |
let svg; | |
if(i == ((numItems + 1) / 2 ) - 1) { | |
svg = getFlatSvg(); | |
arm.classList.add('middle'); | |
} else if(i > numItems / 2 - 1) { | |
svg = getCurveSvg(); | |
arm.classList.add('bottom'); | |
} else { | |
svg = getCurveSvg(); | |
} | |
arm.appendChild(svg); | |
item.prepend(arm); | |
}); | |
}); | |
function getCurveSvg() { | |
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); | |
// viewBox="0 0 100 100" preserveAspectRatio="none" | |
svg.setAttribute('viewBox', "0 0 100 100"); | |
svg.setAttribute('preserveAspectRatio', "none"); | |
const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); | |
path.setAttribute('vector-effect', 'non-scaling-stroke'); | |
path.setAttribute('d', 'm 0 4 C 80 2, 40 96, 100 98'); | |
svg.appendChild(path); | |
return svg; | |
} | |
function getFlatSvg() { | |
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); | |
// viewBox="0 0 100 100" preserveAspectRatio="none" | |
svg.setAttribute('viewBox', "0 0 100 100"); | |
svg.setAttribute('preserveAspectRatio', "none"); | |
const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); | |
path.setAttribute('vector-effect', 'non-scaling-stroke'); | |
path.setAttribute('d', 'm 0 4 h 100'); | |
svg.appendChild(path); | |
return svg; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
:root { | |
--bg-color: hotpink; | |
--fg-color: white; | |
--item-vertical-padding: .25em; | |
--item-vertical-margin: .5em; | |
/* font-size: 12px; */ | |
} | |
body { | |
font-family: system-ui, sans-serif; | |
font-weight: normal; | |
} | |
.container { | |
color: var(--fg-color); | |
display: grid; | |
width: 80%; | |
border: 1px grey solid; | |
grid-template-columns: 2fr 1fr 2fr; | |
align-items: center; | |
line-height: 1 | |
} | |
.items { | |
margin: 0; | |
padding: 0; | |
list-style: none; | |
position: relative; | |
} | |
.items li { | |
background-color: var(--bg-color); | |
margin: var(--item-vertical-margin) 0 var(--item-vertical-margin) 0.5em; | |
padding: var(--item-vertical-padding) 0.5em; | |
border-radius: 0.5em; | |
width: calc(50% - 1em); | |
} | |
.items li div { | |
position: absolute; | |
z-index: -1; | |
/* background-color: rgba(0, 255, 0, 0.5); */ | |
height: calc( | |
50% - | |
( | |
(var(--index) - 1) * (var(--item-vertical-padding) * 2) | |
) - | |
( | |
(var(--index) - 1) * (var(--item-vertical-margin) * 1) | |
) - | |
( | |
(var(--index) - 1) * 1em | |
) + var(--item-vertical-padding) | |
); | |
right: -1em; | |
width: calc(50% + 2em); | |
margin-top: calc(-1 * (var(--item-vertical-padding))); | |
padding-block: calc(var(--item-vertical-padding) + 0.5em); | |
padding-block: 0.5em; | |
} | |
.items li div.bottom { | |
/* background-color: blue; */ | |
/* background-color: rgba(0, 255, 0, 0.5); */ | |
height: calc( | |
50% - | |
( | |
(var(--itemCount) - var(--index) + 0) * (var(--item-vertical-padding) * 2) | |
) - | |
( | |
(var(--itemCount) - var(--index) + 0) * (var(--item-vertical-margin) * 1) | |
) - | |
( | |
(var(--itemCount) - var(--index) + 0) * 1em | |
) - var(--item-vertical-padding) | |
); | |
top: 50%; | |
/* left: calc(var(--index) * 1em); */ | |
margin-top: calc(-1 * (var(--item-vertical-padding))); | |
} | |
.items li div.middle { | |
top: auto; | |
bottom: initial; | |
margin-top: 0; | |
} | |
.items li div.middle svg { | |
height: 1em; | |
} | |
.items li div.bottom svg { | |
transform: scaleY(-1); | |
} | |
.items li div svg { | |
width: 100%; | |
height: calc(100% - 1em); | |
overflow: visible; | |
} | |
.items li div svg path { | |
stroke: hotpink; | |
fill: transparent; | |
stroke-width: 10; | |
} | |
.items.out li { | |
margin: 0.5em 0.5em 0.5em 0; | |
} | |
.head { | |
background-color: var(--bg-color); | |
aspect-ratio: 1; | |
width: 100%; | |
border-radius: 50%; | |
text-align: center; | |
display: flex; | |
justify-content: center; | |
flex-direction: column; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment