This is a very common type of animation - toggle a sidebar on/off:
document.querySelector('.toggle').addEventListener('click', e =>
document.body.classList.toggle('no-aside')
)
body {
display: grid;
grid-gap: 10px;
grid-template-columns: minmax(50px, 200px) auto;
grid-template-areas: "aside main";
margin: 0;
width: 100vw;
height: 100vh;
transition: grid-template-columns .25s;
}
body.no-aside {
grid-template-columns: 50px auto;
}
aside {
background: #111;
color: #fff;
}
main {
background: #ddd;
}
.toggle {
background: #111;
width: 40px;
height: 40px;
display: block;
position: relative;
}
.toggle i,
.toggle i::after,
.toggle i::before {
position: absolute;
width: 40px;
height: 4px;
border-radius: 4px;
transition: transform .15s;
background-color: #fff;
}
.toggle i {
top: 46%;
left: 18%;
display: block;
opacity: .5;
}
.toggle i::before {
top: -10px;
}
.toggle i::after {
bottom: -10px;
}
.toggle i::after,
.toggle i::before {
content: '';
display: block;
}
.toggle i::before {
transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1);
}
.toggle i::after {
transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1);
}
.no-aside .toggle i::before,
.no-aside .toggle i::after {
transform: none;
}
<aside>
<a class="toggle">
<i></i>
</a>
</aside>
<main>
content
</main>
But it appears that the transitions for grid* properties are not yet implemented in browsers so it doesn't work with a grid layout.
Is there a way to achieve this with other properties, but still keep the grid layout? Everything I've tried, with width, left, margin etc. seems to leave a gap between the 2 grid items.
Grid is supposed to have 5 animatable properties:
grid-gap
, grid-row-gap
, grid-column-gap
, grid-template-columns
and grid-template-rows
.
But as you said, browsers have not implemented it yet. Firefox and Edge can animate grid-gap
, grid-row-gap
and grid-column-gap
, but not grid-template-columns
or grid-template-rows
. Chromium browsers can't animate any grid property at all.
A workaround for this particular case would be to set the transition as width on the aside, and have the template columns declared as min-content 1fr
.
document.querySelector('.toggle').addEventListener('click', e =>
document.body.classList.toggle('no-aside')
)
body {
display: grid;
grid-gap: 10px;
grid-template-columns: min-content 1fr;
/*
alternatively, ridiculously uneven FR columns can work too, such as
grid-template-columns: 1fr 30fr;
*/
grid-template-areas: "aside main";
margin: 0;
width: 100vw;
height: 100vh;
}
body.no-aside aside{
width:50px;
}
aside {
width:200px;
background: #111;
color: #fff;
transition: width 1s;
}
main {
background: #ddd;
}
.toggle {
background: #111;
width: 40px;
height: 40px;
display: block;
position: relative;
}
.toggle i,
.toggle i::after,
.toggle i::before {
position: absolute;
width: 40px;
height: 4px;
border-radius: 4px;
transition: transform .15s;
background-color: #fff;
}
.toggle i {
top: 46%;
left: 18%;
display: block;
opacity: .5;
}
.toggle i::before {
top: -10px;
}
.toggle i::after {
bottom: -10px;
}
.toggle i::after,
.toggle i::before {
content: '';
display: block;
}
.toggle i::before {
transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1);
}
.toggle i::after {
transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1);
}
.no-aside .toggle i::before,
.no-aside .toggle i::after {
transform: none;
}
<aside>
<a class="toggle">
<i></i>
</a>
</aside>
<main>
123123
</main>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With