Amžinas klausimas: Grid ar Flexbox?
Kiekvienas frontend kūrėjas anksčiau ar vėliau susiduria su šiuo klausimu. Sėdi prie naujo projekto, žiūri į dizainerio maketus ir galvoji – kurį layout metodą šįkart rinktis? CSS Grid ir Flexbox jau seniai tapo standartiniais įrankiais, bet vis dar matau forumuose ir Discord serveriuose besikartojančius klausimus apie tai, kada naudoti vieną, o kada kitą.
Tiesą sakant, abu šie metodai nėra konkurentai – jie greičiau papildo vienas kitą. Problema ta, kad daugelis kūrėjų įsitvirtina vienoje pusėje ir stengiasi viską daryti tik su Flexbox arba tik su Grid. O realybė tokia, kad geriausi rezultatai pasiekiami derinant abu metodus protingai.
Šiame straipsnyje nenagrinėsiu bazinės sintaksės – internete pilna tutorialų apie tai, kaip veikia display: flex ar grid-template-columns. Vietoj to pasidalinsiu praktine patirtimi, kada kuris metodas tikrai praverčia, ir kaip juos derinti realiuose projektuose.
Flexbox – vienmatis galvojimas
Flexbox buvo sukurtas spręsti vienmatę problemą. Tai reiškia, kad jis puikiai tvarko elementus vienoje ašyje – arba horizontaliai, arba vertikaliai. Taip, galite turėti kelis flex eilutes su flex-wrap: wrap, bet pagrindinis Flexbox stiprumas slypi būtent toje vienmatėje logikoje.
Praktiškai Flexbox yra idealus navigacijos meniu kūrimui. Turite kelis nuorodų elementus, kuriuos norite išdėstyti horizontaliai su tarpais tarp jų? Flexbox padaro tai per kelias sekundes. display: flex, gap: 1rem, ir jau turite veikiančią navigaciją. Norite vieną elementą stumdyti į dešinę pusę? margin-left: auto – ir problema išspręsta.
Dar viena situacija, kur Flexbox tikrai šviečia – vertikalus centravimas. Taip, žinau, kad tai skamba kaip memas, bet prieš Flexbox erą vertikalus centravimas buvo tikras košmaras. Dabar tiesiog display: flex, align-items: center, justify-content: center – ir jūsų elementas idealiai centruotas.
Komponentų viduje Flexbox taip pat neįkainojamas. Pavyzdžiui, kortelė su paveiksliuku kairėje ir tekstu dešinėje – klasikinis Flexbox use case. Arba forma su laukais, kurie turi būti išdėstyti vienoje eilutėje. Čia Flexbox leidžia elementams natūraliai prisitaikyti prie turinio dydžio.
Grid – dvimatis galvojimas ir tikroji galia
CSS Grid atėjo išspręsti tai, ko Flexbox negalėjo – dvimačius išdėstymus. Kai jums reikia kontroliuoti ir eilutes, ir stulpelius vienu metu, Grid yra vienintelis logiškas pasirinkimas.
Pagrindinė puslapio struktūra – header, sidebar, main content, footer – tai Grid teritorija. Galite apibrėžti visą layout’ą keliomis eilutėmis kodo naudojant grid-template-areas. Tai ne tik funkcionalus, bet ir itin skaitomas būdas:
.container {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
}
Pažiūrėjus į šį kodą, iš karto matote puslapio struktūrą. Tai neįtikėtinai patogu, kai grįžtate prie kodo po kelių mėnesių arba kai naujam komandos nariui reikia suprasti layout’ą.
Galerijos ir produktų tinkleliai – dar viena Grid stiprybė. Kai turite daug elementų, kuriuos norite išdėstyti tinkleliu su konkrečiu stulpelių skaičiumi, Grid su repeat() funkcija yra tobulas sprendimas. O auto-fit ir auto-fill su minmax() leidžia sukurti tikrai responsive tinklelius be media queries.
Pavyzdžiui, šis kodas sukuria tinklelį, kuris automatiškai prisitaiko prie ekrano pločio:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}
Elementai automatiškai persidėsto į naują eilutę, kai nebėra vietos, ir kiekvienas užima vienodą plotį. Be jokių media queries!
Kada tikrai reikia Grid, o ne Flexbox
Yra situacijų, kur bandymas naudoti Flexbox vietoj Grid tiesiog sukuria nereikalingą skausmą. Išmokau tai sunkiu būdu, kai prieš kelerius metus bandžiau sukurti sudėtingą dashboard layout’ą tik su Flexbox. Veikė, bet kodas buvo baisus – įdėti flex containeriai, keistos margin manipuliacijos, ir absoliučiai nesuprantama struktūra.
Kai jūsų layout’as turi aiškią tinklelio struktūrą, naudokite Grid. Jei dizaineris jums atsiuntė maketą su aiškiomis kolonėmis ir eilutėmis, tai Grid signalas. Jei elementai turi būti sulygiuoti ir horizontaliai, ir vertikaliai su kitais elementais skirtingose eilutėse – Grid.
Ypač svarbu naudoti Grid, kai elementai turi užimti kelis stulpelius ar eilutes. Flexbox tai padaryti negali natūraliai. Pavyzdžiui, jei turite galerijos tinklelį, kur kai kurie paveikslėliai turi būti dvigubai didesni ir užimti du stulpelius – tai Grid darbas su grid-column: span 2.
Dar vienas dalykas – kai jums reikia, kad elementai skirtingose eilutėse būtų vienodo pločio. Flexbox kiekvieną eilutę traktuoja atskirai, todėl elementai skirtingose eilutėse gali būti skirtingo pločio. Grid leidžia apibrėžti stulpelių pločius visam tinkleliui, todėl viskas lieka sulygiuota.
Kada Flexbox yra geresnis pasirinkimas
Nors Grid yra galingas, Flexbox vis dar laimi daugeliu atvejų dėl savo paprastumo ir intuicijos. Kai turite mažą komponentų grupę, kurią norite išdėstyti vienoje kryptyje, Flexbox yra greitesnis ir paprastesnis sprendimas.
Navigacijos meniu, mygtukų grupės, breadcrumbs, tag’ai – visa tai Flexbox teritorija. Kodėl? Nes šie elementai natūraliai yra vienmačiai. Jums tiesiog reikia išdėstyti juos eilėje su tarpais, ir galbūt kai kuriuos stumdyti į šonus. Grid čia būtų overkill.
Formos taip pat dažnai geriau veikia su Flexbox. Label ir input laukas šalia vienas kito? Flexbox. Mygtukai formos apačioje, išdėstyti horizontaliai? Flexbox. Žinoma, visa forma gali būti Grid, bet atskiri formos elementai viduje dažniausiai geriau veikia su Flexbox.
Kai turinys diktuoja dydį, Flexbox yra natūralesnis pasirinkimas. Jei elementai turi prisitaikyti prie savo turinio dydžio, o ne prie griežtos tinklelio struktūros, Flexbox flex-grow ir flex-shrink savybės leidžia tai padaryti elegantiškai.
Derinimas – kur tikroji magija vyksta
Realybėje daugelis projektų naudoja abu metodus kartu, ir tai yra visiškai normalu. Tipiškas pavyzdys: puslapio struktūra su Grid, o komponentai viduje su Flexbox.
Pavyzdžiui, galite turėti pagrindinį layout’ą su Grid:
.page-layout {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
O tada navigacija header’yje naudoja Flexbox:
.main-nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
}
Produktų sąrašas main content srityje? Grid:
.products {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
}
Bet kiekviena produkto kortelė viduje naudoja Flexbox savo elementams išdėstyti:
.product-card {
display: flex;
flex-direction: column;
gap: 1rem;
}
.product-actions {
display: flex;
gap: 0.5rem;
margin-top: auto;
}
Matote šabloną? Grid dideliems, struktūriniams dalykams; Flexbox mažiems, turinio diktuojamiems dalykams. Tai nėra griežta taisyklė, bet geras orientyras.
Performance ir praktiniai aspektai
Kalbant apie našumą, abu metodai yra labai efektyvūs. Šiuolaikiniai naršyklių varikliai puikiai optimizuoja ir Grid, ir Flexbox. Tačiau yra keletas niuansų, kuriuos verta žinoti.
Grid gali būti šiek tiek lėtesnis su labai sudėtingais layout’ais, turinčiais šimtus elementų. Tai vyksta todėl, kad Grid turi apskaičiuoti visą dvimačią struktūrą. Praktiškai tai retai būna problema, nebent kuriate kažką tikrai sudėtingo kaip spreadsheet aplikaciją.
Flexbox gali turėti problemų su nested flex containeriais. Jei turite daug įdėtų flex containerių, naršyklė turi perskaičiuoti layout’ą kelis kartus. Tai vadinama „layout thrashing” ir gali sulėtinti puslapį. Sprendimas – vengti pernelyg gilaus įdėjimo ir naudoti Grid, kur tai tinka.
Dar vienas praktinis aspektas – debugging. Chrome DevTools turi puikius įrankius ir Grid, ir Flexbox vizualizavimui. Galite įjungti Grid overlay, kuris parodo visas linijas ir sritis. Flexbox taip pat turi savo vizualizaciją. Naudokite šiuos įrankius – jie labai palengvina gyvenimą, kai kažkas neveikia taip, kaip tikėjotės.
Browser support šiandien nėra problema. Ir Grid, ir Flexbox palaiko visi šiuolaikiniai naršykliai. Jei vis dar turite palaikyti IE11 (mano užuojauta), Flexbox turi geresnę palaikymą, bet Grid taip pat veikia su kai kuriomis išlygomis. Autoprefixer paprastai pasirūpina dauguma suderinamumo problemų.
Klaidos, kurių venkite
Per metus mačiau daug klaidų, kurias kūrėjai daro su šiais layout metodais. Viena dažniausių – bandymas naudoti Flexbox visam, nes jis atrodo paprastesnis. Taip, Flexbox sintaksė gali atrodyti paprastesnė pradžioje, bet bandymas sukurti sudėtingą dvimačią struktūrą su Flexbox tampa košmaru.
Kita klaida – per daug specifinių dydžių. Kai naudojate Grid ar Flexbox, leiskite jiems daryti savo darbą. Venkite fiksuotų aukščių ir pločių, kur tik įmanoma. Naudokite fr vienetus Grid’e, flex-grow ir flex-shrink Flexbox’e. Leiskite layout’ui būti lankstam.
Trečia klaida – ignoravimas gap savybės. Anksčiau turėjome naudoti margin’us tarpams tarp elementų, bet dabar ir Grid, ir Flexbox palaiko gap. Tai daug švariau ir paprasčiau. Nereikia rūpintis neigiamais margin’ais ar :last-child selektoriais.
Dar vienas dalykas – nepamirškite apie min-width: 0 ir min-height: 0 Flexbox’e. Flex elementai pagal nutylėjimą turi min-width: auto, kas gali sukelti overflow problemas. Jei jūsų tekstas ar paveikslėliai išlenda iš konteinerio, pabandykite nustatyti min-width: 0 flex elementui.
Realūs pavyzdžiai ir sprendimai
Pasidalinsiu keliais realiais scenarijais iš savo praktikos, kurie puikiai iliustruoja, kada naudoti kurį metodą.
Scenarijus 1: Blog layout su sidebar
Pagrindinė struktūra – Grid. Turite header, sidebar, main content ir footer. Grid leidžia tai apibrėžti aiškiai ir suprantamai. Bet blog post’o viduje – paragrafai, paveikslėliai, citatos – tai viskas gali būti paprastas block layout arba Flexbox, jei reikia horizontalaus išdėstymo.
Scenarijus 2: Dashboard su widget’ais
Čia Grid tikrai šviečia. Galite sukurti tinklelį su grid-template-columns: repeat(12, 1fr) ir leisti widget’ams užimti skirtingą stulpelių skaičių. Vienas widget’as gali būti grid-column: span 4, kitas span 8. Viduje kiekvienas widget’as gali naudoti Flexbox savo turiniui.
Scenarijus 3: E-commerce produktų sąrašas
Produktų tinklelis – Grid su auto-fit ir minmax(). Bet kiekviena produkto kortelė viduje – Flexbox. Paveikslėlis viršuje, pavadinimas, kaina, mygtukai apačioje. flex-direction: column su margin-top: auto mygtukams stumti į apačią.
Scenarijus 4: Responsive navigacija
Desktop versijoje – Flexbox. Mobile versijoje, kai navigacija tampa vertikalia, vis tiek Flexbox, tik su flex-direction: column. Jei turite mega menu su submeniu tinkleliu, tada submeniu gali būti Grid, bet pagrindinis nav – Flexbox.
Kaip galvoti apie layout’us ateityje
Technologijos vystosi, ir CSS layout metodai taip pat. Jau matome naujus dalykus kaip Subgrid, kuris leidžia nested grid’ams paveldėti tėvo grid tracks. Container queries keičia žaidimą responsive dizaine. Bet Grid ir Flexbox pagrindai išliks aktualūs.
Geriausia strategija – suprasti kiekvieno metodo stiprybes ir trūkumus. Negalvokite apie tai kaip „Grid prieš Flexbox”, galvokite „Grid ir Flexbox”. Jie yra įrankiai jūsų arsenale, ir kaip bet kurie įrankiai, kiekvienas turi savo paskirtį.
Kai pradedate naują projektą, pirmiausia pagalvokite apie bendrą struktūrą. Ar tai dvimatis layout’as su aiškiomis eilutėmis ir stulpeliais? Grid. Ar tai vienmatis komponentų išdėstymas? Flexbox. Dažniausiai atsakymas bus – abu, skirtinguose lygiuose.
Praktikuokitės su abiem metodais. Sukurkite projektus, kur tyčia naudojate vieną ar kitą metodą. Pabandykite atkurti sudėtingus layout’us iš populiarių svetainių. Tai padės jums intuityviai suprasti, kuris metodas kada tinka.
Ir svarbiausia – nebijokite eksperimentuoti. CSS layout’ai nebėra statiniai dalykai. Galite greitai pakeisti iš Flexbox į Grid ir atvirkščiai. Jei kažkas neveikia arba atrodo per sudėtinga, galbūt naudojate netinkamą įrankį. Pabandykite kitą metodą – dažnai tai išsprendžia problemą iš karto.
Ateityje, kai mokysitės naujų CSS funkcijų, jau turėsite tvirtą pagrindą. Subgrid, container queries, aspect-ratio – visi šie dalykai stato ant Grid ir Flexbox pagrindų. Suprasdami šiuos pagrindinius metodus, lengvai įsisavinsite ir naujoves.
