রেন্ডারিংএনজি ডিপ-ডাইভ: লেআউটএনজি ব্লক ফ্র্যাগমেন্টেশন

মর্টেন স্টেনশর্ন
Morten Stenshorne

ব্লক ফ্র্যাগমেন্টেশন হল একটি CSS ব্লক-লেভেল বক্সকে (যেমন একটি বিভাগ বা অনুচ্ছেদ) একাধিক খণ্ডে বিভক্ত করে যখন এটি একটি ফ্র্যাগমেন্ট কন্টেইনারের ভিতরে সম্পূর্ণভাবে ফিট না হয়, যাকে ফ্র্যাগমেন্টেইনার বলা হয়। একটি ফ্র্যাগমেন্টেনার একটি উপাদান নয়, তবে বহু-কলাম বিন্যাসে একটি কলাম বা পৃষ্ঠাযুক্ত মিডিয়াতে একটি পৃষ্ঠা উপস্থাপন করে।

ফ্র্যাগমেন্টেশন হওয়ার জন্য, বিষয়বস্তুটি একটি ফ্র্যাগমেন্টেশন প্রেক্ষাপটের মধ্যে থাকা দরকার। একটি ফ্র্যাগমেন্টেশন প্রসঙ্গ একটি মাল্টি-কলাম কন্টেইনার (সামগ্রী কলামে বিভক্ত করা হয়) বা মুদ্রণ করার সময় (সামগ্রী পৃষ্ঠাগুলিতে বিভক্ত করা হয়) দ্বারা সাধারণত প্রতিষ্ঠিত হয়। অনেক লাইন সহ একটি দীর্ঘ অনুচ্ছেদকে একাধিক খণ্ডে বিভক্ত করতে হতে পারে, যাতে প্রথম লাইনগুলি প্রথম খণ্ডে স্থাপন করা হয় এবং অবশিষ্ট লাইনগুলি পরবর্তী খণ্ডগুলিতে স্থাপন করা হয়।

দুটি কলামে বিভক্ত পাঠ্যের একটি অনুচ্ছেদ।
এই উদাহরণে, মাল্টি-কলাম লেআউট ব্যবহার করে একটি অনুচ্ছেদ দুটি কলামে বিভক্ত করা হয়েছে। প্রতিটি কলাম একটি ফ্র্যাগমেন্টেনার, খণ্ডিত প্রবাহের একটি অংশকে প্রতিনিধিত্ব করে।

ব্লক ফ্র্যাগমেন্টেশন আরেকটি সুপরিচিত ফ্র্যাগমেন্টেশনের অনুরূপ: লাইন ফ্র্যাগমেন্টেশন, অন্যথায় "লাইন ব্রেকিং" নামে পরিচিত। যে কোনো ইনলাইন উপাদান যেটিতে একাধিক শব্দ থাকে (যেকোনো টেক্সট নোড, যেকোনো <a> উপাদান, এবং আরও অনেক কিছু), এবং লাইন বিরতির অনুমতি দেয়, একাধিক খণ্ডে বিভক্ত হতে পারে। প্রতিটি খণ্ড একটি ভিন্ন লাইন বাক্সে স্থাপন করা হয়. একটি লাইন বক্স হল ইনলাইন ফ্র্যাগমেন্টেশন যা কলাম এবং পৃষ্ঠাগুলির জন্য একটি ফ্র্যাগমেন্টেনারের সমতুল্য।

লেআউটএনজি ব্লক ফ্র্যাগমেন্টেশন

LayoutNGBlockFragmentation হল LayoutNG-এর জন্য ফ্র্যাগমেন্টেশন ইঞ্জিনের একটি পুনর্লিখন, যা প্রাথমিকভাবে Chrome 102-এ পাঠানো হয়েছিল। ডেটা স্ট্রাকচারের ক্ষেত্রে, এটি একাধিক প্রাক-এনজি ডেটা স্ট্রাকচারকে এনজি টুকরা দিয়ে প্রতিস্থাপিত করেছে যা সরাসরি ফ্র্যাগমেন্ট ট্রিতে উপস্থাপিত হয়েছে।

উদাহরণস্বরূপ, আমরা এখন 'ব্রেক-আগে' এবং 'ব্রেক-আফটার' সিএসএস বৈশিষ্ট্যগুলির জন্য 'এড়িয়ে চলুন' মান সমর্থন করি, যা লেখকদের শিরোনামের পরে বিরতি এড়াতে অনুমতি দেয়। এটি প্রায়শই বিশ্রী দেখায় যখন একটি পৃষ্ঠার শেষ জিনিসটি একটি শিরোনাম হয়, যখন বিভাগটির বিষয়বস্তু পরবর্তী পৃষ্ঠায় শুরু হয়। হেডারের আগে ব্রেক করা ভালো।

উদাহরণ শিরোনাম প্রান্তিককরণ.
চিত্র 1. প্রথম উদাহরণটি পৃষ্ঠার নীচে একটি শিরোনাম দেখায়, দ্বিতীয়টি এটির সংশ্লিষ্ট বিষয়বস্তু সহ নিম্নলিখিত পৃষ্ঠার শীর্ষে দেখায়৷

