ડેવલપર્સને ઝડપી સફળતા (quick win) મેળવવી ગમે છે. જ્યારે ટિકિટમાં "ડાર્ક મોડ ઉમેરો" લખ્યું હોય, ત્યારે સૌથી સરળ રસ્તો સ્પષ્ટ દેખાય છે: light.css લખો, dark.css લખો, અને તેમની વચ્ચે ટોગલ કરો. તે સ્વચ્છ લાગે છે. તે ઝડપથી શિપ (ship) કરી શકાય છે. ત્રણ ઘટકો (components) ધરાવતા નાના સાઇડ પ્રોજેક્ટ માટે, તે કદાચ ટકી શકે છે. પરંતુ એકવાર તમારું એપ્લિકેશન થોડા મોડ્યુલ્સથી વધી જાય, પછી તે બીજી ફાઇલ એસેટ રહેવાને બદલે એક જવાબદારી (liability) બની જાય છે જેને તમારે ડુપ્લીકેટમાં મેન્ટેન કરવી પડે છે.

બે-ફાઇલનો જાળ (The Two-File Trap)

પ્રથમ નજરે તર્ક યોગ્ય લાગે છે. કામનું વિભાજન (Separation of concerns), ખરું ને? અહીં લાઈટ વસ્તુઓ, ત્યાં ડાર્ક વસ્તુઓ. તમે તમારા એડિટરમાં બે બફર્સ ખોલો છો. તમે લાઈટ ફાઇલમાંથી કાર્ડ સ્ટાઇલ્સ ડાર્ક ફાઇલમાં કોપી કરો છો, #ffffff ને બદલે #1a1a1a મૂકો છો, અને કામ પૂરું કરો છો.

સમસ્યા પ્રથમ અઠવાડિયે નથી હોતી. સમસ્યા છઠ્ઠા મહિનામાં આવે છે, જ્યારે ડિઝાઇનર પ્રાઇમરી બટન પર થોડા અલગ બોર્ડર રેડિયસ માટે પૂછે છે, અથવા જ્યારે પ્રોડક્ટ ટીમ ચેકઆઉટ ફોર્મ પર નવું વોર્નિંગ સ્ટેટ ઈચ્છે છે. તમે લાઈટ સ્ટાઇલશીટ અપડેટ કરો છો. તમે ડાર્ક સ્ટાઇલશીટ પર નજર નાખો છો. કદાચ તમે ફેરફાર કોપી કરવાનું યાદ રાખો છો. કદાચ તમે ભૂલી જાઓ છો. આ અંતર (gap) એ છે જ્યાં ગુણવત્તા (quality) નાશ પામે છે. તમે હવે એક ઇન્ટરફેસ મેન્ટેન નથી કરી રહ્યા. તમે બે સમાંતર ઇન્ટરફેસ મેન્ટેન કરી રહ્યા છો જે સમાન HTML સ્કેલેટન શેર કરે છે.

થીમ ડ્રિફ્ટ અનિવાર્ય છે (Theme Drift Is Inevitable)

આ અંતરને એક નામ છે જેને ફ્રન્ટએન્ડ ટીમો ઓળખવાનું શરૂ કરી રહી છે: થીમ ડ્રિફ્ટ (theme drift). તે ત્યારે થાય છે જ્યારે તમારી બે સ્ટાઇલશીટ્સ અલગ-અલગ ઝડપે વિકસે છે. અહીં પેડિંગ એડજસ્ટમેન્ટ. ત્યાં શેડોમાં થોડો ફેરફાર. ડાર્ક ફાઇલ ઉપેક્ષિત ભાઈ બની જાય છે. અથવા તેનાથી પણ ખરાબ, તે ડરનું કારણ બની જાય છે. ડેવલપર્સ ફેરફારો કરવાનું ટાળવા લાગે છે કારણ કે એક થીમને સ્પર્શ કરવાનો અર્થ એ છે કે કામ ડુપ્લીકેટ કરવા માટે બીજી ફાઇલમાં શોધખોળ કરવી પડે.

