<div class="btns">
<button data-starter>애니메이션 시작</button>
<button data-container="start">변환 없음, 애니메이션 없음</button>
<button data-container="transform">애니메이션 전 (0%)</button>
<button data-container="composition" class="active">애니메이션 후 (100%)</button>
</div>
<ul class="units">
<li>100px</li>
<li>200px</li>
<li>300px</li>
<li>400px</li>
<li>500px</li>
<li>600px</li>
<li>700px</li>
<li>800px</li>
<li>900px</li>
</ul>
<ul class="marks">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="container start">
<div class="item">
replace
</div>
<div class="item">
add
</div>
<div class="item">
accumulate
</div>
</div>
<div class="container transform">
<div class="item">
replace
(100x50)
</div>
<div class="item">
add
(200x100)
</div>
<div class="item">
accumulate
(200x100)
</div>
</div>
<div class="container composition zup">
<div class="item">
replace
(200x100)
</div>
<div class="item">
add
(400x200)
</div>
<div class="item">
accumulate
(300x150)
</div>
</div>
// Init~ Don't touch here!
$color: #121212;
body {
padding: 20px;
background-color: #121212;
font-family: 'NanumSquareRound',sans-serif;
color: $color;
}
.btns {
display: flex;
gap: 10px;
margin-bottom: 30px;
}
button {
--btn-color: #6c6665;
--shadow-color: #55504f;
flex-shrink: 0;
height: 40px;
padding: 0 20px;
border: none;
outline: none;
border-radius: 10px;
background-color: var(--btn-color);
box-shadow:
0 6px 0 var(--shadow-color),
0 6px 10px rgba(0,0,0,.2);
font-size: 16px;
color: #fff;
cursor: pointer;
transition: .1s;
}
button:hover {
filter: brightness(130%);
}
button:active {
transform: translateY(4px);
box-shadow:
0 4px 0 var(--shadow-color),
0 3px 5px rgba(0,0,0,.2);
}
button[data-starter] {
--btn-color: crimson;
--shadow-color: #9e1832;
margin-right: 20px;
}
button.active {
--btn-color: royalblue;
--shadow-color: #3254b8;
}
$width: 100px;
$height: 50px;
.container {
// border: 10px solid rgba(black, .1);
border-radius: 10px;
display: grid;
grid-template-columns: repeat(10, $width);
grid-template-rows: repeat(8, $height);
grid-auto-flow: column;
}
.item {
grid-column: 1 / 2;
display: flex;
justify-content: center;
align-items: center;
padding: 0 20px;
box-sizing: border-box;
position: relative;
font-size: 12px;
font-weight: 900;
color: $color;
text-align: center;
text-shadow: 3px 0 0 rgba(white, .3);
cursor: pointer;
@for $i from 0 through 2 {
$nth: $i + 1;
&:nth-child(#{$nth}) {
grid-row-start: $nth + $i;
grid-row-end: $nth + $i + 1;
}
}
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
border: 4px solid rgba($color, .7);
border-radius: 10px;
box-sizing: border-box;
width: 100%;
height: 100%;
z-index: -1;
}
$colors: (tomato, orange, limegreen, dodgerblue, hotpink, darkgray, crimson, orangered, lawngreen, aqua, royalblue, wheat, brown, gray, salmon, deeppink, gold, springgreen, slateblue, darkslategray);
@each $color in $colors {
$index: index($colors, $color);
&:nth-child(#{$index})::before {
background-color: rgba($color, .8);
}
}
&::after {
content: "";
width: 10px;
height: 50%;
background: white;
position: absolute;
top: 16px;
left: 16px;
border-radius: 100px;
opacity: .3;
z-index: -1;
}
}
.units {
margin-bottom: 20px;
display: grid;
grid-template-columns: repeat(10, $width);
li {
font-size: 20px;
font-weight: bold;
color: #333;
transform: translateX($width - 26px);
}
}
.marks {
position: absolute;
display: grid;
grid-template-columns: repeat(10, $width);
grid-auto-rows: $height;
li {
position: relative;
border-left: 4px dashed #333;
border-top: 4px dashed #333;
transform: translateX(-2px);
z-index: -2;
font-size: 16px;
font-weight: bold;
color: #555;
display: flex;
justify-content: center;
align-items: center;
&:nth-child(10n+1) {
border-left: none;
}
&:nth-child(n+71) {
border-bottom: 4px dashed #333;
}
}
}
// Test here!
.container {
position: relative;
&.start {
opacity: .3;
position: absolute;
}
&.transform {
opacity: .3;
position: absolute;
.item {
width: $width;
height: $height;
animation-name: heropy;
animation-duration: 3s;
animation-fill-mode: both;
animation-play-state: paused;
transform: translateX(50px) scale(2);
transform-origin: 0 0;
}
.item:nth-child(1) { animation-composition: replace; }
.item:nth-child(2) { animation-composition: add; }
.item:nth-child(3) { animation-composition: accumulate; }
}
&.composition {
opacity: .3;
.item {
width: $width;
height: $height;
animation-name: heropy;
animation-duration: 3s;
animation-fill-mode: both;
transform: translateX(50px) scale(2);
transform-origin: 0 0;
}
.item:nth-child(1) { animation-composition: replace; }
.item:nth-child(2) { animation-composition: add; }
.item:nth-child(3) { animation-composition: accumulate; }
}
&.zup {
opacity: 1;
z-index: 1;
}
}
@keyframes heropy {
0% {
transform: translateX(50px) scale(1);
}
100% {
transform: translateX(100px) scale(2);
}
}
View Compiled
const containerEls = document.querySelectorAll('.container')
const cotainerEl = document.querySelector('.container.composition')
const btnEls = document.querySelectorAll('.btns [data-container]')
const startBtnEl = document.querySelector('.btns [data-starter]')
startBtnEl.addEventListener('click', () => {
cotainerEl.classList.remove('composition')
setTimeout(() => {
cotainerEl.classList.add('composition')
})
})
btnEls.forEach(btnEl => {
btnEl.addEventListener('click', () => {
const { container: containerName } = btnEl.dataset
btnEls.forEach(b => b !== btnEl && b.classList.remove('active'))
btnEl.classList.toggle('active')
containerEls.forEach(containerEl => {
containerEl.classList.remove('zup')
if (btnEl.classList.contains('active') && containerEl.classList.contains(containerName)) {
containerEl.classList.add('zup')
}
})
})
})
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.