Información del post ⇣

Diferente apariencia de menú en movil, escritorio y al hacer scroll

Este post se publicó hace más de dos años, es posible que la información publicada esté obsoleta o las referencias no existan.

El problema con este tipo de comportamientos es la organización del código y el reseteo de los estilos al pasar de un estado a otro.

De momento la forma más optima que he encontrado para lidiar con todo esto, sin volverse loco y sin duplicar menús es separarando la apariencia de cada menú en mixins y cargandolos cuando corresponda ya sea mediante mediaqueries o jQuery.

Html

No tiene ningún secreto, por defecto el contenedor lleva la clase main-menu que cambiaremos al hacer scroll por scrolled-menu mediante jQuery.

<div class="menu-container main-menu">
    <a class="b-hamburguer">M</a>
    <ul>
        <li><a href="">Inicio</a></li>
        <li><a href="">About</a></li>
        <li><a href="">Blog</a></li>
        <li><a href="">Contacto</a></li>
    </ul>
</div>

Mixins

En este ejemplo he empleado dos mixins uno para los estilos para movil, que llamaremos hamburguer y otro para los estilos del menú desplegado, al que llamaremos desktop.

Personalmente prefiero separar los mixns en archivos diferentes mx-hamburguer.scss y mx-desktop.scss e importarlos al archivo propio del menú menu-container.scss.

@mixin hamburguer{
    // Aqui los estilos para mobile
}

@mixin desktop{
    // Aqui los estilos para el menu desplegado
}

Es aconsejable mantener los estilos comunes en el contenedor generico.

.menu-container{
    max-width: 900;
    margin: 0 auto;
    ...
}

Mixin y mediaqueries

Cargamos los estilos de cada apariencia mediante los mixins. Como podeis ver los estilos del menu de mobil se resetean al cargar los estilos del escritorio, para ello empleamos max-width en la mediaquerie, para determinar hasta donde se usan esos estilos y cargamos los de escritorio al siguiente pixel.

Ahora mismo esto puede ser algo extraño, pero simplifica el trabajo a la hora de incorporar los mismos estilos de la versión de mobil a la versión con scroll.

.main-menu{
    @media (max-width: 800px) {
        @include hamburguer;
    }
    @media (min-width: 801px) {
        @include desktop;
    }  
}

Clases

Los estilos del menú se dividirán en 3 clases.

.menu-container{
    // Estilos comunes a todos los menús
    // Tipografía, colores, ...
}

.main-menu{
    // Estilos cargados por defecto, 
    // donde cargan las mediaqueries arriba mostradas
    // con los dos mixins creados
}

.scrolled-menu{
    // Solo carga el mixin de movil al hacer scroll
}

¿Como funciona todo esto?

Por defecto cargamos la clase .main-menu.

<div class="menu-container main-menu">
    <!-- Html del menu --->
</div>

Mediante jQuery cambiamos la clase main-menu por scrolled-menu, activando de esta manera los estilos del menú movil y desactivando los de escritorio. Como los estilos están separados por mixins y se resetean no es necesario sobreescribir estilos para cada una de las clases y resulta más sencillo de entender y mantener.

Estilos al hacer scroll en movil

Hay que tener en cuenta que los estilos de scrolled-menu se activarán al hacer scroll por debajo de 800px, pero como son exactamente los mismo no debe haber ningun salto ni comportamiento extraño al hacer scroll en movil. En cualquier caso, podemos modificar lo que deseemos mediante las mediaqueries, en este caso la anchura y posicionamiento del menu.

.scrolled-menu{
    @include hamburguer;
    @media (min-width: 801px) {
        width: 100%;
        left: 50%;
        margin-left: -450px;
    } 
}

Demo

Aqui teneis la demo, para poder probar correctamente el funcionamiento es aconsejable verlo a pantalla completa y probar de redimensionar la ventana y hacer scroll cuando la versión de escritorio del menú está cargada (Por encima de 800px).

Demo en codepen