Atskleiskite CSS Flexbox galią suprasdami jo vidinį dydžio nustatymo algoritmą. Šis išsamus gidas aiškina turiniu paremtą dydį, flex-basis, grow, shrink ir maketavimo iššūkius.
Flexbox dydžio nustatymo algoritmo paslaptys: išsami, turiniu paremtų maketų analizė
Ar kada nors naudojote flex: 1
elementų rinkiniui, tikėdamiesi gauti tobulai vienodus stulpelius, tačiau pastebėjote, kad jų dydžiai vis tiek skiriasi? O gal teko vargti su „flex“ elementu, kuris atkakliai atsisako susitraukti, sukeldamas bjaurų perpildymą (overflow), kuris sugadina jūsų dizainą? Šios dažnos problemos programuotojus dažnai priverčia spėlioti ir atsitiktinai keisti savybes. Tačiau sprendimas nėra magija – tai logika.
Atsakymas į šias mįsles slypi giliai CSS specifikacijoje, procese, žinomame kaip Flexbox vidinio dydžio nustatymo algoritmas. Tai galingas, turinį atpažįstantis variklis, kuris valdo „Flexbox“, tačiau jo vidinė logika dažnai gali atrodyti kaip nepermatoma juoda dėžė. Šio algoritmo supratimas yra raktas į „Flexbox“ įvaldymą ir tikrai nuspėjamų, atsparių vartotojo sąsajų kūrimą.
Šis gidas skirtas programuotojams visame pasaulyje, kurie nori pereiti nuo „bandymų ir klaidų“ metodo prie „sąmoningo dizaino“ su „Flexbox“. Mes žingsnis po žingsnio išnarstysime šį galingą algoritmą, paversdami sumaištį aiškumu ir suteikdami jums galimybę kurti tvirtesnius ir globaliai pritaikytus maketus, kurie veiktų su bet kokiu turiniu, bet kuria kalba.
Ne tik fiksuoti pikseliai: vidinio ir išorinio dydžio nustatymo supratimas
Prieš gilinantis į patį algoritmą, labai svarbu suprasti pagrindinę CSS maketavimo koncepciją: skirtumą tarp vidinio ir išorinio dydžio nustatymo.
- Išorinis dydžio nustatymas (Extrinsic Sizing): Tai yra tada, kai jūs, programuotojas, aiškiai nurodote elemento dydį. Savybės, tokios kaip
width: 500px
,height: 50%
arbawidth: 30rem
, yra išorinio dydžio nustatymo pavyzdžiai. Dydį lemia veiksniai, esantys už elemento turinio ribų. - Vidinis dydžio nustatymas (Intrinsic Sizing): Tai yra tada, kai naršyklė apskaičiuoja elemento dydį pagal jame esantį turinį. Mygtukas, kuris natūraliai platėja, kad tilptų ilgesnis tekstas, naudoja vidinį dydžio nustatymą. Dydį lemia veiksniai, esantys elemento viduje.
„Flexbox“ yra vidinio, turiniu paremto dydžio nustatymo meistras. Nors jūs pateikiate taisykles („flex“ savybes), galutinius dydžio sprendimus naršyklė priima atsižvelgdama į „flex“ elementų turinį ir konteineryje esančią erdvę. Būtent tai daro jį tokiu galingu kuriant lanksčius, adaptyvius dizainus.
Trys lankstumo ramsčiai: flex-basis
, flex-grow
ir flex-shrink
priminimas
„Flexbox“ algoritmo sprendimus daugiausia lemia trys savybės, dažnai nustatomos kartu naudojant flex
trumpinį. Norint suprasti tolesnius žingsnius, būtina tvirtai jas išmanyti.
1. flex-basis
: pradinė pozicija
Pagalvokite apie flex-basis
kaip apie idealų arba „hipotetinį“ pradinį „flex“ elemento dydį pagrindinėje ašyje, prieš jam pradedant didėti ar mažėti. Tai yra bazinė linija, nuo kurios atliekami visi kiti skaičiavimai.
- Tai gali būti ilgio vienetas (pvz.,
100px
,10rem
) arba procentas (25%
). - Numatytoji vertė yra
auto
. Kai nustatytaauto
, naršyklė pirmiausia žiūri į elemento pagrindinio dydžio savybę (width
horizontaliame „flex“ konteineryje,height
vertikaliame). - Štai esminis ryšys: Jei pagrindinio dydžio savybė taip pat yra
auto
,flex-basis
nustatomas pagal elemento vidinį, turiniu paremtą dydį. Būtent taip pats turinys nuo pat pradžių gauna „balsą“ dydžio nustatymo procese. - Taip pat galima naudoti vertę
content
, kuri aiškiai nurodo naršyklei naudoti vidinį dydį.
2. flex-grow
: teigiamos erdvės užėmimas
flex-grow
savybė yra bematis skaičius, kuris nurodo, kiek teigiamos laisvos vietos „flex“ konteineryje elementas turėtų užimti, palyginti su kitais elementais. Teigiama laisva vieta atsiranda, kai „flex“ konteineris yra didesnis už visų jame esančių elementų flex-basis
verčių sumą.
- Numatytoji vertė yra
0
, o tai reiškia, kad elementai pagal numatytuosius nustatymus nedidės. - Jei visi elementai turi
flex-grow: 1
, likusi erdvė paskirstoma tarp jų po lygiai. - Jei vienas elementas turi
flex-grow: 2
, o kiti –flex-grow: 1
, pirmasis elementas gaus dvigubai daugiau laisvos vietos nei kiti.
3. flex-shrink
: neigiamos erdvės atidavimas
Savybė flex-shrink
yra flex-grow
atitikmuo. Tai bematis skaičius, nurodantis, kaip elementas atiduoda erdvę, kai konteineris yra per mažas, kad tilptų visų jo elementų flex-basis
. Tai dažnai yra labiausiai nesuprantama iš šių trijų savybių.
- Numatytoji vertė yra
1
, o tai reiškia, kad elementams leidžiama susitraukti, jei reikia. - Dažnai klaidingai manoma, kad
flex-shrink: 2
priverčia elementą susitraukti „dvigubai greičiau“ paprasta prasme. Iš tikrųjų viskas sudėtingiau: dydis, kuriuo elementas susitraukia, yra proporcingas joflex-shrink
koeficientui, padaugintam iš joflex-basis
. Šią svarbią detalę vėliau išnagrinėsime praktiniame pavyzdyje.
„Flexbox“ dydžio nustatymo algoritmas: nuoseklus suskirstymas
Dabar atidengkime uždangą ir pereikime per naršyklės mąstymo procesą. Nors oficiali W3C specifikacija yra labai techniška ir tiksli, pagrindinę logiką galime supaprastinti į lengviau virškinamą, nuoseklų modelį vienai „flex“ eilutei.
1 žingsnis: Nustatykite „Flex“ bazinius dydžius ir hipotetinius pagrindinius dydžius
Pirma, naršyklei reikia atskaitos taško kiekvienam elementui. Ji apskaičiuoja kiekvieno elemento konteineryje „flex“ bazinį dydį. Tai daugiausia priklauso nuo apskaičiuotos flex-basis
savybės vertės. Šis „flex“ bazinis dydis tampa elemento „hipotetiniu pagrindiniu dydžiu“ kitiems žingsniams. Tai yra dydis, kokio elementas *norėtų* būti prieš bet kokias derybas su kaimyniniais elementais.
2 žingsnis: Nustatykite „Flex“ konteinerio pagrindinį dydį
Toliau naršyklė išsiaiškina paties „flex“ konteinerio dydį jo pagrindinėje ašyje. Tai gali būti fiksuotas plotis iš jūsų CSS, procentinė dalis nuo tėvinio elemento, arba jo dydis gali būti nustatytas vidiniu būdu pagal jo paties turinį. Šis galutinis, apibrėžtas dydis yra erdvės „biudžetas“, su kuriuo turi dirbti „flex“ elementai.
3 žingsnis: Surinkite „Flex“ elementus į „Flex“ eilutes
Tada naršyklė nustato, kaip sugrupuoti elementus. Jei nustatyta flex-wrap: nowrap
(numatytoji vertė), visi elementai laikomi vienos eilutės dalimi. Jei aktyvuota flex-wrap: wrap
arba wrap-reverse
, naršyklė paskirsto elementus per vieną ar daugiau eilučių. Likusi algoritmo dalis taikoma kiekvienai elementų eilutei atskirai.
4 žingsnis: Apskaičiuokite lanksčius ilgius (pagrindinė logika)
Tai yra algoritmo šerdis, kur vyksta faktinis dydžio nustatymas ir paskirstymas. Tai dviejų dalių procesas.
4a dalis: Apskaičiuokite laisvą erdvę
Naršyklė apskaičiuoja bendrą laisvą erdvę „flex“ eilutėje. Ji tai daro atimdama visų elementų „flex“ bazinių dydžių sumą (iš 1 žingsnio) iš konteinerio pagrindinio dydžio (iš 2 žingsnio).
Laisva erdvė = Konteinerio pagrindinis dydis - Visų elementų „flex“ bazinių dydžių suma
Šis rezultatas gali būti:
- Teigiamas: Konteineryje yra daugiau vietos, nei reikia elementams. Ši papildoma erdvė bus paskirstyta naudojant
flex-grow
. - Neigiamas: Elementai kartu yra didesni už konteinerį. Šis erdvės trūkumas (perpildymas) reiškia, kad elementai turi susitraukti pagal savo
flex-shrink
vertes. - Nulinis: Elementai telpa tobulai. Nereikia nei didinti, nei mažinti.
4b dalis: Paskirstykite laisvą erdvę
Dabar naršyklė paskirsto apskaičiuotą laisvą erdvę. Tai iteracinis procesas, tačiau logiką galime apibendrinti:
- Jei laisva erdvė yra teigiama (didėjimas):
- Naršyklė susumuoja visų elementų eilutėje
flex-grow
koeficientus. - Tada ji proporcingai paskirsto teigiamą laisvą erdvę kiekvienam elementui. Erdvės kiekis, kurį gauna elementas, yra:
(Elemento flex-grow / Visų flex-grow koeficientų suma) * Teigiama laisva erdvė
. - Galutinis elemento dydis yra jo
flex-basis
plius jam skirta paskirstytos erdvės dalis. Šį didėjimą riboja elementomax-width
arbamax-height
savybė.
- Naršyklė susumuoja visų elementų eilutėje
- Jei laisva erdvė yra neigiama (mažėjimas):
- Tai yra sudėtingesnė dalis. Kiekvienam elementui naršyklė apskaičiuoja pasvertą susitraukimo koeficientą, padaugindama jo „flex“ bazinį dydį iš jo
flex-shrink
vertės:Pasvertas susitraukimo koeficientas = „Flex“ bazinis dydis * flex-shrink
. - Tada ji susumuoja visus šiuos pasvertus susitraukimo koeficientus.
- Neigiama erdvė (perpildymo dydis) paskirstoma kiekvienam elementui proporcingai, atsižvelgiant į šį pasvertą koeficientą. Dydis, kuriuo elementas susitraukia, yra:
(Elemento pasvertas susitraukimo koeficientas / Visų pasvertų susitraukimo koeficientų suma) * Neigiama laisva erdvė
. - Galutinis elemento dydis yra jo
flex-basis
atėmus jam skirtą paskirstytos neigiamos erdvės dalį. Šį susitraukimą riboja elementomin-width
arbamin-height
savybė, kuri, svarbiausia, pagal nutylėjimą yraauto
.
- Tai yra sudėtingesnė dalis. Kiekvienam elementui naršyklė apskaičiuoja pasvertą susitraukimo koeficientą, padaugindama jo „flex“ bazinį dydį iš jo
5 žingsnis: Lygiavimas pagal pagrindinę ašį
Kai nustatomi galutiniai visų elementų dydžiai, naršyklė naudoja justify-content
savybę, kad išlygiuotų elementus pagal pagrindinę ašį konteineryje. Tai įvyksta *po to*, kai baigiami visi dydžio skaičiavimai.
Praktiniai scenarijai: nuo teorijos iki realybės
Suprasti teoriją yra viena, o pamatyti ją veikiant – sustiprina žinias. Panagrinėkime keletą įprastų scenarijų, kuriuos dabar lengva paaiškinti, remiantis mūsų algoritmo supratimu.
1 scenarijus: Tikri vienodo pločio stulpeliai ir flex: 1
trumpinys
Problema: Jūs pritaikote flex-grow: 1
visiems elementams, bet jų pločiai galiausiai nebūna vienodi.
Paaiškinimas: Taip atsitinka, kai naudojate trumpinį, pvz., flex: auto
(kuris išsiplečia į flex: 1 1 auto
), arba tiesiog nustatote flex-grow: 1
, palikdami flex-basis
su numatytąja auto
verte. Pagal algoritmą, flex-basis: auto
apskaičiuojamas pagal elemento turinio dydį. Taigi, elementas su daugiau turinio pradeda nuo didesnio „flex“ bazinio dydžio. Nors likusi laisva erdvė paskirstoma po lygiai, galutiniai elementų dydžiai skirsis, nes jų pradiniai taškai buvo skirtingi.
Sprendimas: Naudokite trumpinį flex: 1
. Tai išsiplečia į flex: 1 1 0%
. Svarbiausia dalis yra flex-basis: 0%
. Tai priverčia kiekvieną elementą pradėti nuo hipotetinio bazinio dydžio 0. Visas konteinerio plotis tampa „teigiama laisva erdve“. Kadangi visi elementai turi flex-grow: 1
, visa ši erdvė paskirstoma tarp jų po lygiai, todėl gaunami tikrai vienodo pločio stulpeliai, nepriklausomai nuo jų turinio.
2 scenarijus: flex-shrink
proporcingumo galvosūkis
Problema: Turite du elementus, abu su flex-shrink: 1
, bet kai konteineris susitraukia, vienas elementas praranda daug daugiau pločio nei kitas.
Paaiškinimas: Tai puikus 4b žingsnio neigiamai erdvei pavyzdys. Susitraukimas priklauso ne tik nuo flex-shrink
koeficiento; jis yra pasvertas pagal elemento flex-basis
. Didesnis elementas turi daugiau „atiduoti“.
Apsvarstykime 500px pločio konteinerį su dviem elementais:
- Elementas A:
flex: 0 1 400px;
(400px bazinis dydis) - Elementas B:
flex: 0 1 200px;
(200px bazinis dydis)
Bendras bazinis dydis yra 600px, o tai yra 100px per daug konteineriui (100px neigiamos erdvės).
- Elemento A pasvertas susitraukimo koeficientas:
400px * 1 = 400
- Elemento B pasvertas susitraukimo koeficientas:
200px * 1 = 200
- Bendra pasvertų koeficientų suma:
400 + 200 = 600
Dabar paskirstykime 100px neigiamos erdvės:
- Elementas A susitraukia:
(400 / 600) * 100px = ~66.67px
- Elementas B susitraukia:
(200 / 600) * 100px = ~33.33px
Nors abu turėjo flex-shrink: 1
, didesnis elementas prarado dvigubai daugiau pločio, nes jo bazinis dydis buvo dvigubai didesnis. Algoritmas veikė tiksliai taip, kaip ir buvo sukurta.
3 scenarijus: Nesitraukiantis elementas ir min-width: 0
sprendimas
Problema: Turite elementą su ilga teksto eilute (pvz., URL) arba dideliu paveikslėliu, ir jis atsisako susitraukti mažiau nei tam tikras dydis, todėl išlipa iš konteinerio ribų.
Paaiškinimas: Prisiminkite, kad susitraukimo procesą riboja minimalus elemento dydis. Pagal numatytuosius nustatymus „flex“ elementai turi min-width: auto
. Elementui, kuriame yra tekstas ar paveikslėliai, ši auto
vertė apskaičiuojama pagal jo vidinį minimalų dydį. Tekstui tai dažnai yra ilgiausio neskaidomo žodžio ar eilutės plotis. „Flex“ algoritmas susitrauks elementą, bet sustos, kai pasieks šį apskaičiuotą minimalų plotį, o tai sukels perpildymą, jei vis dar nebus pakankamai vietos.
Sprendimas: Norėdami leisti elementui susitraukti mažiau nei jo vidinis turinio dydis, turite pakeisti šį numatytąjį elgesį. Dažniausias sprendimas yra pritaikyti min-width: 0
„flex“ elementui. Tai nurodo naršyklei: „Leidžiu tau sumažinti šį elementą iki nulio pločio, jei reikia“, taip išvengiant perpildymo.
Vidinio dydžio nustatymo esmė: min-content
ir max-content
Norėdami visiškai suprasti turiniu paremtą dydžio nustatymą, turime greitai apibrėžti du susijusius raktinius žodžius:
max-content
: Vidinis pageidaujamas elemento plotis. Tekstui tai yra plotis, kurį tekstas užimtų, jei turėtų begalinę erdvę ir niekada nereikėtų jo perkelti į kitą eilutę.min-content
: Vidinis minimalus elemento plotis. Tekstui tai yra ilgiausios neskaidomos eilutės (pvz., vieno ilgo žodžio) plotis. Tai mažiausias dydis, kurį jis gali pasiekti, neperpildydamas savo paties turinio.
Kai flex-basis
yra auto
, o elemento width
taip pat yra auto
, naršyklė iš esmės naudoja max-content
dydį kaip pradinį elemento „flex“ bazinį dydį. Būtent todėl elementai su daugiau turinio pradeda nuo didesnio dydžio, dar prieš „flex“ algoritmui pradedant skirstyti laisvą erdvę.
Globalios pasekmės ir našumas
Šis turiniu pagrįstas požiūris turi svarbių pasekmių pasaulinei auditorijai ir našumui jautrioms programoms.
Tarptautinimas (i18n) yra svarbus
Turiniu paremtas dydžio nustatymas yra dviašmenis kardas tarptautinėms svetainėms. Viena vertus, tai fantastiška galimybė leisti maketams prisitaikyti prie skirtingų kalbų, kur mygtukų etiketės ir antraštės gali labai skirtis ilgiu. Kita vertus, tai gali sukelti netikėtų maketo lūžių.
Pavyzdžiui, vokiečių kalba garsėja ilgais sudurtiniais žodžiais. Žodis kaip „Donaudampfschifffahrtsgesellschaftskapitän“ žymiai padidina elemento min-content
dydį. Jei šis elementas yra „flex“ elementas, jis gali priešintis susitraukimui taip, kaip nesitikėjote, kai kūrėte maketą su trumpesniu anglišku tekstu. Panašiai, kai kurios kalbos, pavyzdžiui, japonų ar kinų, gali neturėti tarpų tarp žodžių, o tai turi įtakos, kaip skaičiuojamas žodžių kėlimas ir dydžio nustatymas. Tai puikus pavyzdys, kodėl vidinio algoritmo supratimas yra labai svarbus kuriant maketus, kurie būtų pakankamai tvirti, kad veiktų visiems ir visur.
Našumo pastabos
Kadangi naršyklei reikia išmatuoti „flex“ elementų turinį, kad apskaičiuotų jų vidinius dydžius, tai turi skaičiavimo kainą. Daugumai svetainių ir programų ši kaina yra nereikšminga ir neverta jaudintis. Tačiau labai sudėtingose, giliai įdėtose vartotojo sąsajose su tūkstančiais elementų šie maketo skaičiavimai gali tapti našumo kliūtimi. Tokiais pažangiais atvejais programuotojai gali tyrinėti CSS savybes, tokias kaip contain: layout
ar content-visibility
, kad optimizuotų atvaizdavimo našumą, bet tai jau kitos dienos tema.
Praktinės įžvalgos: jūsų „Flexbox“ dydžio nustatymo atmintinė
Apibendrinant, štai pagrindinės išvados, kurias galite pritaikyti nedelsiant:
- Norėdami gauti tikrai vienodo pločio stulpelius: Visada naudokite
flex: 1
(trumpinysflex: 1 1 0%
). Nulinisflex-basis
yra raktas. - Jei elementas nesitraukia: Labiausiai tikėtina priežastis yra numanomasis
min-width: auto
. Pritaikykitemin-width: 0
„flex“ elementui, kad leistumėte jam susitraukti mažiau nei jo turinio dydis. - Prisiminkite, kad
flex-shrink
yra pasvertas: Elementai su didesniuflex-basis
susitrauks daugiau absoliučiais dydžiais nei mažesni elementai su tuo pačiuflex-shrink
koeficientu. flex-basis
yra karalius: Jis nustato atskaitos tašką visiems dydžio skaičiavimams. Valdykiteflex-basis
, kad turėtumėte didžiausią įtaką galutiniam maketui. Naudojantauto
, atsižvelgiama į turinio dydį; naudojant konkrečią vertę, gaunate aiškią kontrolę.- Galvokite kaip naršyklė: Vizualizuokite žingsnius. Pirma, gaukite bazinius dydžius. Tada apskaičiuokite laisvą erdvę (teigiamą ar neigiamą). Galiausiai paskirstykite tą erdvę pagal didėjimo/mažėjimo taisykles.
Išvada
CSS „Flexbox“ dydžio nustatymo algoritmas nėra savavališka magija; tai gerai apibrėžta, logiška ir neįtikėtinai galinga, turinį atpažįstanti sistema. Peržengdami paprastų savybių ir verčių porų ribas ir suprasdami pagrindinį procesą, jūs įgyjate galimybę nuspėti, derinti ir kurti maketus su pasitikėjimu ir tikslumu.
Kitą kartą, kai „flex“ elementas elgsis netinkamai, jums nereikės spėlioti. Galėsite mintyse pereiti per algoritmą: patikrinti flex-basis
, atsižvelgti į vidinį turinio dydį, išanalizuoti laisvą erdvę ir pritaikyti flex-grow
ar flex-shrink
taisykles. Dabar jūs turite žinių, kaip sukurti vartotojo sąsajas, kurios yra ne tik elegantiškos, bet ir atsparios, gražiai prisitaikančios prie dinamiškos turinio prigimties, nesvarbu, iš kurios pasaulio vietos jis būtų.