Flexbox

Flexbox és un mètode de disseny de pàgina web unidimensional que distribueix els elements de la pàgina web en files o en columnes. Els elements són «flexibles» i omplen tot l’espai de més o s’encongeixen per caber en espais més petits. Aquest article n’explica els fonaments.

Prerequisits: Conceptes bàsics d'HTML (consulta la Introducció a l’HTML), i nocions de com funciona el CSS (consulta la Introducció al CSS).
Objectiu: Aprendre a utilitzar el sistema de disseny de pàgines web Flexbox.

Per què Flexbox?

Durant molt de temps, les úniques eines fiables compatibles amb els navegadors, disponibles per crear dissenys de pàgina web amb CSS eren mètodes com ara els elements flotants (floats) i el posicionament. Estan bé i funcionen, però d'alguna manera també són més limitats i frustrants.

Uns requisits senzills de disseny de pàgina web com els que enumerem a continuació són difícils o impossibles d'aconseguir amb aquestes eines d’una manera còmoda i flexible:

  • Que un bloc de contingut es centri verticalment dins de l’element pare.
  • Que tots els elements fills d'un contenidor ocupin la mateixa quantitat d'amplada/alçada, independentment de la quantitat d'amplada/alçada que hi hagi disponible.
  • Que totes les columnes d'un disseny de pàgina en columnes múltiples adoptin la mateixa alçada, encara que continguin una quantitat de contingut diferent.

Com veureu en les properes seccions, Flexbox facilita moltes tasques de disseny de pàgina web. Aprofundim-hi!

Un exemple senzill

En aquest article, et farem treballar en un seguit d'exercicis que t’ajudaran a entendre com funciona Flexbox. Per començar, fes una còpia local del primer fitxer d'inici, flexbox0.html, que trobaràs en el nostre repositori de GitHub; carrega’l en un navegador modern (com Firefox o Chrome) i consulta’n el codi en el teu editor. També ho pots veure en viu aquí.

Observa que hi ha un element <header> amb un títol d’encapçalament de nivell superior i un element <section> que conté tres elements <article>. Els farem servir per a crear un disseny de tres columnes força habitual.

Especificar els elements flexbox

Per començar hem de decidir quins elements volem configurar perquè es comportin com caixes flexibles. Per tal de fer-ho, establim un valor especial de display en l'element pare dels elements als quals afectarà. En aquest cas, volem que siguin els elements <article>, per la qual cosa ho configurem en l’element <section>:

section {
  display: flex;
}

Això fa que l'element <section> esdevingui un contenidor flexible i els seus fills ítems flexibles. El resultat d'això hauria de presentar un aspecte semblant a això:

Per tant, aquesta declaració única, ens dona tot el que necessitem; increïble, oi? Tenim el nostre disseny de pàgina de columna múltiple amb columnes de la mateixa mida, i que tenen la mateixa alçada. Això és perquè els valors predeterminats que s’han donat als elements flex (els fills del contenidor flex) estan dissenyats per a resoldre problemes comuns com aquest.

Per deixar-ho clar, reiterem el que passa aquí. L’element al qual hem donat un valor de display de flex actua com un element de nivell de bloc en termes de com interactua amb la resta de la pàgina, però els seus fills es presenten com a elements flexibles. La següent secció explicarà amb més detall què significa això. Fixeu-vos també que podeu utilitzar un valor de display d'inline-flex si voleu disposar els fills d'un element com a elements flexibles, però que aquest element es comporti com un element en línia.

El model flex

Els elements que es disposen com caixes flexibles, es distribueixen al llarg de dos eixos:

flex_terms.png

  • L'eix principal (main axis) és l'eix que corre en la direcció en què es disposen els elements flex (p. ex., com files al llarg de la pàgina o com columnes, cap avall de la pàgina). L'inici i el final d'aquest eix reben els noms d’inici principal (main start) i final principal (main end).
  • L'eix transversal (cross axis) és l'eix que corre perpendicular a la direcció en què es disposen els elements flexibles. L'inici i el final d'aquest eix s'anomenen inici transversal (cross-start) i final tranversal (cross-end).
  • L'element pare que està configurat amb display: flex (la secció <section> del nostre exemple) s'anomena contenidor flex (flex container).
  • Els elements que es disposen com caixes flexibles dins del contenidor flex s'anomenen elements flexibles (flex items) (els elements <article> del nostre exemple).

