Marko Prelec

Flexbox header

Auto Flexbox Header

Na tretjem CSS Meetupu #2016:first-child() sem predstavil poenostavljeno kodo za flexbox header naše zadnje ProteusThemes WordPress teme, ki je še v izdelavi. Objavim link, ko bo sprejeta na ThemeForest.

HTML struktura

Za delovanje flexboxa najprej potrebujemo HTML strukturo, kjer imamo neke elemente znotraj containerja. V našem primeru bo container class .header, elementi znotraj njega so pa .header__logo, .header__widgets, .header__navigation in .header__social-icons.


<header class="header">
  <div class="header__logo">
    Logo
  </div>
  <div class="header__widgets">
    Widgets
  </div>
  <div class="header__navigation">
    Navigation
  </div>
  <div class="header__social-icons">
    Social Icons
  </div>
</header>

Osnoven CSS

Sedaj, ko imamo strukturo narejeno, bomo vsakemu elementu določili različen background color. Le zato, da jih lažje ločimo med seboj. Pod resolucijo 992px bo širina vseh elementov 100%, nad 992px pa določimo neko fiksno širino in višino. Primer kode za class .header__logo:


.header__logo {
  background-color: red;
  width: 100%;
}

@media (min-width: 992px) {
  .header__logo {
    width: 250px;
    height: 150px;
  }
}

Poglejmo, kaj se je zgodilo, če to kodo pogledamo v brskalniku.

Flexbox
Pripravljena mobile struktura preden smo dodali flexbox.

Na resolucijah manjših od 992px lahko vidimo, da so vsi elementi en pod drugim in vsak zaseda 100% širine.

Flexbox
Pripravljena desktop struktura preden smo dodali flexbox.

Nad 992px so spet vsi elementi eden pod drugim, le da imajo tukaj določeno še širino in višino.
Sedaj, ko imamo vse to pripravljeno, lahko začnemo s flexboxom.

Flexbox


.header {
  display: flex;
}

Na container, v našem primeru je to class .header, dodamo display: flex;, na ta način smo flexbox aktivirali in to sedaj vpliva tudi na vse elemente (prvega nivoja) znotraj containerja.

Flexbox
Zaradi flex wrap so vsi elementi v eni vrstici.

Mobilna verzija:

Flexbox
Zaradi flex wrap so vsi elementi v eni vrstici.

Vidimo, da nam je tako za mobile kot za desktop verzijo strani vse elemente prestavilo v eno vrstico, čeprav imajo skupno širino večjo od 100%. Zakaj se to zgodi?

Flex Wrap

Kriva je privzeta flexbox nastavitev za flex-wrap, ki je nowrap. To pomeni, da flexbox ne pusti, da bi elementi skočili v novo vrstico. Če nowrap spremenimo v wrap, pa gredo v novo vrstico, če je njihova širina večja od 100%.


.header {
  display: flex;
  flex-wrap: wrap;
}

Flex Direction

Druga pomembna stvar tukaj je še flex-direction, za katerega je privzeta nastavitev row. Tukaj imamo na izbiro še row-reverse, ki elemente razporedi v obratnem vrstnem redu. Zelo uporabno, če delamo RTL verzijo strani. Obstaja še column in column-reverse. Vse se obnaša isto kot pri row, le da so tukaj elementi eden pod drugim. V našem primeru bomo uporabili nastavitev row, saj hočemo, da so vsi naši elementi v vrsti in v normalnem vrstnem redu.


.header {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
}

Flex Flow

To kodo lahko še skrajšamo, tako da jo združimo v flex-flow, kjer najprej napišemo flex-direction potem pa še flex-wrap.


.header {
  display: flex;
  flex-flow: row wrap;
}
Flexbox
Desktop flexbox header pred popravkom, ki poskrbi, da gresta Navigation in Social Icons pod Widgets.

Vidimo, da so se elementi lepo razporedili in da je širina upoštevana. Problem imamo le še z Navigation in Social Icons. V našem primeru lahko to rešimo tako, da .header__navigation premaknemo v levo, kolikor je velik logo z margin-left in dvignemo za 90px, točno toliko, kolikor imamo še praznega prostora pod Widgetsi. Podobno naredimo še s Social Icons. Ker imamo flex-wrap nastavljen na wrap bosta oba elementa lepo zapolnila prazen prostor pod widgetsi.


@media (min-width: 992px) {
  .header__navigation {
    width: calc(80% - 250px);
    height: 90px;
    margin-left: 250px;
    margin-top: -90px;
  }
}

@media (min-width: 992px) {
  .header__social-icons {
    width: 20%;
    height: 90px;
    margin-top: -90px;
  }
}
Flexbox
Končana struktura za desktop verzijo flexbox headerja.

Order

Še en majhen problem imamo pri resolucijah manjših od 992px. V dizajnu so Widgeti pred Logotom in ne za Logotom, kot je to na desktop verziji. Včasih bi to rešili tako, da bi kodo od widgetov imeli v HTMLju napisano 2x. Enkrat pred logotom, drugič za logotom, vse skupaj bi pa po potrebi skrivali z display: none;. Stvar funkcionira, koda je pa grda in se po nepotrebnem 2x naloži.

Flexbox ima tudi tukaj super rešitev, in sicer order. Prav order je eden izmed glavnih razlogov, da v naših temah v headerju uporabljamo flexbox. Uporaba je precej enostavna. Napišemo, kje po vrsti naj se določen element pojavi in to je to.


.header__logo {
  order: 2;
}

@media (min-width: 992px) {
  .header__logo {
    order: 1;
  }
}

.header__widgets {
  order: 1;
}

@media (min-width: 992px) {
  .header__widgets {
    order: 2;
  }
}

.header__navigation {
  order: 3;
}

.header__social-icons {
  order: 4;
}

V našem primeru order pustimo takšen, kot je za resolucije večje od 992px. Za manjše pa lahko vidimo, da smo za .header__logo dodali order: 2; za .header__widgets pa order: 1;

Flexbox
Zaradi flexbox orderja so sedaj Widgets nad Logo.

Flexbox header

Sedaj, ko imamo vso strukturo pripravljeno, popravimo background-color barve, dodamo v vsak element primerno vsebino in naš header je končan.

Auto Flexbox Header
Desktop verzija flexbox headerja za Auto WordPress temo.

Mobilna verzija:

Auto Mobile Flexbox Header
Mobile verzija flexbox headerja za Auto WordPress temo.

Flexbox podpora

Za pregled podpore uporabimo spletno stran Can I Use: http://caniuse.com/#feat=flexbox. Vidimo, da je flexbox podprt povsod razen v starejših Internet Explorerjih.

IE10 in IE11 sta podprta samo delno zaradi kupa bugov, ki jih imata s flexboxom, ampak tudi za večino teh obstajajo že rešitve. Če ste prisiljeni podpirati tudi IE8 in IE9 pa obstaja Polyfill, ki vam bo rešil ta problem: https://github.com/10up/flexibility.

* Zaradi lepše predstavitve sem izpustil prefixe.

Author

Marko Prelec

I started working on the web in primary school. Since then, I have accumulated a lot of experience and always strive to write simple and efficient code. You can find more about me on Twitter.