કોગ્નિટિવ ઓવરહેડ (cognitive overhead) ઝડપથી વધે છે. તમે CSS એકવાર લખવા માંગતા હતા. તેના બદલે તમે તે બે વાર લખ્યું, અને હવે જ્યારે પણ ડિઝાઇન સિસ્ટમ બદલાય છે ત્યારે તમે તે દેવા પર વ્યાજ ચૂકવી રહ્યા છો. ડાર્ક મોડમાં આઇકોન્સ મિસઅલાઈન થાય છે કારણ કે કોઈએ લાઈટ ફાઇલમાં flex gap અપડેટ કર્યું અને તેને ડાર્ક ફાઇલમાં પણ કરવા ભૂલી ગયું. ફોકસ રિંગ્સ ગાયબ થઈ જાય છે કારણ કે નવો એક્સેસિબિલિટી નિયમ માત્ર એક શીટમાં જ આવ્યો હતો. UI માત્ર ખોટું દેખાતું નથી, તે તૂટેલું (broken) લાગવા લાગે છે.

સેમેન્ટિક ટોકન્સનો ઉપયોગ કરો (Use Semantic Tokens)

ઉકેલ કોઈ સારું ડિફ ટૂલ (diff tool) અથવા કડક કોડ રિવ્યુ નથી. ઉકેલ રંગ વિશે વિચારવાની અલગ રીત છે. તમારી સ્ટાઇલ્સને દેખાવના આધારે ગોઠવવાનું બંધ કરો અને તેના હેતુ (purpose) મુજબ ગોઠવવાનું શરૂ કરો. અહીં સેમેન્ટિક ટોકન્સ (semantic tokens) કામ આવે છે.

કાર્ડને વ્હાઇટ બેકગ્રાઉન્ડ આપવાને બદલે, તેને 'સર્ફેસ બેકગ્રાઉન્ડ' આપો. ટેક્સ્ટ માટે બ્લેક અને ઓફ-વ્હાઇટ વચ્ચે પસંદગી કરવાને બદલે, 'ટેક્સ્ટ કલર' પસંદ કરો. ઘટક (component) ને ખબર નથી કે વપરાશકર્તા લાઈટ મોડ પસંદ કરે છે કે ડાર્ક, અને તેને તેનાથી કોઈ ફરક પડતો નથી. તે ફક્ત તેના કામને અનુરૂપ ટોકન માંગે છે.

એક સ્ટાન્ડર્ડ બટન વિશે વિચારો. બે-ફાઇલની દુનિયામાં, .btn લાઈટ સ્ટાઇલશીટમાં વ્હાઇટ બેકગ્રાઉન્ડ અને ડાર્ક બોર્ડર સાથે રહે છે. તેનો જોડિયો ડાર્ક સ્ટાઇલશીટમાં લગભગ કાળા બેકગ્રાઉન્ડ અને હળવા બોર્ડર સાથે રહે છે. તે એક બટન માટે બમણો કોડ છે. ટોકન્સ સાથે, .btn પાસે એક જ ડિક્લેરેશન છે: બેકગ્રાઉન્ડ var(--color-surface-secondary) છે અને બોર્ડર var(--color-border-default) છે. મૂલ્યો (values) પોતે રૂટ (root) પર રહે છે. જ્યારે સાઇટ લાઈટ મોડમાં હોય, ત્યારે --color-surface-secondary #f8f9fa જેવું કંઈક બને છે. ડાર્ક મોડમાં, તે જ ટોકન #2d2d2d બને છે. બટન ઘટક ક્યારેય બદલાતું નથી. ફક્ત તેની નીચેનો ડેટા બદલાય છે.

સ્ટ્રક્ચર અને ડેટા વચ્ચેનો આ તફાવત સૂક્ષ્મ છે પણ શક્તિશાળી છે. તમારું કાર્ડ ઘટક લેઆઉટ, સ્પેસિંગ, ટાઇપોગ્રાફી અને એલિવેશન એક જ વાર વ્યાખ્યાયિત કરે છે. તમારું થીમ લેયર પેલેટ વ્યાખ્યાયિત કરે છે. આ વિભાજન જ એ છે જેના માટે CSS કસ્ટમ પ્રોપર્ટીઝ બનાવવામાં આવી હતી.