ক্রোম ফ্র্যাগমেন্টেশন ওভারফ্লোকেও সমর্থন করে, যাতে মনোলিথিক (অবিচ্ছেদযোগ্য বলে মনে করা হয়) বিষয়বস্তু একাধিক কলামে বিভক্ত না হয় এবং ছায়া এবং রূপান্তরের মতো পেইন্ট প্রভাবগুলি সঠিকভাবে প্রয়োগ করা হয়।

LayoutNG এ ব্লক ফ্র্যাগমেন্টেশন এখন সম্পূর্ণ হয়েছে

কোর ফ্র্যাগমেন্টেশন (ব্লক কন্টেনার, লাইন লেআউট, ফ্লোট এবং আউট-অফ-ফ্লো পজিশনিং সহ) Chrome 102-এ পাঠানো হয়েছে। Chrome 103-এ ফ্লেক্স এবং গ্রিড ফ্র্যাগমেন্টেশন পাঠানো হয়েছে এবং Chrome 106-এ টেবিল ফ্র্যাগমেন্টেশন পাঠানো হয়েছে। শেষ পর্যন্ত, Chrome 108-এ প্রিন্টিং পাঠানো হয়েছে। ব্লক ফ্র্যাগমেন্টেশন ছিল শেষ বৈশিষ্ট্য যা লেআউট সম্পাদনের জন্য লিগ্যাসি ইঞ্জিনের উপর নির্ভর করে।

ক্রোম 108 অনুযায়ী, লেআউট সম্পাদন করতে লেগসি ইঞ্জিন আর ব্যবহার করা হয় না।

এছাড়াও, LayoutNG ডেটা স্ট্রাকচার পেইন্টিং এবং হিট-টেস্টিং সমর্থন করে, কিন্তু আমরা JavaScript API-এর জন্য কিছু লিগ্যাসি ডেটা স্ট্রাকচারের উপর নির্ভর করি যেগুলি লেআউটের তথ্য পড়ে, যেমন offsetLeft এবং offsetTop

NG এর সাথে সবকিছু সাজানো নতুন বৈশিষ্ট্যগুলিকে বাস্তবায়ন এবং প্রেরণ করা সম্ভব করবে যেখানে শুধুমাত্র LayoutNG বাস্তবায়ন রয়েছে (এবং কোন লিগ্যাসি ইঞ্জিন কাউন্টারপার্ট নেই), যেমন CSS কন্টেইনার ক্যোয়ারী , অ্যাঙ্কর পজিশনিং, MathML , এবং কাস্টম লেআউট (Houdini) । কন্টেইনার প্রশ্নের জন্য, আমরা এটিকে কিছুটা আগেই পাঠিয়ে দিয়েছি, ডেভেলপারদের একটি সতর্কতা সহ যে মুদ্রণ এখনও সমর্থিত নয়।

আমরা 2019 সালে LayoutNG-এর প্রথম অংশ পাঠিয়েছিলাম, যেটিতে নিয়মিত ব্লক কন্টেইনার লেআউট, ইনলাইন লেআউট, ফ্লোট এবং আউট-অফ-ফ্লো পজিশনিং ছিল, কিন্তু ফ্লেক্স, গ্রিড বা টেবিলের জন্য কোনও সমর্থন নেই এবং কোনও ব্লক ফ্র্যাগমেন্টেশন সমর্থন নেই। আমরা ফ্লেক্স, গ্রিড, টেবিল, প্লাস ব্লক ফ্র্যাগমেন্টেশন জড়িত যেকোনো কিছুর জন্য লিগ্যাসি লেআউট ইঞ্জিন ব্যবহার করতে ফিরে আসব। এটি খণ্ডিত বিষয়বস্তুর মধ্যে ব্লক, ইনলাইন, ভাসমান এবং প্রবাহের বাইরের উপাদানগুলির জন্যও সত্য ছিল—যেমন আপনি দেখতে পাচ্ছেন, এইরকম একটি জটিল লেআউট ইঞ্জিন ইন-প্লেস আপগ্রেড করা একটি অত্যন্ত সূক্ষ্ম নৃত্য।

উপরন্তু, 2019-এর মাঝামাঝি পর্যন্ত LayoutNG ব্লক ফ্র্যাগমেন্টেশন লেআউটের মূল কার্যকারিতার বেশিরভাগই ইতিমধ্যেই (একটি পতাকার পিছনে) প্রয়োগ করা হয়েছে। তাহলে, জাহাজে আসতে এত সময় লাগলো কেন? সংক্ষিপ্ত উত্তর হল: ফ্র্যাগমেন্টেশনকে সিস্টেমের বিভিন্ন উত্তরাধিকারী অংশের সাথে সঠিকভাবে সহাবস্থান করতে হবে, যা সমস্ত নির্ভরতা আপগ্রেড না হওয়া পর্যন্ত অপসারণ বা আপগ্রেড করা যাবে না।

উত্তরাধিকার ইঞ্জিন মিথস্ক্রিয়া

লিগ্যাসি ডেটা স্ট্রাকচারগুলি এখনও জাভাস্ক্রিপ্ট এপিআইগুলির দায়িত্বে রয়েছে যা লেআউটের তথ্য পড়ে, তাই আমাদের এমনভাবে লেগ্যাসি ইঞ্জিনে ডেটা লিখতে হবে যাতে এটি বোঝা যায়। এর মধ্যে রয়েছে লেগসি মাল্টি-কলাম ডেটা স্ট্রাকচার, যেমন LayoutMultiColumnFlowThread সঠিকভাবে আপডেট করা।

