Add transition when hiding the sidebar

Viewed 320

I created my layout with css grid with two columns:

.app {
    height: 100vh;
    display: grid;
    grid-template-columns: 260px 1fr;
    grid-template-rows: 56px 1fr 40px;
    grid-template-areas: "menu header" "menu content" "menu footer";
}

Now I want to add a smooth transition. I did the following: When I click on header component's toggle button, I hide my sidebar component.

.hide-menu {
    grid-template-areas:
        "header header"
        "content content"
        "footer footer";
}

The problem is that the layout is breaking.

enter image description here

enter image description here

enter image description here

I don't know what to pass as a parameter in translateX of layout component. I guess this is my issue.

.openMain {
    transform: translateX(-260px); <<<<<<<<
    transition: all 500ms linear;
}

Could you help me find out where I'm going wrong?

Full code

Layout component

<template>
    <div class="app" :class="{ 'hide-menu': ! isMenuVisible, closeMain: isMenuVisible, openMain: ! isMenuVisible}">
        <lheader />
        <lmenu />
        <main class="main p-5" style="overflow: auto">
            <slot />
        </main>
        <lfooter />
    </div>
</template>

<script>
import Lheader from "./Lheader.vue";
import Lfooter from "./Lfooter.vue";
import Lmenu from "./Lmenu.vue";
import { mapState } from "vuex";

export default {
    name: "Layout",
    computed: mapState(["isMenuVisible"]),
    components: {
        Lheader,
        Lfooter,
        Lmenu,
    },
};
</script>

<style>
.app {
    height: 100vh;
    display: grid;
    grid-template-columns: 260px 1fr;
    grid-template-rows: 56px 1fr 40px;
    grid-template-areas: "menu header" "menu content" "menu footer";
}
.main {
    grid-area: content;
    background-color: #ebedef;
}
.hide-menu {
    grid-template-areas:
        "header header"
        "content content"
        "footer footer";
}
.openMain {
    transform: translateX(-260px);
    transition: all 500ms linear;
}
.closeMain {
    transform: translateX(0);
    transition: all 500ms linear;
}

</style>

Menu (sidebar) component

<template>        
    <aside :class="{ openSidebar:isMenuVisible, closeSidebar:!isMenuVisible }" class="menu text-white border-r
        border-gray-400">
        <div class="flex justify-center items-center h-14 bg-gray-800">
            Brand
        </div>
        <div class="flex flex-col">
            <ul>
                <inertia-link href="/">
                    <li class="flex items-center p-5 hover:bg-gray-700 cursor-pointer "
                        :class="isUrl('') ? 'bg-gray-700' : ''">
                            <i class="fas fa-tachometer-alt mr-2"></i>Dashboard
                    </li>
                </inertia-link>
                <li class="flex flex-col p-5 hover:bg-gray-700 cursor-pointer"
                    :class="isUrl('users/index') ? 'bg-gray-700' : ''">
                    <a href="#" class="flex items-center" @click="usersMenu = !usersMenu">
                        <div class="flex-grow">
                            <i class="fas fa-users mr-2"></i>Users
                        </div>
                        <div>
                            <i class="fas" :class="{'fa-angle-down': usersMenu, 'fa-angle-left': !usersMenu }">
                            </i>
                        </div>
                    </a>
                    <ul class="flex flex-col pt-5" :class="{ hidden: usersMenu }">
                        <inertia-link href="/users/index">
                            <li class="flex items-center h-14 px-6 hover:bg-gray-600 cursor-pointer rounded
                                transition duration-500 ease-in-out"
                                :class=" isUrl('users/index') ? 'bg-gray-600' : ''" >
                                    <i class="fas fa-list mr-2"></i>List
                            </li>
                        </inertia-link>
                        <inertia-link href="/users/report">
                            <li class="flex items-center h-14 px-6 hover:bg-gray-600 cursor-pointer rounded
                                transition duration-500 ease-in-out"
                                :class=" isUrl('users/report') ? 'bg-gray-600' : ''" >
                                    <i class="fas fa-list mr-2"></i>Report
                            </li>
                        </inertia-link>
                    </ul>
                </li>
            </ul>
        </div>
    </aside>
</template>

<script>
import { mapState } from 'vuex'

export default {
    name: "Menu",
    computed: mapState(['isMenuVisible']),
    data() {
        return {
            usersMenu: true
        };
    },
    methods: {
        isUrl(...urls) {
            let currentUrl = this.$page.url.substr(1);
            if (urls[0] === "") {
                return currentUrl === "";
            }
            return urls.filter((url) => currentUrl.startsWith(url)).length;
        }
    },
};
</script>

<style>
.menu {
    grid-area: menu;
    background-color: #3c4b64;
}
.openSidebar {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: translateX(0);
    transition: all 500ms linear;
}
.closeSidebar {
    position: absolute;
    opacity: 0;
    visibility: hidden;
    transform: translateX(-260px);
    transition: all 500ms linear;
}
</style>
2 Answers

Just adjust the width of the sidebar, and set the column width in the grid to auto.

Grid will do the adjustments for you.

In the snippet, just hover the grid to hide the sidebar

.app {
  height: 100vh;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: 56px 1fr 40px;
  grid-template-areas: "menu header" "menu content" "menu footer";
}

.menu {
   grid-area: "menu";
   width: 260px;
   height: 100vh;
   background-color: lightblue;
   transition: width 1s;
   overflow: hidden;
}

.app:hover .menu {
    width: 0px;
}

.header {
   grid-area: header;
}

.content {
   grid-area: content;
}

.footer {
   grid-area: footer;
}
<div class="app">
  <div class="menu">MENU</div>
  <div class="header">HEADER</div>
  <div class="content">CONTENT</div>
  <div class="footer">FOOTER</div>
</div>

First off, I don't think this would be the way I would do this type of thing, however, since this is what you are asking, have you tried:

.app {
    height: 100vh;
    display: grid;
    grid-template-columns: 260px 1fr;
    grid-template-rows: 56px 1fr 40px;
    grid-template-areas: "menu header" "menu content" "menu footer";
}

.hide-menu {
    grid-template-columns: 0px 1fr;
    grid-template-areas:
        "menu header"
        "menu content"
        "menu footer";
}

And perhaps you should also give the menu something like transform: scaleX(0) when clicking that button.

I think the main problem here is your translate actually. You start of by removing the sidebar, and then you translate everything the width of the sidebar. That's why the right content moves additionally. Maybe you could just start of by removing the translate and see what happens to be honest...

Related