Responsive menu

W dzisiejszych czasach, gdy internet przeglądany jest na różnorakich urządzeniach tworzenie sztywnych nawigacji jest błędem. Jak wiemy, dobra nawigacja po naszej stronie to klucz do jej sukcesu, a przynajmniej jeden z głównych elementów wpływających na niego.

Stworzenie płynnego, dopasowującego się do wielkości ekranu menu wcale trudnym zadaniem nie jest, o czym przekonacie się już za chwilę.


Zanim przystąpimy do pracy, trochę teorii, którą jeżeli wiesz o co chodzi spokojnie możesz pominąć.

Jak wiecie, menu to jedna z najważniejszych rzeczy na naszej stronie. Jeżeli nie jest intuicyjne, wygodne w użytku to możecie zapomnieć o dużej ilości użytkowników (chyba że wasza strona nazywa się Facebook).
Popatrzmy na przykładowe menu.

mobile-menu

 

Nie wiem jak wy, ale ja nie dał bym rady trafić swoimi paluchami w tak małe elementy na mobilnych urządzeniach. Ok, powyżej pokazałem te urządzenia w mniejszych rozmiarach, ale i tak menu wydaje się być ciut za małe.
Jeżeli jesteśmy nieco mądrzejszymi webmasterami, zamiast sztywnego na szerokość menu, zrobimy takie, które dopasowuje się do rozdzielczości. Jednak i w tym przypadku będzie problem. Przy małych ekranach kolejne elementy nie zmieszczą się obok siebie i zostaną zawinięte jeden pod drugi. Tak czy siak wciąż będą dość małe, źle ułożone i nieprzyjemne do korzystania na telefonach.

Stąd właśnie najlepiej korzystać w takich przypadkach z techniki Responsive design, który w skrócie polega na tym, że layout zmienia swoje ułożenie w zależności od rozdzielczości ekranu. Jeżeli nie za bardzo wiesz o czym piszę, wtedy zapraszam cię do bardzo dobrego artykułu po polsku i innego po angielsku.

Zaczynamy pracę

Nasze menu będzie zwykłą listą UL:

<nav>        
    <ul>
        <li><a href="">Start</a></li>
        <li><a href="">Oferta</a></li>
        <li><a href="">Galeria</a></li>
        <li><a href="">Cennik</a></li>
        <li><a href="">O nas</a></li>
        <li><a href="">Kontakt</a></li>
    </ul>
</nav>

Dodajmy do niego trochę stylowania.

.clearfix:before, 
.clearfix:after { content: ''; display: table; }
.clearfix:after { clear: both; }
.clearfix { zoom: 1; }

body {
    margin:0;
}
nav {
    min-height:60px;
    background: rgb(51,51,51); /* Old browsers */
    background: -moz-linear-gradient(top,  rgba(51,51,51,1) 0%, rgba(17,17,17,1) 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(51,51,51,1)), color-stop(100%,rgba(17,17,17,1))); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top,  rgba(51,51,51,1) 0%,rgba(17,17,17,1) 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top,  rgba(51,51,51,1) 0%,rgba(17,17,17,1) 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top,  rgba(51,51,51,1) 0%,rgba(17,17,17,1) 100%); /* IE10+ */
    background: linear-gradient(to bottom,  rgba(51,51,51,1) 0%,rgba(17,17,17,1) 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#333333', endColorstr='#111111',GradientType=0 ); /* IE6-9 */
}
nav ul {
    list-style:none; 
    padding:0; 
    margin:0;         
    font-size:0;
    display: block;        
}
nav ul li {
    display: inline-block;        
    max-width:100px;
    min-width:15%;
    text-align: center;
}    
nav ul li a {
    font:bold 14px/60px 'Open Sans', sans-serif;
    color:#eee;
    height:60px;
    display: block;
    text-decoration: none;        
    border-right:1px solid #444;
    border-left:1px solid #111;
}
nav ul li a:hover, nav ul li a:active, nav ul li a:focus {
    background: rgb(241,231,103); /* Old browsers */
    background: -moz-linear-gradient(top,  rgba(241,231,103,1) 0%, rgba(254,182,69,1) 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(241,231,103,1)), color-stop(100%,rgba(254,182,69,1))); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top,  rgba(241,231,103,1) 0%,rgba(254,182,69,1) 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top,  rgba(241,231,103,1) 0%,rgba(254,182,69,1) 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top,  rgba(241,231,103,1) 0%,rgba(254,182,69,1) 100%); /* IE10+ */
    background: linear-gradient(to bottom,  rgba(241,231,103,1) 0%,rgba(254,182,69,1) 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f1e767', endColorstr='#feb645',GradientType=0 ); /* IE6-9 */
    color:#333;
    box-shadow:-4px 0 3px -3px rgba(0, 0, 0, 0.6) inset,4px 0 3px -3px rgba(0, 0, 0, 0.6) inset;
}

Kod wydłużają głównie css-owe gradienty, które jak zwykle tworzę z wykorzystaniem tego narzędzia.
Nie stosuję tutaj żadnych sztywnych miar szerokości. Przy wysokości nie ma tego problemu, ale żeby nasze menu ładnie się dopasowywało do szerokości, nie możemy korzystać z żadnych pixeli przy szerokościach (wyjątkiem jest max-width, które ogranicza nam zbytnie wydłużanie elementów przy szerokich ekranach). Dla listy ustawiłem rozmiar czcionki na 0, który od razu nadpisuję dla LI nową wartością. Dzięki temu między poszczególnymi elementami listy nie ma odstępów, które normalnie dla elementów typu display-block występują.

http://cssdeck.com/labs/ila3dylz/0

 

