കുറച്ച് വർഷങ്ങൾക്ക് മുമ്പ്, ഞാൻ ഒരു ഡാഷ്ബോർഡ് നിർമ്മിക്കാൻ ഇരുന്നു. വലിയ സങ്കീർണ്ണതകളൊന്നുമില്ലാത്ത—ഒരു ഫിക്സഡ് സൈഡ്ബാർ, ഒരു മെയിൻ കണ്ടന്റ് ഏരിയ, പിന്നെ ഒരു ഫൂട്ടർ എന്നിവ മാത്രം. Flexbox ആണ് ഇതിന് അനുയോജ്യമായ മാർഗ്ഗമെന്ന് എനിക്ക് തോന്നി, തുടക്കത്തിൽ അത് ശരിയായി പ്രവർത്തിക്കുകയും ചെയ്തു. എന്നാൽ മെയിൻ സെക്ഷനിൽ ഒരു നിര കാർഡുകൾ (cards) ചേർത്തതോടെ ലേഔട്ട് മുഴുവൻ തകിടം മറിഞ്ഞു. അടുത്ത മൂന്ന് മണിക്കൂർ ഞാൻ flex-grow റേഷ്യോകളും നെസ്റ്റഡ് പെർസെന്റേജ് വീതികളും (nested percentage widths) ക്രമീകരിക്കാൻ പാടുപെട്ടു. എത്ര പാഡിംഗ് കുറച്ചാലും കണ്ടെയ്നറുകൾ നിരയായി വരാൻ തയ്യാറാകാത്തത് ഞാൻ നോക്കിനിന്നു. ആ പേജ് ഏതു നിമിഷവും തകരാൻ പോകുന്ന ഒരു ഗോപുരം പോലെ തോന്നി.
ആ കഠിനമായ അനുഭവം ആധുനിക CSS ലേഔട്ടിനെക്കുറിച്ചുള്ള ഏറ്റവും പ്രധാനപ്പെട്ട ഒരു കാര്യം എന്നെ പഠിപ്പിച്ചു: Flexbox-ഉം Grid-ഉം പരസ്പരം എതിരാളികളല്ല. അവ വ്യത്യസ്ത ജോലികൾക്കായി ഉപയോഗിക്കേണ്ട ഉപകരണങ്ങളാണ്. തെറ്റായ ഉപകരണം ഉപയോഗിക്കുന്നതാണ് മിക്ക ലേഔട്ട് പരാജയങ്ങൾക്കും കാരണം.
വ്യത്യാസം അളവുകളിലാണ് (Dimensionality)
Flexbox-നെ ഒരു ഇടനാഴി (hallway) പോലെ കരുതുക. ഐറ്റങ്ങൾ ഒരു ദിശയിൽ മാത്രം ഒഴുകുന്നു—ഒന്നുകിൽ ഒരു വരിയായി (row) അല്ലെങ്കിൽ ഒരു നിരയായി (column). ഇത് വൺ-ഡൈമൻഷണൽ (one-dimensional) വിതരണത്തിനായി നിർമ്മിച്ചതാണ്. ബ്രൗസർ ഉള്ളടക്കം നോക്കുന്നു, തുടർന്ന് ആ ഒരൊറ്റ അച്ചുതണ്ടിലൂടെ (axis) അത് എങ്ങനെ വലിച്ചുനീട്ടണം, ചുരുക്കണം അല്ലെങ്കിൽ ക്രമീകരിക്കണം എന്ന് തീരുമാനിക്കുന്നു. ഉള്ളടക്കമാണ് ലേഔട്ടിനെ തീരുമാനിക്കുന്ന സാഹചര്യങ്ങളിൽ Flexbox തികച്ചും അനുയോജ്യമാണ്. ഒരു നാവിഗേഷൻ ബാർ, ഫോം ഫീൽഡുകളുടെ ഒരു കൂട്ടം, അല്ലെങ്കിൽ തുല്യ അകലം ആവശ്യമുള്ള ടാഗുകളുടെ ഒരു സെറ്റ് എന്നിവയെല്ലാം ഒരു ഫ്ലെക്സ് കണ്ടെയ്നറിൽ സ്വാഭാവികമായി ഇരിക്കുന്നു, കാരണം അവയെല്ലാം ഒരേ ലോജിക് പിന്തുടരുന്നു.
മറുവശത്ത്, Grid എന്നത് ഒരു ഫ്ലോർ പ്ലാൻ (floor plan) പോലെയാണ്. ഇത് കർശനമായി ടു-ഡൈമൻഷണൽ (two-dimensional) ആണ്, വരികളും (rows) നിരകളും (columns) ഒരേസമയം കൈകാര്യം ചെയ്യുന്നു. നിങ്ങൾ ആദ്യം ഘടന (structure) നിർവചിക്കുന്നു, അതിനുശേഷം അതിനുള്ളിൽ ഐറ്റങ്ങൾ ക്രമീകരിക്കുന്നു. വെർട്ടിക്കൽ, ഹൊറിസോണ്ടൽ പൊസിഷനിംഗ് എന്നിവ ഒരേസമയം നിയന്ത്രിക്കേണ്ട പേജ് ആർക്കിടെക്ചറിന് Grid അനുയോജ്യമാണ്. നെസ്റ്റഡ് Flexbox കണ്ടെയ്നറുകൾ ഉപയോഗിച്ച് ഒരു സങ്കീർണ്ണമായ ടു-ഡൈമൻഷണൽ ഡിസൈൻ നിർമ്മിക്കാൻ ശ്രമിക്കുമ്പോൾ, അത് അമിതമായ മാർക്കപ്പും (markup), ദുർബലമായ റാപ്പറുകളും (wrappers), ചെറിയ മാറ്റങ്ങൾ വരുത്തിയാൽ പോലും തകരാൻ സാധ്യതയുള്ള കണക്കുകൂട്ടലുകളും ഉണ്ടാക്കുന്നു.
Flexbox ഇപ്പോഴും പ്രസക്തമാണ്
എല്ലാ ഫ്ലെക്സ് കണ്ടെയ്നറുകളും ഉടൻ തന്നെ Grid ഉപയോഗിച്ച് മാറ്റാൻ ശ്രമിക്കരുത്. ഓരോ കമ്പോണന്റുകൾക്കുള്ളിലും Flexbox പലപ്പോഴും കൂടുതൽ ലളിതവും കൃത്യവുമാണ്. രണ്ട് ബട്ടണുകളുള്ള ഒരു കാർഡ് ഫൂട്ടർ ഉണ്ടെന്നും അതിൽ ഒരെണ്ണം ഇടത് വശത്തും മറ്റൊന്ന് വലത് വശത്തും വേണമെന്നുണ്ടെങ്കിൽ, justify-content: space-between കൃത്യമായി അത് ചെയ്യുന്നു. ഉയരം അറിയാത്ത ഒരു ബട്ടണിനുള്ളിൽ ഒരു ഐക്കൺ വെർട്ടിക്കലായി സെന്റർ ചെയ്യണമെങ്കിൽ, align-items: center ആണ് ഏറ്റവും എളുപ്പമുള്ള വഴി. വ്യത്യസ്ത നീളമുള്ള പേരുകളുള്ള യൂസർ ബാഡ്ജുകൾ പോലുള്ള മാറിക്കൊണ്ടിരിക്കുന്ന ഉള്ളടക്കം (variable content) Flexbox-ൽ സുഗമമായി ക്രമീകരിക്കാം, കാരണം ഇത് കണ്ടന്റിന് മുൻഗണന നൽകുന്നു (content-first). കണ്ടെയ്നർ അതിനുള്ളിലെ ഉള്ളടക്കത്തിനനുസരിച്ച് മാറുന്നു.
Grid എന്നത് കണ്ടെയ്നറിന് മുൻഗണന നൽകുന്നതാണ് (container-first). എത്ര ട്രാക്കുകൾ ഉണ്ട് എന്നും അവയുടെ വലിപ്പം എത്രയായിരിക്കണം എന്നും നിങ്ങൾ ബ്രൗസറിനോട് പറയുന്നു, അതിനുശേഷം ആ സെല്ലുകളിലേക്ക് ഐറ്റങ്ങൾ ഇടുന്നു. നിങ്ങളുടെ ലേഔട്ട് ഒരേ നിരയിലുള്ള ഐറ്റങ്ങൾ മാത്രമാണെങ്കിൽ, Grid ഉപയോഗിക്കുന്നത് അനാവശ്യമായ സങ്കീർണ്ണത ഉണ്ടാക്കും.
പേജ് ലേഔട്ടിന് Grid ആണ് അനുയോജ്യം
ഇവിടെയാണ് Grid അതിന്റെ കരുത്ത് കാണിക്കുന്നത്. എന്റെ ഡാഷ്ബോർഡ് ദുരന്തം ഓർമ്മയുണ്ടോ? ഘടന എങ്ങനെയായിരിക്കണമായിരുന്നു എന്ന് നോക്കാം:
.page {
display: grid;
min-height: 100vh;
grid-template-rows: auto 1fr auto;
grid-template-columns: 200px 1fr;
}
.header { grid-row: 1; grid-column: 1 / -1; }
.sidebar { grid-row: 2; grid-column: 1; }
.main { grid-row: 2; grid-column: 2; }
.footer { grid-row: 3; grid-column: 1 / -1; }
ഇവിടെ എന്താണ് സംഭവിക്കുന്നതെന്ന് നോക്കൂ. .page കണ്ടെയ്നർ മൂന്ന് വരികളും (rows) രണ്ട് നിരകളും (columns) ഉണ്ടാക്കുന്നു. auto ഉപയോഗിക്കുന്നതുകൊണ്ട് ആദ്യത്തെ വരി ഹെഡറിലെ ഉള്ളടക്കത്തിനനുസരിച്ച് വലിപ്പം ക്രമീകരിക്കുന്നു. ഇടയിലുള്ള വരി 1fr ഉപയോഗിച്ച് ബാക്കിയുള്ള എല്ലാ സ്ഥലവും കൈക്കലാക്കുന്നു. ഫൂട്ടർ അവസാന വരിയിൽ അതിന്റെ ഉള്ളടക്കത്തിനനുസരിച്ച് വരുന്നു. അതേസമയം, സൈഡ്ബാർ 200 പിക്സൽ വീതിയിൽ ലോക്ക് ചെയ്യപ്പെടുന്നു, മെയിൻ ഏരിയ ബാക്കി ഭാഗം നിറയ്ക്കുന്നു.
ഇതിലെ പൊസിഷനിംഗ് ലോജിക് ആണ് യഥാർത്ഥ ആശ്വാസം. ഹെഡർ കോളം ലൈൻ 1 മുതൽ -1 വരെ വ്യാപിച്ചു കിടക്കുന്നു, അതായത് നിങ്ങൾ പിന്നീട് എത്ര കോളം കൂട്ടിയാലും ഹെഡർ രണ്ട് കോളം വീതിയിലും കാണപ്പെടും. സൈഡ്ബാർ, മെയിൻ കണ്ടന്റ് എന്നിവ രണ്ടും രണ്ടാമത്തെ വരി പങ്കിടുന്നുണ്ടെങ്കിലും അവ വ്യത്യസ്ത നിരകളിലാണ്. ഫൂട്ടർ മൂന്നാമത്തെ വരിയിൽ മുഴുവൻ വീതിയിലും വരുന്നു. ചൈൽഡ് എലമെന്റുകളിൽ നിങ്ങൾക്ക് പെർസെന്റേജ് കണക്കുകൂട്ടലുകൾ ആവശ്യമില്ല. ഉയരം ക്രമീകരിക്കാൻ നെസ്റ്റഡ് റാപ്പറുകൾ ഉപയോഗിക്കേണ്ടി വരുന്നില്ല. സൈഡ്ബാർ വീതി ഒരിടത്ത് മാറ്റിയാൽ മെയിൻ ഏരിയ തനിയെ ക്രമീകരിക്കപ്പെടും. ലേഔട്ട് മുഴുവൻ ഒരു സിസ്റ്റം പോലെ പ്രവർത്തിക്കുന്നു.
grid-template-areas ഉപയോഗിച്ചുള്ള വായനാസുഖം
കൂടുതൽ വ്യക്തതയ്ക്കായി നിങ്ങൾക്ക് സെക്ഷനുകൾക്ക് പേര് നൽകാം. ലൈൻ നമ്പറുകൾ മാനേജ് ചെയ്യുന്നതിന് പകരം, നിങ്ങൾക്ക് ഒരു വിഷ്വൽ മാപ്പ് തയ്യാറാക്കാം:
.page {
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; }
.main { grid-area: main; }
ഇപ്പോൾ നിങ്ങളുടെ സ്റ്റൈൽഷീറ്റ് ഒരു വയർഫ്രെയിം (wireframe) പോലെ വായിക്കാം. മറ്റൊരു ബ്രേക്ക്പോയിന്റിൽ സൈഡ്ബാർ വലത് വശത്ത് വരണമെന്നുണ്ടെങ്കിൽ, ടെംപ്ലേറ്റ് സ്ട്രിംഗിലെ രണ്ട് വാക്കുകൾ മാറ്റിയാൽ മതി. നെസ്റ്റഡ് ഫ്ലെക്സ് കണ്ടെയ്നറുകൾ ഉപയോഗിച്ച് ഇത്തരത്തിലുള്ള ഘടനാപരമായ വ്യക്തത (structural readability) കൈവരിക്കാൻ കഴിയില്ല.
രണ്ട് കഠിനമായ പാഠങ്ങൾ
Grid ഒരു മാന്ത്രികവിദ്യയല്ല. നിങ്ങളുടെ ലേഔട്ടിനെ പെട്ടെന്ന് തകരാറിലാക്കുന്ന രണ്ട് തെറ്റുകളുണ്ട്.
ആദ്യത്തേത് യൂണിറ്റുകളുടെ അശ്രദ്ധമായ ഉപയോഗമാണ്. നിങ്ങൾ grid-template-columns: 1fr 1fr 1fr എന്ന് നിർവചിച്ചുവെങ്കിലും നിങ്ങളുടെ ഡിസൈനിന് രണ്ട് കോളങ്ങൾ മാത്രമേ ആവശ്യമുള്ളൂ എങ്കിൽ, ആ മൂന്നാമത്തെ ട്രാക്ക് അവിടെ നിലനിൽക്കും. അത് ശൂന്യമായി ഇരുന്നുകൊണ്ട് നിങ്ങൾ പ്രതീക്ഷിക്കാത്ത ഒരു വിടവ് ഉണ്ടാക്കിയേക്കാം, അല്ലെങ്കിൽ നിങ്ങളുടെ യഥാർത്ഥ ഉള്ളടക്കത്തെ ഡിസൈൻ തകരാറിലാക്കുന്ന രീതിയിൽ ചുരുക്കി വെക്കാൻ നിർബന്ധിച്ചേക്കാം. ബോധപൂർവ്വം പ്രവർത്തിക്കുക. നിങ്ങൾക്ക് രണ്ട് കോളങ്ങൾ ആണ് വേണ്ടതെങ്കിൽ, repeat(2, 1fr) എന്ന് എഴുതുക.
