Tutorial Flexbox și Sass Grid: Cum să eficientizați designul receptiv

Publicat: 2022-03-11

Recent, am fost provocată să îmi creez propriul sistem de grilă și, deoarece reinventarea roții este întotdeauna utilă ca experiență de învățare, am mers pe ea. Știam că va fi o provocare interesantă, dar am fost surprins de cât de ușor s-a dovedit a fi!

Tutorial Sass și Flexbox Grid

În acest experiment, vom analiza aspectele Flexbox și modul în care acestea permit implementări grațioase ale layout-urilor, fără a face hack-uri nebunești. De asemenea, dacă nu sunteți familiarizat cu Sass, vom vedea cum funcționează și vom folosi câteva utilitare Sass la îndemână. S-ar putea chiar să înveți ceva nou despre grilele CSS, cum ar fi cea care face parte din Bootstrap.

O foarte scurtă introducere a Sass și Flexbox

Sass este practic un instrument care vă permite să evitați unele dintre deficiențele CSS, este un limbaj de scripting care este interpretat în CSS. Sintaxa pare foarte familiară dacă scrieți deja stiluri CSS, dar setul de instrumente include variabile, mixuri pentru reutilizare și directive if, for, fiecare și while, printre altele. Unul dintre cele mai utile lucruri despre Sass este că orice cod CSS valid este Sass valid, astfel încât să vă puteți transforma progresiv baza de cod.