Tingues present aquesta terminologia a mesura que avances en les seccions. Sempre pots tornar enrere si en algun moment l’ús d’aquests termes et genera confusions.

Columnes o files?

Flexbox proporciona una propietat anomenada flex-direction, que especifica en quina direcció discorre l'eix principal (en quina direcció es disposen les caixes flexibles fill); per defecte, està definida en row, que fa que els elements flexibles es disposin en una fila en la direcció de l'idioma predeterminat amb què funciona el teu navegador (d'esquerra a dreta, en el cas d'un navegador en català).

Prova d'afegir a la teva regla <section> la declaració següent:

flex-direction: column;

Observa que això posa de nou els elements en una disposició en columna, igual que estaven abans d’afegir-hi el CSS. Abans de continuar, elimina aquesta declaració del teu exemple.

Nota: També pots disposar elements flexibles en direcció inversa amb els valors row-reverse i column-reverse. Experimenta també amb aquests valors.

Ajust

Un problema que sorgeix quan tens un disseny de pàgina amb una amplada o una alçada fixa és que els fills de l’element flexbox poden desbordar el contenidor i trencar el disseny de la pàgina. Fes un cop d'ull al nostre exemple flexbox-wrap0.html i mira’l en directe (fes primer una còpia local d'aquest fitxer, si vols seguir amb aquest exemple):

Aquí observem que els fills desborden el contenidor. Una manera de solucionar això és afegir a la teva regla <section> la declaració següent:

flex-wrap: wrap;

Afegeix també la declaració següent a la teva regla <article>

flex: 200px;

Ara prova-ho; observa que el disseny es veu força més bé ara que hi has inclòs això:

Ara hi ha diverses files, i a cada fila hi ha tantes elements fill flexbox com és raonable que hi hagi, i si hi ha cap desbordament, es genera una altra línia. La declaració flex: 200px que hem establer per als elements <article> significa que cada article tindrà com a mínim una amplada de 200px; més endavant parlarem d'aquesta propietat amb més detall. També pots observar que els últims fills de l'última fila s’han fet més amples, de manera que la fila està igualment tota plena.

Però encara hi podem fer més. Primer de tot, prova de canviar el valor de la propietat flex-direction a row-reverse; observa que encara tens el disseny de files múltiples, però ara comença des de la cantonada oposada de la finestra del navegador i flueix en sentit invers.

La propietat flex-flow abreujada

En aquest punt, val la pena observar que hi ha una propietat abreujada per a flex-direction i flex-wrap, que és: flex-flow. Per exemple, pots substituir:

flex-direction: row;
flex-wrap: wrap;

per

flex-flow: row wrap;

Dimensió flexible dels elements flexibles

Tornem ara al nostre primer exemple i observem com podem controlar quina proporció d'espai poden ocupar els elements flexibles. Fes servir la teva còpia local de flexbox0.html, o fes una còpia de flexbox1.html com a punt de partida nou (també el pots veure en viu).

Primer, afegeix la regla següent al final del teu CSS:

article {
  flex: 1;
}

Es tracta d'un valor de proporció sense unitat que determina quina quantitat de l'espai disponible al llarg de l'eix principal ocupa cada element flexible. En aquest cas donem a cada element <article> un valor de 1, que significa que tots ocuparan una quantitat igual de l'espai que sobri després que s'hagin establert elements com ara l’àrea de farciment i el marge. És una proporció, que significa que donar a cada element flexible un valor de 400.000 tindria exactament el mateix efecte.

A continuació, afegeix la regla següent a sota de l'anterior:

article:nth-of-type(3) {
  flex: 2;
}

Aleshores, actualitza. Observa que el tercer element <article> ocupa el doble de l'amplada disponible que els altres dos; perquè ara hi ha en total quatre unitats proporcionals disponibles. Els dos primers elements flexibles en tenen una cadascun, i prenen 1/4 de l'espai disponible cadascun. El tercer té dues unitats, de manera que ocupa 2/4 de l'espai disponible (o el que és el mateix, la meitat).

També pots especificar un valor de mida mínima per al valor flex. Actualitza les teves regles per als elements <article>, així:

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}

Això bàsicament estableix que «Es dona a cada element flexible primer 200px de l'espai disponible. A continuació, la resta de l'espai disponible es reparteix segons les unitats de proporció». Actualitza i observa com es reparteix l'espai ara.