লিগ্যাসি ইঞ্জিন ফলব্যাক সনাক্তকরণ এবং পরিচালনা

আমাদের লিগ্যাসি লেআউট ইঞ্জিনে ফিরে যেতে হয়েছিল যখন ভিতরে এমন সামগ্রী ছিল যা এখনও LayoutNG ব্লক ফ্র্যাগমেন্টেশন দ্বারা পরিচালনা করা যায়নি। শিপিং কোর লেআউটএনজি ব্লক ফ্র্যাগমেন্টেশনের সময়, এতে ফ্লেক্স, গ্রিড, টেবিল এবং প্রিন্ট করা যেকোনো কিছু অন্তর্ভুক্ত ছিল। এটি বিশেষভাবে কঠিন ছিল কারণ লেআউট ট্রিতে অবজেক্ট তৈরি করার আগে আমাদের লিগ্যাসি ফলব্যাকের প্রয়োজনীয়তা সনাক্ত করতে হবে। উদাহরণস্বরূপ, একটি মাল্টি-কলাম কন্টেইনার পূর্বপুরুষ আছে কিনা তা জানার আগে এবং কোন DOM নোডগুলি ফর্ম্যাটিং প্রসঙ্গে পরিণত হবে তা জানার আগে আমাদের সনাক্ত করতে হবে। এটি একটি মুরগি-ডিম সমস্যা যার একটি নিখুঁত সমাধান নেই, তবে যতক্ষণ না এর একমাত্র অসদাচরণটি মিথ্যা ইতিবাচক (আসলে কোন প্রয়োজন না থাকলে উত্তরাধিকারে পতন), এটি ঠিক আছে, কারণ সেই বিন্যাস আচরণে যে কোনও বাগ রয়েছে Chromium এর আগে থেকেই আছে, নতুন নয়।

প্রাক পেইন্ট গাছ হাঁটা

প্রি-পেইন্ট এমন কিছু যা আমরা লেআউটের পরে করি , কিন্তু পেইন্টিংয়ের আগে। প্রধান চ্যালেঞ্জ হল যে আমাদের এখনও লেআউট অবজেক্ট ট্রিতে হাঁটতে হবে, কিন্তু আমাদের এখন এনজি টুকরো আছে—তাহলে আমরা কীভাবে এটি মোকাবেলা করব? আমরা একই সময়ে লেআউট অবজেক্ট এবং এনজি ফ্র্যাগমেন্ট গাছ উভয়ই হাঁটছি! এটি বেশ জটিল, কারণ দুটি গাছের মধ্যে ম্যাপিং তুচ্ছ নয়।

যদিও লেআউট অবজেক্ট ট্রি স্ট্রাকচারটি DOM গাছের সাথে ঘনিষ্ঠভাবে সাদৃশ্যপূর্ণ, তবে ফ্র্যাগমেন্ট ট্রি হল লেআউটের একটি আউটপুট , এটিতে একটি ইনপুট নয়। ইনলাইন ফ্র্যাগমেন্টেশন (লাইন ফ্র্যাগমেন্ট) এবং ব্লক ফ্র্যাগমেন্টেশন (কলাম বা পেজ ফ্র্যাগমেন্ট) সহ যেকোনও ফ্র্যাগমেন্টেশনের প্রভাবকে প্রতিফলিত করার পাশাপাশি, ফ্র্যাগমেন্ট ট্রিতে একটি ধারণকৃত ব্লক এবং ডিওএম বংশধরদের মধ্যে একটি সরাসরি পিতামাতা-সন্তানের সম্পর্ক রয়েছে যাদের সেই খণ্ডটি রয়েছে। তাদের ধারণকারী ব্লক. উদাহরণ স্বরূপ, ফ্র্যাগমেন্ট ট্রিতে, সম্পূর্ণভাবে অবস্থানকারী উপাদান দ্বারা উত্পন্ন একটি খণ্ডটি তার ধারণ করা ব্লকের একটি সরাসরি সন্তান, এমনকি যদি প্রবাহের বাইরে অবস্থানকারী বংশধর এবং এর ধারণকারী ব্লকের মধ্যে পূর্বপুরুষ শৃঙ্খলে অন্যান্য নোড থাকে।

এটি আরও জটিল হতে পারে যখন ফ্র্যাগমেন্টেশনের ভিতরে একটি বাহির-অফ-ফ্লো পজিশন করা উপাদান থাকে, কারণ তখন বাহির-অফ-ফ্লো টুকরাগুলি ফ্র্যাগমেন্টেনারের সরাসরি সন্তান হয়ে যায় (এবং CSS যেটিকে ধারণকারী ব্লক বলে মনে করে তার সন্তান নয়)। এটি একটি সমস্যা যা উত্তরাধিকার ইঞ্জিনের সাথে সহাবস্থান করার জন্য সমাধান করতে হয়েছিল। ভবিষ্যতে, আমাদের এই কোডটি সরলীকরণ করতে সক্ষম হওয়া উচিত, কারণ লেআউটএনজি সমস্ত আধুনিক লেআউট মোডগুলিকে নমনীয়ভাবে সমর্থন করার জন্য ডিজাইন করা হয়েছে।

লিগ্যাসি ফ্র্যাগমেন্টেশন ইঞ্জিনের সমস্যা