Jak masz szeroki monitor, to zobaczysz ładnie ułożone menu. Jeżeli masz mniejszą rozdzielczość, zobaczysz problemy, o których wspominałem powyżej. Przy małych rozdzielczościach poszczególne elementy menu mimo szerokości procentowej dochodzą do momentu, w którym nie mogą się dalej pomniejszać (przez wielkość czcionki) i zachodzą jedno pod drugie. Zajmiemy się tym przy okazji wersji dla urządzeń mobilnych.

Wersja mobilna

Mobilna wersja powinna mieć przede wszystkim duże, wyraźne linki. Dlatego elementy listy leżące obok siebie zamieniamy na duże leżące jeden pod drugim.
I teraz mała podpowiedź. Nowe stylowanie dla wersji mobilnej dopisujemy bezpośrednio pod tamtym stylowaniem. Dzięki temu będziemy widzieli nową mobilną wersję (którą potem podepniemy do odpowiedniej rozdzielczości) na bierząco.

...poprzednie stylowanie...

nav #input-toggle:checked ~ ul {
    max-height:500px;
}
nav ul li {
    border:0;
    width:100%;
    max-width: 100%;
    min-width:0;
    border-bottom:1px solid #333;

}
nav ul li a {
    display: block;
    text-align: center;
}

http://cssdeck.com/labs/mletn4fz/0

 

Wszystko pięknie i ładnie, ale w obecnej formie po wejściu na naszą stronę na telefonie zamiast treści zobaczymy tylko nasze wysokie menu, które przykryje cały ekran.
Idąc więc za popularnym ostatnio trendem dodamy znaną i lubianą ikonkę, która służy do rozwijania wersji mobilnej menu.

ikonka-menu

Pisać na jej temat nie będę, bo w przytoczonym artykule napisano wszystko co napisać było można :) Zamiast przedłużać, bierzemy się do dalszej roboty.
Większość tutoriali stosuje tutaj JS, ale tak naprawdę wcale nie musimy zapuszczać do takiego rozwijania skryptów.
Wystarczy wykorzystać technikę zaprezentowaną w tym tutorialu, która polega na stylowaniu elementu który leży bezpośrednio za inputem typu checkbox (któremu możemy pobierać stany za pomocą pseudoselektora :checked). Ogólnie ta technika ma postać:

.input-checkbox + .menu {......}
.input-checkbox:checked + .menu {......}

Samego checkboxa zbytnio stylować nie możemy, dlatego go ukrywamy, a zmieniamy wygląd dla labela, który odnosi się do tego ukrytego checkboxa :)
I to właśnie ten label będzie naszym guzikiem pokazującym menu.

<nav>        
    <label for="input-toggle">
        <span></span>
        <span></span>
        <span></span>
    </label>

    <input type="checkbox" id="input-toggle">    
    <ul>
        <li><a href="">Start</a></li>
        <li><a href="">Oferta</a></li>
        <li><a href="">Galeria</a></li>
        <li><a href="">Cennik</a></li>
        <li><a href="">O nas</a></li>
        <li><a href="">Kontakt</a></li>
    </ul>
</nav>

Doszedł nam omawiany checkbox, oraz labelka, która ma w sobie 3 spany (trzy białe kreseczki w naszym przycisku).
Dodać stylowanie do labelki i checkboxa:

#input-toggle {
    opacity:0;
    position: absolute;
    top:0;
    left:0;
}

.navigation-toggle { 
    display:block;
    width:44px; 
    height:33px; 
    margin:5px; 
    text-align:center; 
    border-radius:4px; 
    border:1px solid #404040; 
    background-image: linear-gradient(to bottom, #000, #111); 
    background-repeat: repeat-x; 
    color:#FFFFFF; 
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 
    padding-top:10px; 
    position:absolute; 
    top:2px; right:2px; 
    cursor:pointer; 
}
.navigation-toggle span { 
    background-color: #F5F5F5; 
    border-radius: 1px 1px 1px 1px; 
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); 
    display:block; 
    height:2px; 
    width:18px; 
    margin:4px auto; 
}
nav ul {
    margin-top:55px;
    overflow: hidden;                
    max-height:0;
    transition:max-height 0.35s ease 0s;
    -webkit-transition:max-height 0.35s ease 0s;
    -moz-transition:max-height 0.35s ease 0s;
}
nav #input-toggle:checked + ul {
    max-height:500px;
}

Chcąc uzyskać animację rozwijania menu nie możemy zwyczajnie zmieniać mu wartości display. Trzeba zmieniać jego wysokość. Ale zmiana wysokości z height:0 (menu ukryte) na height:auto nie współgra z transition, czyli nie uzyskujemy animacji. Dlatego właśnie korzystamy z min-height, który sprawdza się wyśmienicie.

http://cssdeck.com/labs/p4xmflii/0

 

Tak naprawdę całą pracę mamy już skończoną. Pozostaje naszą wersję mobilną objąć odpowiednim media queries

@media screen and (max-width:500px) {
      ....tutaj leci nasz kod dla mobilnych wersji...
}

I to wszystko. Gotową wersję z lekko uporządkowanym kodem css możesz zobaczyć pod poniższym linkiem:

Finalne menuNie zapomnij podłubać przy wielkości okna przeglądarki by zobaczyć jak ładnie zmienia się nasze dzieło.

Niestety powyższa metoda taka cudowna nie jest. Na mobilnych przeglądarkach istnieje błąd, który powoduje, że trik z checkboxem nie działa. Jest na to jednak bardzo proste lekarstwo.
Więcej na ten temat przeczytasz tutaj: http://timpietrusky.com/advanced-checkbox-hack

Komentarze