El valor real de flexbox es pot apreciar en la flexibilitat / capacitat de resposta; si canvies la mida de la finestra del navegador o afegeixes un altre element <article>, el disseny de pàgina encara funciona.

Propietat flex abreujada o no abreujada

flex és una propietat de abreujada que pot especificar fins a tres valors diferents:

  • El valor de la proporció sense unitat que hem comentat abans. Es pot especificar per a cada element usant la propietat no abreujada flex-grow.
  • Un segon valor de proporció sense unitat, flex-shrink, que entra en joc quan els elements flexibles desborden de l’element contenidor. Especifica quanta de la quantitat que desborda es treu de la mida de cada element flexible per a evitar que desbordi del contenidor. Aquesta és una característica avançada de flexbox i no la detallarem més en aquest article.
  • El valor mínim de la mida, que hem comentat abans. Es pot especificar per a cada element usant el valor no abreujat flex-base.

Recomanem evitar l'ús de les propietats flex no abreujades, si no és que t’és realment necessari (per exemple, perquè has de substituir alguna configuració anterior). Comporta escriure una gran quantitat de codi addicional, i pot acabar sent una mica confús.

Alineació horitzontal i vertical

També pots utilitzar funcions flexbox per a alinear elements flexibles al llarg dels eixos principals o transversals. Ho expliquem amb un nou exemple, flex-align0.html (també el pots veure en viu), que convertirem en una bonica barra d'eines/botons flexible. De moment, observa aquesta barra de menú horitzontal amb alguns botons agrupats a la cantonada superior esquerra.

Primer, fes una còpia local d'aquest exemple.

A continuació, afegeix a la part inferior del CSS de l'exemple el codi següent:

div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}

Actualitza la pàgina i observa que els botons estan ben centrats, horitzontalment i verticalment. Ho hem fet amb dues propietats noves.

El control align-items disposa els elements flexibles sobre l'eix transversal.

  • El valor predeterminat és stretch, que estira tots els elements flexibles fins a ocupar tot l’espai de l’element pare en la direcció de l'eix transversal. Si l’element pare no té una amplada fixa en la direcció de l'eix transversal, tots els elements flexibles es faran tan llargs com l’element flexible més llarg. Per això el nostre primer exemple tenia per defecte columnes de la mateixa alçada.
  • El valor center que hem utilitzat en el codi anterior manté les dimensions intrínseques dels elements, però els centrats al llarg de l'eix transversal. És per això que els botons d’aquest exemple estan centrats verticalment.
  • També pots tenir valors com flex-start i flex-end, que alineen tots els elements al principi i al final de l'eix transversal, respectivament. Consulta’n tots els detalls en align-items.

Pots anul·lar el comportament align-items per a elements flexibles individuals amb la propietat align-self. Per exemple, afegeix al teu CSS el codi el següent:

button:first-child {
  align-self: flex-end;
}

Dona un cop d'ull a l'efecte que hi produeix i retira de nou aquest codi quan hagis acabat.

La propietat justify-content controla on s’ubiquen els elements flexibles sobre l'eix principal.

  • El valor per defecte és flex-start, que col·loca tots els elements al principi de l'eix principal.
  • Pots fer servir flex-end perquè es col·loquin al final.
  • El valor center també és un valor per a justify-content i posa els elements flexibles al centre de l'eix principal.
  • El valor que hem utilitzat abans, space-around, és útil perquè distribueix tots els elements sobre l'eix principal de manera uniforme i deixa una mica d'espai en cada extrem.
  • Hi ha un altre valor, space-between, que és molt similar a space-around, però que no deixa cap espai als extrems.

T’animem a jugar amb aquests valors i veure com funcionen abans de continuar.

Ordena els elements flexibles

Flexbox també té una característica que canvia l'ordre de disposició dels elements flexibles sense afectar l'ordre d'origen. Aquesta és una altra característica que és impossible de fer amb els mètodes tradicionals de disseny de pàgines web.

El codi per a això és senzill: afegeix al codi d'exemple de la barra de botons el codi CSS següent:

button:first-child {
  order: 1;
}