লিগ্যাসি ইঞ্জিন, ওয়েবের পূর্ববর্তী যুগে ডিজাইন করা হয়েছে, প্রকৃতপক্ষে ফ্র্যাগমেন্টেশনের ধারণা নেই, এমনকি যদি ফ্র্যাগমেন্টেশন প্রযুক্তিগতভাবে তখনও বিদ্যমান ছিল (মুদ্রণ সমর্থন করার জন্য)। ফ্র্যাগমেন্টেশন সমর্থন ছিল এমন কিছু যা উপরে বোল্ট করা হয়েছে (মুদ্রণ) বা রেট্রোফিটেড (মাল্টি-কলাম)।

খণ্ডিত বিষয়বস্তু তৈরি করার সময়, লিগ্যাসি ইঞ্জিন সবকিছুকে একটি লম্বা স্ট্রিপে রাখে যার প্রস্থ একটি কলাম বা পৃষ্ঠার ইনলাইন-আকার এবং উচ্চতা যতটা লম্বা তার বিষয়বস্তু ধারণ করতে হবে। এই লম্বা স্ট্রিপটি পৃষ্ঠায় রেন্ডার করা হয় না - এটিকে একটি ভার্চুয়াল পৃষ্ঠায় রেন্ডারিং হিসাবে মনে করুন যা চূড়ান্ত প্রদর্শনের জন্য পুনরায় সাজানো হয়। এটি ধারণাগতভাবে একটি সম্পূর্ণ কাগজের সংবাদপত্রের নিবন্ধটি একটি কলামে মুদ্রণের অনুরূপ, এবং তারপরে কাঁচি ব্যবহার করে এটিকে একটি দ্বিতীয় ধাপ হিসাবে একাধিক অংশে কাটা। (আগে, কিছু সংবাদপত্র আসলে এর মতো কৌশল ব্যবহার করেছিল!)

লিগ্যাসি ইঞ্জিন স্ট্রিপে একটি কাল্পনিক পৃষ্ঠা বা কলামের সীমানা ট্র্যাক রাখে। এটি এটিকে পরবর্তী পৃষ্ঠা বা কলামে সীমানা অতিক্রম করে না এমন বিষয়বস্তুকে নাজ করতে দেয়৷ উদাহরণস্বরূপ, যদি ইঞ্জিনের বর্তমান পৃষ্ঠাটি যা মনে করে তার উপর যদি একটি লাইনের উপরের অর্ধেকটি ফিট হয়, তাহলে এটি একটি "প্যাজিনেশন স্ট্রুট" সন্নিবেশিত করবে যাতে এটিকে সেই অবস্থানে ঠেলে দেওয়া হয় যেখানে ইঞ্জিন অনুমান করে যে পরবর্তী পৃষ্ঠার শীর্ষটি . তারপরে, বেশিরভাগ প্রকৃত ফ্র্যাগমেন্টেশন কাজ ("কাঁচি দিয়ে কাটা এবং বসানো") প্রি-পেইন্ট এবং পেইন্টিংয়ের সময় লেআউটের পরে, বিষয়বস্তুর লম্বা স্ট্রিপকে পৃষ্ঠা বা কলামে টুকরো টুকরো করে (অংশগুলি ক্লিপিং এবং অনুবাদ করে) হয়। এটি কয়েকটি জিনিসকে অপরিহার্যভাবে অসম্ভব করে তুলেছে, যেমন ট্রান্সফর্ম প্রয়োগ করা এবং ফ্র্যাগমেন্টেশনের পরে আপেক্ষিক অবস্থান নির্ধারণ করা (যা স্পেকের প্রয়োজন)। উপরন্তু, যদিও লিগ্যাসি ইঞ্জিনে টেবিল ফ্র্যাগমেন্টেশনের জন্য কিছু সমর্থন রয়েছে, সেখানে কোনও ফ্লেক্স বা গ্রিড ফ্র্যাগমেন্টেশন সমর্থন নেই।

কাঁচি, বসানো এবং আঠা ব্যবহার করার আগে লিগ্যাসি ইঞ্জিনে কীভাবে একটি তিন-কলামের বিন্যাস অভ্যন্তরীণভাবে উপস্থাপিত হয় তার একটি দৃষ্টান্ত রয়েছে (আমাদের একটি নির্দিষ্ট উচ্চতা রয়েছে, যাতে কেবল চারটি লাইন ফিট হয়, তবে নীচে কিছু অতিরিক্ত স্থান রয়েছে):

একটি কলাম হিসাবে অভ্যন্তরীণ উপস্থাপনা যেখানে পৃষ্ঠা সংখ্যা স্ট্রট হয় যেখানে বিষয়বস্তু ভেঙে যায় এবং অন-স্ক্রীন উপস্থাপনা তিনটি কলাম হিসাবে

যেহেতু লিগ্যাসি লেআউট ইঞ্জিন প্রকৃতপক্ষে লেআউটের সময় বিষয়বস্তুকে খণ্ডিত করে না, সেখানে অনেক অদ্ভুত নিদর্শন রয়েছে, যেমন আপেক্ষিক অবস্থান এবং রূপান্তরগুলি ভুলভাবে প্রয়োগ করা, এবং বক্স-ছায়াগুলি কলামের প্রান্তে ক্লিপ করা হয়েছে৷

এখানে পাঠ্য-ছায়া সহ একটি উদাহরণ:

উত্তরাধিকার ইঞ্জিন এটি ভালভাবে পরিচালনা করে না:

ক্লিপ করা পাঠ্য ছায়া দ্বিতীয় কলামে স্থাপন করা হয়েছে।

আপনি কি প্রথম কলামের লাইন থেকে টেক্সট-শ্যাডো ক্লিপ করা হয়েছে এবং পরিবর্তে দ্বিতীয় কলামের শীর্ষে রাখা হয়েছে তা কি দেখতে পাচ্ছেন? কারণ লিগ্যাসি লেআউট ইঞ্জিন ফ্র্যাগমেন্টেশন বোঝে না।

এটি নিম্নরূপ দেখতে হবে:

ছায়া সহ পাঠ্যের দুটি কলাম সঠিকভাবে প্রদর্শিত হচ্ছে।

এর পরে, রূপান্তর এবং বক্স-শ্যাডো সহ এটিকে আরও জটিল করে তুলি। লক্ষ্য করুন কিভাবে লিগ্যাসি ইঞ্জিনে, ভুল ক্লিপিং এবং কলাম ব্লিড আছে। এর কারণ হল রূপান্তরগুলি একটি পোস্ট-লেআউট, পোস্ট-ফ্র্যাগমেন্টেশন প্রভাব হিসাবে প্রয়োগ করা উচিত বলে অনুমিত হয়। LayoutNG ফ্র্যাগমেন্টেশনের সাথে উভয়ই সঠিকভাবে কাজ করে। এটি ফায়ারফক্সের সাথে ইন্টারঅপ বাড়ায়, যা কিছু সময়ের জন্য ভাল ফ্র্যাগমেন্টেশন সমর্থন করেছে এবং এই এলাকায় বেশিরভাগ পরীক্ষাও সেখানে পাস করেছে।

বাক্স দুটি কলাম জুড়ে ভুলভাবে ভাঙ্গা হয়েছে.

লিগ্যাসি ইঞ্জিনেও লম্বা একশিলা বিষয়বস্তুর সমস্যা রয়েছে। বিষয়বস্তু একচেটিয়া হয় যদি এটি একাধিক খণ্ডে বিভক্ত হওয়ার যোগ্য না হয়। ওভারফ্লো স্ক্রোলিং সহ উপাদানগুলি একচেটিয়া, কারণ এটি একটি অ-আয়তাকার অঞ্চলে স্ক্রোল করা ব্যবহারকারীদের পক্ষে বোঝা যায় না। লাইন বক্স এবং ছবি একশিলা বিষয়বস্তুর অন্যান্য উদাহরণ। এখানে একটি উদাহরণ:

যদি একচেটিয়া বিষয়বস্তুর অংশটি একটি কলামের মধ্যে ফিট করার জন্য খুব বেশি লম্বা হয়, তাহলে লিগ্যাসি ইঞ্জিন নিষ্ঠুরভাবে এটিকে টুকরো টুকরো করে ফেলবে (স্ক্রোলযোগ্য কন্টেইনারটি স্ক্রোল করার চেষ্টা করার সময় খুব "আকর্ষণীয়" আচরণের দিকে নিয়ে যায়):

এটিকে প্রথম কলাম ওভারফ্লো করার পরিবর্তে (যেমন এটি লেআউটএনজি ব্লক ফ্র্যাগমেন্টেশনের সাথে করে):

ALT_TEXT_HERE

উত্তরাধিকার ইঞ্জিন জোরপূর্বক বিরতি সমর্থন করে। উদাহরণস্বরূপ, <div style="break-before:page;"> DIV এর আগে একটি পৃষ্ঠা বিরতি সন্নিবেশ করাবে৷ যাইহোক, এটি শুধুমাত্র সর্বোত্তম আনফোর্সড বিরতি খোঁজার জন্য সীমিত সমর্থন আছে। এটি break-inside:avoid এবং অনাথ এবং বিধবাকে সমর্থন করে, কিন্তু ব্লকের মধ্যে বিরতি এড়ানোর জন্য কোন সমর্থন নেই, যদি break-before:avoid । এই উদাহরণ বিবেচনা করুন:

পাঠ্য দুটি কলামে বিভক্ত।

এখানে, #multicol উপাদানটির প্রতিটি কলামে 5 লাইনের জন্য জায়গা রয়েছে (কারণ এটি 100px লম্বা, এবং লাইন-উচ্চতা 20px), তাই #firstchild এর সমস্ত প্রথম কলামে ফিট হতে পারে। যাইহোক, এর ভাইবোন #secondchild break-before:avoid আছে, যার অর্থ বিষয়বস্তু তাদের মধ্যে বিরতি না ঘটতে চায়। যেহেতু widows মান 2, তাই আমাদের বিরতি পরিহারের সমস্ত অনুরোধ মেনে নিতে #firstchild এর 2 লাইন দ্বিতীয় কলামে পুশ করতে হবে। ক্রোমিয়াম হল প্রথম ব্রাউজার ইঞ্জিন যা এই বৈশিষ্ট্যগুলির সমন্বয়কে সম্পূর্ণরূপে সমর্থন করে৷

কিভাবে NG ফ্র্যাগমেন্টেশন কাজ করে