આર્કિટેક્ચર કેવી રીતે બદલાય છે

આ અભિગમ તમે સ્ટાઇલ્સ કેવી રીતે લખો છો તેને મૂળભૂત રીતે પુનર્ગઠિત કરે છે.

જૂની રીત સામાન્ય રીતે આવી દેખાય છે:

  • પેડિંગ, રેડિયસ, બેકગ્રાઉન્ડ, ટેક્સ્ટ કલર અને શેડો વ્યાખ્યાયિત કરતી એક લાઈટ કાર્ડ સ્ટાઇલશીટ.
  • માત્ર રંગો બદલવા માટે મોટાભાગના સમાન ગુણધર્મોને ફરીથી વ્યાખ્યાયિત કરતી એક ડાર્ક કાર્ડ સ્ટાઇલશીટ.
  • કઈ સ્ટાઇલશીટ લોડ કરવી અથવા બોડી પર કઈ ક્લાસ ટોગલ કરવી તે નક્કી કરતું એક લોજિક લેયર.

નવી રીત આવી દેખાય છે:

  • લેઆઉટ વ્યાખ્યાયિત કરતી અને સેમેન્ટિક ટોકન્સ સોંપતી એક કાર્ડ સ્ટાઇલશીટ.
  • લાઈટ સંદર્ભમાં તે ટોકન્સનો અર્થ શું છે તે વ્યાખ્યાયિત કરતી એક થીમ ફાઇલ.
  • ડાર્ક સંદર્ભમાં તે ટોકન્સનો અર્થ શું છે તે વ્યાખ્યાયિત કરતી એક થીમ ફાઇલ, અથવા ફક્ત તે જ ફાઇલમાં એક બ્લોક.
  • ઘટક લેયરને અડક્યા વિના વેલ્યુ લેયરને બદલતું એક સિંગલ એટ્રિબ્યુટ સ્વેપ.

You keep the setup stable. You only change the data. When the designer wants to introduce a third theme, maybe a high-contrast mode or a midnight blue variant, you do not rewrite the card. You add one more assignment to the token map. The component stays dumb and happy. It still wants a surface color. The theme tells it which surface color to use.

The Data Attribute Switch

Implementation can stay simple and readable. Apply a data attribute to your HTML tag, something like data-theme="dark", and let your token definitions scope under it.

Set your defaults on :root for the light experience so the page renders correctly before JavaScript runs. Then override the token values under [data-theme="dark"]. A tiny script watches for a toggle click, updates the attribute, and every component on the page responds instantly. No class thrashing on individual elements. No importing an entirely separate stylesheet mid-render. The browser already has the variables in memory; it just repaints with new values.

This keeps your code clean in a very practical sense. You do not have to grep across two directories to find every instance of .card. You do not have to worry about specificity wars between competing theme classes stacked on the same node. Your HTML stays readable. Your CSS stays centralized and searchable.

It Is About Values, Not Versions

Dark mode is about values. It is not a second version of your UI. The corners of your card do not get rounder at night. Your grid does not collapse into a different shape. Your type scale does not need a new rhythm. Only the colors shift, and sometimes the shadows breathe a little deeper. Treating darkness as a full reskin is over-engineering that creates maintenance nightmares.

The teams that get this right treat their design system like a database. Components query for properties by name. Themes provide the records. Switching from light to dark is a query parameter change, not a schema rewrite.

That mindset is what saves you from theme drift. One card. One button. One source of truth for spacing and sizing. The palette lives in one place, logically mapped, ready for whatever environment the user prefers.

The Real Takeaway

If you are maintaining two CSS files for light and dark, you are not theming. You are cloning. Move to semantic tokens, scope them with a root-level data attribute, and let your components ask for roles instead of hardcoding appearances. The initial refactor takes effort, but the alternative is an endless game of whack-a-mole across parallel stylesheets. Life is too short to write the same card twice.