Ero Stefano
Ero Stefano

Reputation: 646

Why is the width transition not working for screens smaller than 800px?

I'm working on a responsive website. I want the nav to fly in from left on small screens. For testing I added a click listener which adds and removes the class ".sidenav" to the nav.

Screen bigger than 800px:

Screen smaller than 800px:

Where is the mistake?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        html {
            height: 100%;
        }

        body {
            display: grid;
            height: 100%;
            margin: 0;
            grid-template-rows: 5rem 1fr 5rem;
        }

        header {
            grid-area: 1 / 1 / span 1 / span 1;
            background-color: aqua;
        }

        nav {
            background-color: lightblue;

            position: fixed;
            top: 5rem;

            width: 0;
            display: none;
            transition: width 2s;
        }

        main {
            grid-area: 2 / 1 / span 1 / span 1;
        }

        .sidenav {
            display: unset;
            width: 20rem;
        }

        footer {
            grid-area: 3 / 1 / span 1 / span 1;
            background-color: chartreuse;
        }

        @media screen and (min-width: 800px) {
            body {
                grid-template-rows: 5rem 1fr 5rem;
                grid-template-columns: 10rem 1fr;
            }

            header {
                grid-area: 1 / 1 / span 1 / span 2;
            }

            nav {
                grid-area: 2 / 1 / span 1 / span 1;
                display: unset;
                width: 10rem;
            }

            main {
                grid-area: 2 / 2 / span 1 / span 2;
            }

            footer {
                grid-area: 3 / 1 / span 1 / span 2;
            }
        }
    </style>
</head>
<body>

<header>Header</header>
<nav>Navigation</nav>
<main>Main</main>
<footer>Footer</footer>

<script>
    window.onclick = () => {
        let classList = document.getElementsByTagName('nav')[0].classList;
        if (classList.contains('sidenav')) {
            classList.remove('sidenav')
        } else {
            classList.add('sidenav')
        }
    }
</script>
</body>
</html>

Upvotes: 0

Views: 65

Answers (2)

Ero Stefano
Ero Stefano

Reputation: 646

As mentioned in the above posts display: none; is not transitionable. Thus I removed it and kept width: 0; which has the same visual effect. In addition I had to move transition: width 2s; into the class .sidenav.

Here is the working snippet:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
      html {
          height: 100%;
      }

      body {
          display: grid;
          height: 100%;
          margin: 0;
          grid-template-rows: 5rem 1fr 5rem;
      }

      header {
          grid-area: 1 / 1 / span 1 / span 1;
          background-color: aqua;
      }

      nav {
          background-color: lightblue;

          position: fixed;
          top: 5rem;

          width: 0;
      }

      main {
          grid-area: 2 / 1 / span 1 / span 1;
      }

      .sidenav {
          width: 20rem;
          transition: width 2s;
      }

      footer {
          grid-area: 3 / 1 / span 1 / span 1;
          background-color: chartreuse;
      }

      @media screen and (min-width: 800px) {
          body {
              grid-template-rows: 5rem 1fr 5rem;
              grid-template-columns: 10rem 1fr;
          }

          header {
              grid-area: 1 / 1 / span 1 / span 2;
          }

          nav {
              grid-area: 2 / 1 / span 1 / span 1;
              display: unset;
              width: 10rem;
          }

          main {
              grid-area: 2 / 2 / span 1 / span 2;
          }

          footer {
              grid-area: 3 / 1 / span 1 / span 2;
          }
      }
  </style>
</head>
<body>

<header>Header</header>
<nav>Navigation</nav>
<main>Main</main>
<footer>Footer</footer>

<script>
  window.onclick = () => {
    let classList = document.getElementsByTagName('nav')[0].classList;
    if (classList.contains('sidenav')) {
      classList.remove('sidenav')
    } else {
      classList.add('sidenav')
    }
  }
</script>
</body>
</html>

Upvotes: 0

Franco Gabriel
Franco Gabriel

Reputation: 568

The issue you have is that for viewports that are less than 800px you set display: none as property, first of all is not transitioned anywhere and in second place that's is a not transitioned property. It means that it has only discrete values going to unset immediately in your case.

I suggest you to play with visibility property for this effect, that's not transitionable but you can delay its appearing with transition-delay property.

Hope it helps!

Upvotes: 1

Related Questions