এনজি লেআউট ইঞ্জিন সাধারণত সিএসএস বক্স ট্রি ডেপথ-প্রথম অতিক্রম করে ডকুমেন্ট তৈরি করে। যখন একটি নোডের সমস্ত বংশধরকে বিন্যস্ত করা হয়, তখন সেই নোডের বিন্যাসটি সম্পূর্ণ করা যেতে পারে, একটি NGPphysicalFragment তৈরি করে এবং প্যারেন্ট লেআউট অ্যালগরিদমে ফিরে এসে। সেই অ্যালগরিদমটি তার চাইল্ড ফ্র্যাগমেন্টের তালিকায় খণ্ডটিকে যুক্ত করে, এবং, একবার সমস্ত শিশু সম্পূর্ণ হয়ে গেলে, ভিতরে তার সমস্ত শিশু খণ্ড সহ নিজের জন্য একটি খণ্ড তৈরি করে৷ এই পদ্ধতির মাধ্যমে এটি সমগ্র নথির জন্য একটি খণ্ড গাছ তৈরি করে। যদিও এটি একটি অতি-সরলীকরণ: উদাহরণস্বরূপ, প্রবাহের বাইরে অবস্থানকারী উপাদানগুলিকে বিছিয়ে দেওয়ার আগে DOM ট্রিতে যেখান থেকে তারা বিদ্যমান সেখানে থেকে তাদের ধারণকৃত ব্লকে বাবল করতে হবে। আমি সরলতার জন্য এখানে এই উন্নত বিবরণ উপেক্ষা করছি।

সিএসএস বক্সের পাশাপাশি, লেআউটএনজি একটি লেআউট অ্যালগরিদমে একটি সীমাবদ্ধ স্থান প্রদান করে। এটি অ্যালগরিদমকে তথ্য প্রদান করে যেমন লেআউটের জন্য উপলব্ধ স্থান, একটি নতুন ফর্ম্যাটিং প্রসঙ্গ প্রতিষ্ঠিত হয়েছে কিনা এবং পূর্ববর্তী বিষয়বস্তু থেকে মধ্যবর্তী মার্জিন ভেঙে যাওয়া ফলাফল। সীমাবদ্ধ স্থানটি ফ্র্যাগমেন্টেনারের বিন্যস্ত ব্লক-আকার এবং বর্তমান ব্লকটি এতে অফসেট করে তাও জানে। এটি কোথায় ভাঙ্গতে হবে তা নির্দেশ করে।

যখন ব্লক ফ্র্যাগমেন্টেশন জড়িত থাকে, তখন বংশধরদের লেআউটটি বিরতিতে থামতে হয়। ভাঙার কারণগুলির মধ্যে রয়েছে পৃষ্ঠা বা কলামে স্থান ফুরিয়ে যাওয়া বা জোর করে বিরতি দেওয়া। তারপরে আমরা যে নোডগুলি পরিদর্শন করেছি তার জন্য আমরা টুকরো তৈরি করি এবং ফ্র্যাগমেন্টেশন প্রসঙ্গ রুট পর্যন্ত (মাল্টিকোল কন্টেইনার, বা, মুদ্রণের ক্ষেত্রে, নথি রুট) পর্যন্ত ফিরে আসি। তারপর, ফ্র্যাগমেন্টেশন কনটেক্সট রুটে, আমরা একটি নতুন ফ্র্যাগমেন্টেনারের জন্য প্রস্তুতি নিই, এবং আবার গাছে নেমে পড়ি, যেখানে আমরা বিরতির আগে ছেড়েছিলাম সেখানে আবার শুরু করি।

বিরতির পরে লেআউট পুনরায় শুরু করার উপায় প্রদানের জন্য গুরুত্বপূর্ণ ডেটা কাঠামোকে NGBlockBreakToken বলা হয়। এটি পরবর্তী ফ্র্যাগমেন্টেনারে সঠিকভাবে লেআউট পুনরায় শুরু করার জন্য প্রয়োজনীয় সমস্ত তথ্য ধারণ করে। একটি NGBlockBreakToken একটি নোডের সাথে যুক্ত, এবং এটি একটি NGBlockBreakToken ট্রি গঠন করে, যাতে প্রতিটি নোড যা পুনরায় চালু করা প্রয়োজন তা উপস্থাপন করা হয়। একটি NGBlockBreakToken NGPphysicalBoxFragment এর সাথে সংযুক্ত থাকে যা ভিতরে ভেঙ্গে যাওয়া নোডগুলির জন্য তৈরি হয়। ব্রেক টোকেনগুলি পিতামাতার কাছে প্রচার করা হয়, ব্রেক টোকেনের একটি গাছ তৈরি করে। যদি আমাদের একটি নোডের আগে ব্রেক করার প্রয়োজন হয় (এর ভিতরের পরিবর্তে), কোন টুকরো তৈরি করা হবে না, তবে প্যারেন্ট নোডকে এখনও নোডের জন্য একটি "ব্রেক-আগে" ব্রেক টোকেন তৈরি করতে হবে, যাতে আমরা যখন এটি তৈরি করা শুরু করতে পারি আমরা পরবর্তী ফ্র্যাগমেন্টেইনারে নোড ট্রিতে একই অবস্থানে পৌঁছেছি।

ব্রেক ঢোকানো হয় যখন আমাদের হয় ফ্র্যাগমেন্টেনার স্পেস শেষ হয়ে যায় (একটি আনফোর্সড ব্রেক), অথবা যখন জোর করে বিরতির অনুরোধ করা হয়।