Actualitza, i observa que ara el botó «Smile» s'ha mogut al final de l'eix principal. Parlarem de com això funciona amb una mica més detall:

  • Per defecte, tots els elements flexibles tenen un valor d’ordre (order) de 0.
  • Els elements flexibles que estan configurats amb un valor d’ordre més alt apareixen més endavant en l'ordre de visualització que els elements amb valors d’ordre més baix.
  • Els elements flexibles que tenen el mateix valor d'ordre apareixen en l’ordre d'origen. Així, si hi ha quatre elements que tenen configurats els valors d'ordre 2, 1, 1 i 0, respectivament, l’ordre de visualització serà 4t, 2n, 3r i 1r.
  • El 3r element apareix després del 2n perquè té el mateix valor d'ordre i està després en l'ordre d'origen.

Pots establir valors d'ordre negatius i fer que els elements apareguin abans que els elements amb un ordre 0. Per exemple, pots fer que el botó «Blush» aparegui al principi de l'eix principal amb la següent regla:

button:last-child {
  order: -1;
}

Caixes flexibles imbricades

Amb flexbox és possible crear dissenys força complexos. És del tot correcte establir que un element flexible sigui també un contenidor flexible, de manera que els elements fills també es disposin com caixes flexibles. Dona un cop d'ull a complex-flexbox.html (o també el pots veure en viu).

L'HTML d’això és força senzill. Hi ha un element <section> que conté tres elements <article>. El tercer element <article> conté tres elements <div>:

section - article
          article
          article - div - button   
                    div   button
                    div   button
                          button
                          button

Observa el codi que hem utilitzat per al disseny.

En primer lloc, establim que els fills de <section> es disposin com caixes flexibles.

section {
  display: flex;
}

A continuació, establim alguns valors flex en els propis elements <article>. Aquí cal tenir en compte la 2a regla; configurem el tercer element <article> de manera que els seus elements fills es disposin també com elements flexibles, però aquesta vegada en columna.

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}

A continuació, seleccionem el primer element <div>. Utilitzem la declaració flex: 1 100px; perquè hi doni efectivament una alçada mínima de 100px, aleshores en configurem els elements fills (els elements <button>) perquè també siguin elements flexibles. Els distribuïm en fila perquè ocupin tot l’espai amb la propietat wrap i els alineem al centre de l'espai disponible, com hem fet en l'exemple del botó individual que hem vist abans.

article:nth-of-type(3) div:first-child {
  flex: 1 100px;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-around;
}

Finalment, establim les dimensions del botó, però la qüestió interessant és que hi donem un valor de flex de 1. Això té un efecte molt interessant, que pots observar si canvies la mida de l'amplada de la finestra del navegador. Els botons ocuparan tant d’espai com puguin i es disposaran sobre la mateixa línia tant com sigui possible, però quan ja no càpiguen amb comoditat a la mateixa línia, cauran a la línia següent.

button {
  flex: 1;
  margin: 5px;
  font-size: 18px;
  line-height: 1.5;
}

Compatibilitat amb altres navegadors

Flexbox és compatible amb la majoria de navegadors nous: Firefox, Chrome, Opera, Microsoft Edge i IE 11, i les versions més noves d'Android/iOS, etc. No obstant això, cal tenir en compte que encara hi ha navegadors antics en ús que no admeten Flexbox (o bé n’admeten una versió antiga i desactualitzada).

Mentre ets en procés d’aprendre i experimentar, això no importa gaire; però si consideres l'ús de flexbox en un lloc web real, has de fer proves i assegurar-te que la teva experiència d'usuari continua sent acceptable en el màxim nombre de navegadors possible.

Flexbox és una mica més complicat que altres característiques CSS. Per exemple, si un navegador no té ombres CSS, probablement el lloc web serà encara usable. En canvi, la no-compatibilitat amb les característiques de flexbox probablement trencarà del tot el disseny i inutilitzarà el lloc web.

En un altre mòdul parlarem de les estratègies per a superar els complexos problemes de compatibilitat dels navegadors.

Posa a prova les teves habilitats

Hem vist moltes coses en aquest article. En recordes la informació més important? Trobaràs més tests per poder comprovar si has retingut la informació abans de seguir a Test your skills: Flexbox.

Resum

Això clou el nostre recorregut pels fonaments de flexbox. Esperem que t’hagis divertit i que sàpigues jugar-hi mentre continues endavant amb el teu aprenentatge. A continuació, veurem un altre aspecte important dels dissenys CSS, els sistemes de graella.