Un exemplu simplu de buclă for:

 @for $i from 1 through 3 { .a-numbered-class-#{$i} { width: (20 * $i) * 1px; } }

Această buclă simplă iterează de la 1 la 3 și creează clase. Indicele iterației va fi stocat ușor în $i . De asemenea, putem face matematică și imprima .a-numbered-class-X trei ori cu o lățime diferită de fiecare dată. Acest cod iese:

 .a-numbered-class-1 { width: 20px; } .a-numbered-class-2 { width: 40px; } .a-numbered-class-3 { width: 60px; }

După cum putem vedea, putem abstra o mulțime din munca pe care ar trebui să o faceți în CSS. În CSS, ar trebui să copiați, să lipiți și să modificați manual, ceea ce este evident mai predispus la erori și mai puțin elegant. Dacă nu ați încercat încă, nu mai pierdeți timpul!

Flexbox înseamnă Flexible Box, un sistem de aspect CSS3 care poziționează și distribuie elementele în mod dinamic. Este un instrument foarte puternic care permite machete flexibile cu efort minim. Pentru mai multe detalii despre cum să învățați Flexbox, consultați Ghidul complet al lui Chris Coyier pentru Flexbox.

Grila

Trecând la grila în sine, să începem cu elementele sale de bază. Acestea vor fi inspirate de elementele grilei Bootstrap: Containers, Rows și Columns, fiecare conținut în primul.

Vom folosi convențiile de denumire BEM pentru numele claselor. Convențiile BEM sunt destul de simplu de utilizat și adaugă multe informații despre element și contextul acestuia. Pe scurt, aveți:

  • Blocuri , care „încapsulează o entitate independentă care are sens în sine”: .block .
  • Elemente , care sunt „părți ale unui bloc și nu au o semnificație independentă”, care sunt notate prin numele blocului, două liniuțe de subliniere și elementul: .block__elem
  • Modificatori , cum ar fi „Flags on blocks or elements”, care sunt reprezentați cu două liniuțe: .block .block--mod .

Containere, rânduri și coloane

Containere

Acesta este elementul cel mai exterior al grilei, va conține elementele noastre de rând. Există două tipuri de recipiente: .container și .container--fluid .

Comportamentul .container este definit prin a fi 100% din lățimea sub un anumit punct, având o lățime maximă fixă ​​deasupra acestuia și având margini egale la stânga și la dreapta:

 $grid__bp-md: 768; .container { max-width: $grid__bp-md * 1px; margin: 0 auto; }

Joacă-te cu el aici extinzând și contractând fereastra de „ieșire”.

Pentru containerul de fluid, care are întotdeauna 100% lățime, pur și simplu înlocuim acele proprietăți cu un modificator:

 &--fluid { margin: 0; max-width: 100%; }

Joacă-te cu el aici.

A fost ușor! Acum avem ambele containere implementate. Să trecem la următorul element.

Rânduri

Rândurile vor fi organizatorii orizontali ai conținutului nostru.

Vom folosi Flexbox pentru a poziționa elementele copil ale unui rând, făcându-le înfășurate astfel încât să nu se debordeze și oferindu-le 100% lățime în interiorul rândului (pentru a le putea cuibă mai târziu).

 &__row { display: flex; flex-wrap: wrap; width: 100%; }

Acest lucru va poziționa elementele copil unul lângă altul și le va înfășura în linii noi dacă suma lățimii lor este mai mare decât ea însăși. Acum trebuie doar să adăugăm câteva div-uri și va arăta astfel:

Elemente de rând

Joacă-te cu el aici extinzând și contractând fereastra de „ieșire”.

Lucrurile încep să prindă contur, dar aceasta nu este încă o grilă CSS. Lipsește…

Coloane

Coloanele sunt locul unde se află conținutul site-ului. Ele definesc în câte părți este împărțit rândul și cât ocupă. Vom face un aspect cu douăsprezece coloane. Aceasta înseamnă că putem împărți rândul în una sau până la douăsprezece părți.

Pentru început, niște matematică de bază. Când dorim să avem o coloană, lățimea acesteia ar trebui să fie de 100%. Dacă vrem douăsprezece coloane. Apoi fiecare ar trebui să ocupe 8,333...% sau 100/12 din lățime.

Cu Flexbox, pentru a distribui conținutul în acest mod, putem folosi flex-basis .

Pentru a împărți în patru coloane, acum am adăuga ceva de genul:

 flex-basis: (100 / 4 ) * 1%;

În acest fel, putem face ca elementele să ocupe fiecare 25% din lățime – sau orice procent dorim.

Joacă-te cu el aici.

Să facem asta mai dinamică. Deoarece dorim ca acest lucru să reflecte posibilele noastre clase, să numim .col-1 , o clasă pentru o coloană div care va avea 8,333% din lățime, deoarece douăsprezece dintre ele ar trebui să se potrivească înainte de a trebui să se încadreze la o nouă linie. Procentul va crește pe tot parcursul până la .col-12 , care va ocupa 100%.

 $grid__cols: 12; @for $i from 1 through $grid__cols { .col-#{$i} { flex-basis: (100 / ($grid__cols / $i) ) * 1%; } }

Doar pentru a clarifica ce se întâmplă, să presupunem că vrem să împărțim lățimea în patru părți egale. Am avea nevoie .col-3 , deoarece se potrivește de 4 ori în 12, ceea ce înseamnă că .col-3 ar trebui să aibă o bază flexibilă de 25%:

 100 / ($grid__cols / $i) 100 / (12 / 3) = 25

Aceasta începe deja să arate ca o grilă!

Arată ca o grilă!

Joacă-te cu el aici.

Coloane dependente de lățimea ecranului

Acum vrem să putem avea un element care să aibă o anumită lățime pe mobil dar una diferită pe tablete și așa mai departe. Vom folosi anumite puncte de întrerupere în funcție de lățimea ferestrei. Interfața noastră de utilizare va reacționa la aceste puncte de întrerupere și se va adapta la un aspect ideal, adaptat dimensiunilor ecranului diferitelor dispozitive. Vom numi punctele de întrerupere după dimensiune: mic (sm), mediu (md) și așa mai departe, .col-sm-12 va fi un element care ocupă cel puțin 12 coloane până la punctul de întrerupere sm .

Să redenumim clasa .col- .col-* .col-sm-* . Deoarece grila noastră va fi mai întâi mobilă, îi vom aplica proprietățile tuturor dimensiunilor de ecran. Pentru cele care trebuie să ne comportăm diferit cu ecrane mai mari, vom adăuga clasa: .col-md-* .

Imaginați-vă un element cu .col-sm-12 și .col-md-4 . Comportamentul așteptat va fi acela că sub punctul de întrerupere „md” (mediu) va avea 100% lățime, iar deasupra acestuia va avea 33,333% - o apariție foarte comună, deoarece pe mobil ar putea fi necesar să stivuiți elemente deasupra, mai degrabă decât lângă unul pe altul când lățimea ta este mult mai limitată.

Stivuirea coloanelor după atingerea unui punct de întrerupere

Pentru aceasta, va trebui să adăugăm o interogare media (o expresie care conține cod care se va executa numai deasupra sau sub o anumită lățime sau pe un anumit dispozitiv) la punctul de întrerupere și să creăm coloanele noastre md așa cum am făcut înainte pentru sm :

 @media screen and (min-width: $grid__bp-md * 1px) { @for $i from 1 through $grid__cols { &__col-md-#{$i} { flex-basis: (100 / ($grid__cols / $i) ) * 1%; } } }

Joacă-te cu el aici.

Se apropie deja de ceva util. Este destul de umed (înțelegi? Nu este USCAT…), așa că haideți să o facem mai abstractă.

După cum am văzut, vom avea nevoie de o interogare media pentru fiecare punct de întrerupere, așa că haideți să creăm un mixin care primește un punct de întrerupere care creează dinamic interogări media. Ar putea arata cam asa:

 @mixin create-mq($breakpoint) { @if($breakpoint == 0) { @content; } @else { @media screen and (min-width: $breakpoint *1px) { @content; } } }

Acum, să includem ceea ce aveam pentru a crea clasele __col într-un mixin numit create-col-classes și să folosim mixin-ul create-mq .

 @mixin create-col-classes($modifier, $grid__cols, $breakpoint) { @include create-mq($breakpoint) { @for $i from 1 through $grid__cols { &__col#{$modifier}-#{$i} { flex-basis: (100 / ($grid__cols / $i) ) * 1%; } } } }

Si asta e. Pentru a-l folosi, definim acum punctele noastre de întrerupere într-o hartă Sass și le repetăm.

 $map-grid-props: ('-sm': 0, '-md': $grid__bp-md, '-lg': $grid__bp-lg); @each $modifier , $breakpoint in $map-grid-props { @include create-col-classes($modifier, $grid__cols, $breakpoint); }

Sistemul nostru de rețea este practic gata! Am definit o .container__col-sm-* care va fi implicită și îi putem modifica comportamentul pe ecrane mai mari cu container__col-md-* și container__col-lg-* .

Putem chiar cuibari rânduri! Joacă-te cu el aici.

Lucrul frumos este că, dacă am dori acum să aibă aceleași puncte de întrerupere ca Bootstrap v4, ar trebui doar să facem:

 $grid__bp-sm: 576; $grid__bp-md: 768; $grid__bp-lg: 992; $grid__bp-xl: 1200; $map-grid-props: ( '': 0, '-sm': $grid__bp-sm, '-md': $grid__bp-md, '-lg': $grid__bp-lg, '-xl': $grid__bp-xl );

Si asta e! Joacă-te cu el aici.

Observați cum Bootstrap adoptă o abordare mai completă, pe mobil, mai întâi decât am discutat inițial. Cele mai mici dimensiuni de fereastră nu au sufix precum sm sau md , raționamentul fiind că clasa echivalentă cu .container__col-X nu va fi aplicată doar de la o lățime a ferestrei de la 0 la 576px; dacă nu îl suprascriem în mod explicit, va fi acel număr de coloane la fiecare dimensiune de fereastră. În caz contrar, am putea adăuga clasa .container__col-sm-Y pentru a face din aceasta o lățime de coloane Y între punctele de întrerupere sm .

Compensare

Compensațiile vor adăuga o marjă rămasă față de coloana anterioară. Un .container__col-offset-4 va adăuga o margin-left: 33.333% pe toate dimensiunile de ecran. .container__col-md-offset-4 va face același lucru, dar deasupra punctului de întrerupere md .

Implementarea este acum banala; adăugăm o proprietate -offset pe aceeași buclă în care creăm clasele, dar în loc de flex-bases , scriem proprietatea margin-left . Trebuie să facem unul suplimentar și pentru -offset-0 , deoarece este posibil să dorim să ștergem marja pe ecrane mai mari:

 @mixin create-col-classes($modifier, $grid-cols, $breakpoint) { @include create-mq($breakpoint) { &__col#{$modifier}-offset-0 { margin-left: 0; } @for $i from 1 through $grid-cols { &__col#{$modifier}-#{$i} { flex-basis: (100 / ($grid-cols / $i) ) * 1%; } &__col#{$modifier}-offset-#{$i} { margin-left: (100 / ($grid-cols / $i) ) * 1%; } } } }

Acum avem compensații complet funcționale! Joacă-te cu el aici.

Posibilitate de afișare

Uneori vrem să afișăm/ascundem un element sub sau deasupra unui anumit punct. Pentru aceasta, putem face disponibile clase precum cele din Bootstrap v4.

De exemplu, clasa .hidden-md-up va ascunde orice element cu această clasă de la punctul de întrerupere md în sus; invers, .hidden-md-down îl va ascunde de la punctul de întrerupere în jos.

Codul pentru acest lucru este din nou simplu: ne repetăm ​​punctele de întrerupere și creăm o clasă .hidden-* cu un for each punct de întrerupere. Totuși, am modificat clasa create-mq pentru a fi puțin mai abstractă:

 @each $modifier , $breakpoint in $map-grid-props { @if($modifier == '') { $modifier: '-xs'; } @include create-mq($breakpoint - 1, 'max') { .hidden#{$modifier}-down { display: none !important; } } @include create-mq($breakpoint, 'min') { .hidden#{$modifier}-up { display: none !important; } } }

Ca o notă secundară, nu este aceasta una dintre puținele utilizări bune pentru !important ? Observați că elementul poate avea o specificitate arbitrar mai mare cu o regulă display: block , dar am dori totuși să-l ascundem sub sau deasupra punctului de întrerupere. Dacă nu sunteți de acord cu această abordare, spuneți-mi în comentarii!

Deci, asta este: acum avem un sistem de afișare.

Joacă-te cu el aici.

Concluzie

Deși acest „cadru” nu este pregătit pentru producție, arată cât de puternice pot fi layout-urile Flexbox și cât de util este Sass. Cu doar câteva linii de cod, am implementat funcționalitatea de bază a unui cadru/grilă CSS.

Fie ca acesta să servească și ca o lecție că o versiune de bază a practic oricărui software poate fi implementată foarte ușor. Problemele concrete ale lumii reale încep să se adună și o îngreunează.

Am creat un depozit GitHub unde puteți trimite probleme sau solicită solicitări.

Ce caracteristici ați dori să vedeți implementate? Ar putea fi implementarea simplificată sau mai elegantă?

Simțiți-vă liber să-mi spuneți părerea dvs. în comentariile de mai jos.