সর্বোত্তম আনফোর্সড ব্রেকগুলির জন্য স্পেসিফিকেশনে নিয়ম রয়েছে এবং যেখানে আমাদের স্থান ফুরিয়ে যায় ঠিক সেখানে একটি বিরতি সন্নিবেশ করা সবসময় সঠিক কাজ নয়। উদাহরণস্বরূপ, break-before মতো বিভিন্ন CSS বৈশিষ্ট্য রয়েছে যা বিরতির অবস্থানের পছন্দকে প্রভাবিত করে।

লেআউটের সময়, আনফোর্সড ব্রেক স্পেসিফিকেশন বিভাগটি সঠিকভাবে বাস্তবায়ন করার জন্য, আমাদের সম্ভবত ভাল ব্রেকপয়েন্টগুলির ট্র্যাক রাখতে হবে। এই রেকর্ডের অর্থ হল আমরা ফিরে যেতে পারি এবং পাওয়া শেষ সম্ভাব্য সর্বোত্তম ব্রেকপয়েন্ট ব্যবহার করতে পারি, যদি আমাদের এমন একটি স্থানে স্থান ফুরিয়ে যায় যেখানে আমরা বিরতি পরিহার করার অনুরোধ লঙ্ঘন করি (উদাহরণস্বরূপ, break-before:avoid বা orphans:7 )। প্রতিটি সম্ভাব্য ব্রেকপয়েন্টকে একটি স্কোর দেওয়া হয়, "শুধুমাত্র শেষ অবলম্বন হিসাবে এটি করুন" থেকে "ব্রেক করার জন্য নিখুঁত জায়গা" পর্যন্ত, এর মধ্যে কিছু মান রয়েছে। যদি একটি বিরতির অবস্থান "নিখুঁত" হিসাবে স্কোর করে, এর মানে হল যে আমরা যদি সেখানে বিরতি করি তবে কোনও ভঙ্গকারী নিয়ম লঙ্ঘন করা হবে না (এবং যদি আমরা এই স্কোরটি ঠিক সেই সময়ে পাই যেখানে আমাদের স্থান ফুরিয়ে যায়, তাহলে আরও ভাল কিছুর জন্য পিছনে তাকানোর দরকার নেই। ) যদি স্কোরটি "শেষ-অবলম্বন" হয়, তাহলে ব্রেকপয়েন্টটিও বৈধ নয়, তবে আমরা যদি আরও ভাল কিছু না পাই, তাহলে ফ্র্যাগমেন্টেনার ওভারফ্লো এড়াতে আমরা সেখানে বিরতি দিতে পারি।

বৈধ ব্রেকপয়েন্টগুলি সাধারণত শুধুমাত্র ভাইবোনদের (লাইন বক্স বা ব্লক) মধ্যে ঘটে এবং নয়, উদাহরণস্বরূপ, একজন পিতামাতা এবং তার প্রথম সন্তানের মধ্যে ( শ্রেণী C ব্রেকপয়েন্টগুলি একটি ব্যতিক্রম, তবে আমাদের এখানে সেগুলি নিয়ে আলোচনা করার দরকার নেই)। ব্রেক-বিফোর:এভয়েড সহ একটি ব্লক ভাইবোনের আগে উদাহরণ স্বরূপ একটি বৈধ ব্রেকপয়েন্ট রয়েছে , তবে এটি "পারফেক্ট" এবং "শেষ-অবলম্বন" এর মধ্যে কোথাও।

লেআউটের সময় আমরা NGEarlyBreak নামক একটি কাঠামোতে এখন পর্যন্ত পাওয়া সেরা ব্রেকপয়েন্টের ট্র্যাক রাখি। একটি প্রারম্ভিক বিরতি একটি ব্লক নোডের আগে বা ভিতরে, বা একটি লাইনের আগে (হয় একটি ব্লক কন্টেইনার লাইন, বা একটি ফ্লেক্স লাইন) একটি সম্ভাব্য ব্রেকপয়েন্ট। আমরা NGEarlyBreak অবজেক্টগুলির একটি চেইন বা পথ তৈরি করতে পারি, যদি আমাদের স্থান ফুরিয়ে যাওয়ার সময় আমরা আগে হেঁটে গিয়েছিলাম এমন কিছুর ভিতরে সবচেয়ে ভাল ব্রেকপয়েন্টটি রয়েছে। এখানে একটি উদাহরণ:

এই ক্ষেত্রে, আমাদের #second ঠিক আগে স্থান ফুরিয়ে যায়, কিন্তু এতে "ব্রেক-ফোর:এভয়েড" আছে, যা "ভায়োলটিং ব্রেক এভয়েড" এর ব্রেক লোকেশন স্কোর পায়। সেই মুহুর্তে আমাদের কাছে "নিখুঁত" সহ "লাইন 3"' এর আগে "ভিতরে #outer > ভিতরে #middle > ভিতরে #inner ভিতরের > এর একটি NGEarlyBreak চেইন আছে, তাই আমরা বরং সেখানে ভাঙব। তাই আমাদের ফিরে আসতে হবে এবং পুনরায় দৌড়াতে হবে। #outer এর শুরু থেকে লেআউট (এবং এবার আমরা যে NGEarlyBreak পেয়েছি), যাতে আমরা #inner এ "লাইন 3" এর আগে ব্রেক করতে পারি (আমরা "লাইন 3" এর আগে ভেঙে ফেলি, যাতে বাকি 4 লাইন শেষ হয় পরবর্তী অংশে, এবং widows:4 ।)

অ্যালগরিদমটি সর্বদা সর্বোত্তম সম্ভাব্য ব্রেকপয়েন্টে বিরতি দেওয়ার জন্য ডিজাইন করা হয়েছে — যেমনটি নির্দিষ্টকরণে সংজ্ঞায়িত করা হয়েছে — সঠিক ক্রমে নিয়মগুলি বাদ দিয়ে, যদি সেগুলি সব সন্তুষ্ট না হয়। মনে রাখবেন যে প্রতি খণ্ডিত প্রবাহে আমাদের শুধুমাত্র একবারে পুনরায় লেআউট করতে হবে। যখন আমরা দ্বিতীয় লেআউট পাসে আছি, ততক্ষণে সর্বোত্তম বিরতি অবস্থানটি ইতিমধ্যেই লেআউট অ্যালগরিদমগুলিতে পাস করা হয়েছে, এটি সেই বিরতি অবস্থান যা প্রথম লেআউট পাসে আবিষ্কৃত হয়েছিল এবং সেই রাউন্ডে লেআউট আউটপুটের অংশ হিসাবে সরবরাহ করা হয়েছিল৷ দ্বিতীয় লেআউট পাসে, আমাদের স্থান ফুরিয়ে না যাওয়া পর্যন্ত আমরা লেআউট করছি না—আসলে আমাদের কাছে স্থান ফুরিয়ে যাওয়ার আশা করা যায় না (এটি আসলে একটি ত্রুটি হবে), কারণ আমাদেরকে একটি সুপার-সুইট সরবরাহ করা হয়েছে (আচ্ছা, যতটা মিষ্টি পাওয়া যায়) একটি প্রারম্ভিক বিরতি ঢোকানোর জায়গা, অপ্রয়োজনীয়ভাবে কোনও ভাঙার নিয়ম লঙ্ঘন এড়াতে। তাই আমরা শুধু যে বিন্দু আউট রাখা, এবং বিরতি.

সেই নোটে, কখনও কখনও আমাদের কিছু বিরতি এড়ানোর অনুরোধ লঙ্ঘন করতে হবে, যদি এটি ফ্র্যাগমেন্টেনার ওভারফ্লো এড়াতে সহায়তা করে। যেমন:

এখানে, আমাদের #second ঠিক আগে স্থান ফুরিয়ে যায়, কিন্তু এতে "ব্রেক-ফোর:এভয়ড" আছে। শেষ উদাহরণের মতোই এটি "ভায়লেটিং ব্রেক এভয়েড"-এ অনুবাদ করা হয়েছে। আমাদের কাছে "অনাথ এবং বিধবাদের লঙ্ঘন" সহ একটি NGEarlyBreak আছে ( #first > "লাইন 2" এর আগে), যা এখনও নিখুঁত নয়, তবে "ভায়োলটিং ব্রেক এড়িয়ে যাওয়া" থেকে ভাল। তাই আমরা এতিম/বিধবাদের অনুরোধ লঙ্ঘন করে "লাইন 2" এর আগে বিরতি দেব। স্পেক 4.4 এ এটির সাথে ডিল করে। আনফোর্সড ব্রেকস , যেখানে এটি সংজ্ঞায়িত করে যে ফ্র্যাগমেন্টেনার ওভারফ্লো এড়াতে যদি আমাদের কাছে পর্যাপ্ত ব্রেকপয়েন্ট না থাকে তবে কোন ব্রেকিং নিয়মগুলি প্রথমে উপেক্ষা করা হবে।

উপসংহার

লেআউটএনজি ব্লক ফ্র্যাগমেন্টেশন প্রজেক্টের কার্যকরী লক্ষ্য ছিল লেগাসি ইঞ্জিন সমর্থন করে এমন সবকিছুর লেআউটএনজি-আর্কিটেকচার-সহায়ক বাস্তবায়ন প্রদান করা এবং বাগ ফিক্স ব্যতীত যতটা সম্ভব কম। প্রধান ব্যতিক্রম হল আরও ভাল বিরতি পরিহার সমর্থন (উদাহরণস্বরূপ break-before:avoid ), কারণ এটি ফ্র্যাগমেন্টেশন ইঞ্জিনের একটি মূল অংশ, তাই এটিকে শুরু থেকেই সেখানে থাকতে হয়েছিল, কারণ এটি পরে যোগ করার অর্থ আরেকটি পুনর্লিখন হবে।

এখন যেহেতু LayoutNG ব্লক ফ্র্যাগমেন্টেশন শেষ হয়েছে, আমরা নতুন কার্যকারিতা যোগ করার জন্য কাজ শুরু করতে পারি, যেমন প্রিন্ট করার সময় মিশ্র পৃষ্ঠার আকার সমর্থন করা, মুদ্রণের সময় @page মার্জিন বক্স, box-decoration-break:clone এবং আরও অনেক কিছু। এবং সাধারণভাবে LayoutNG এর মতো, আমরা আশা করি নতুন সিস্টেমের বাগ রেট এবং রক্ষণাবেক্ষণের বোঝা সময়ের সাথে উল্লেখযোগ্যভাবে কম হবে।

স্বীকৃতি