ব্রাউজার কীভাবে কাজ করে

আধুনিক ওয়েব ব্রাউজারের নেপথ্য কাহিনি

প্রস্তাবনা

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

একজন ওয়েব ডেভেলপার হিসেবে, ব্রাউজার অপারেশনের ইন্টার্নাল সম্পর্কে জানা আপনাকে আরও ভালো সিদ্ধান্ত নিতে এবং ডেভেলপমেন্টের সেরা পদ্ধতির পিছনে যুক্তি বুঝতে সাহায্য করে। যদিও এটি একটি দীর্ঘ ডকুমেন্ট, আমরা সাজেস্ট করি যে আপনি এটি খুঁটিয়ে দেখার জন্য কিছুটা সময় ব্যয় করুন। আপনি এটি করার জন্য আনন্দিত হবেন।

পল আইরিশ, Chrome ডেভেলপার রিলেশন

ভূমিকা

ওয়েব ব্রাউজার হল সবচেয়ে বেশি ব্যবহৃত সফ্টওয়্যার। এই প্রাইমারে, আমি ব্যাখ্যা করব যে এগুলি পর্দার আড়ালে কীভাবে কাজ করে। ব্রাউজার স্ক্রিনে Google পৃষ্ঠা না দেখা পর্যন্ত অ্যাড্রেস বারে google.com টাইপ করলে কী হয় তা আমরা দেখব।

আমরা যেসব ব্রাউজার নিয়ে কথা বলব

বর্তমানে ডেস্কটপে পাঁচটি প্রধান ব্রাউজার ব্যবহার করা হয়: Chrome, Internet Explorer, Firefox, Safari এবং Opera। মোবাইলে প্রধান ব্রাউজারগুলি হল Android Browser, iPhone, Opera Mini এবং Opera Mobile, UC Browser, Nokia S40/S60 ব্রাউজার এবং Chrome, যার সবকটিই Opera ব্রাউজার ছাড়া WebKit-এর উপর ভিত্তি করে তৈরি। আমি ওপেন সোর্স ব্রাউজার Firefox ও Chrome এবং Safari (যা আংশিকভাবে ওপেন সোর্স) থেকে উদাহরণ দেব। StatCounter পরিসংখ্যান (জুন ২০১৩ পর্যন্ত) অনুযায়ী, বিশ্বব্যাপী ডেস্কটপ ব্রাউজার ব্যবহারের প্রায় ৭১% Chrome, Firefox ও Safari-র দখলে। মোবাইলে, Android ব্রাউজার, iPhone এবং Chrome-এর ব্যবহার প্রায় ৫৪%।

ব্রাউজারের প্রধান কার্যকারিতা

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

ব্রাউজার যেভাবে HTML ফাইল ব্যাখ্যা করে এবং দেখায় তা HTML এবং CSS স্পেসিফিকেশনে উল্লেখ করা আছে। এইসব স্পেসিফিকেশন W3C (World Wide Web Consortium) সংস্থা দ্বারা পরিচালিত হয়, যা হল ওয়েবের জন্য স্ট্যান্ডার্ড সংস্থা। বহু বছর ধরে ব্রাউজারগুলি স্পেসিফিকেশনের শুধুমাত্র একটি অংশ মেনে চলে এবং নিজস্ব এক্সটেনশন ডেভেলপ করে। এর ফলে ওয়েব লেখকদের জন্য গুরুতর কম্প্যাটিবিলিটি সংক্রান্ত সমস্যা দেখা দেয়। আজকাল বেশিরভাগ ব্রাউজারই কম-বেশি স্পেসিফিকেশন মেনে চলে।

ব্রাউজার ইউজার ইন্টারফেসের মধ্যে অনেক মিল আছে। সাধারণ ইউজার ইন্টারফেস এলিমেন্টের মধ্যে রয়েছে:

  1. URI যোগ করার জন্য অ্যাড্রেস বার
  2. ফিরে যাওয়া ও এগিয়ে যাওয়ার বোতাম
  3. বুকমার্ক করার বিকল্প
  4. বর্তমান ডকুমেন্ট রিফ্রেশ বা লোড করা বন্ধ করার জন্য রিফ্রেশ ও বন্ধ করার বোতাম
  5. হোম বোতাম যা আপনাকে হোম পেজে নিয়ে যায়

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

উচ্চ-স্তরের পরিকাঠামো

ব্রাউজারের প্রধান কম্পোনেন্টগুলি হল:

  1. ইউজার ইন্টারফেস: এর মধ্যে অ্যাড্রেস বার, পিছনে/সামনে যাওয়ার বোতাম, বুকমার্কিং মেনু ইত্যাদি পড়ে। ব্রাউজার ডিসপ্লের প্রতিটি অংশ, শুধু যে উইন্ডোতে আপনি অনুরোধ করা পৃষ্ঠা দেখছেন সেটি বাদে।
  2. ব্রাউজার ইঞ্জিন: UI ও রেন্ডারিং ইঞ্জিনের মধ্যে অ্যাকশন মার্শাল করে।
  3. রেন্ডারিং ইঞ্জিন: অনুরোধ করা কন্টেন্ট দেখানোর জন্য দায়ী। যেমন, অনুরোধ করা কন্টেন্ট HTML হলে, রেন্ডারিং ইঞ্জিন HTML ও CSS পার্স করে এবং পার্স করা কন্টেন্ট স্ক্রিনে দেখায়।
  4. নেটওয়ার্কিং: HTTP অনুরোধের মতো নেটওয়ার্ক কলের জন্য, প্ল্যাটফর্ম-নিরপেক্ষ ইন্টারফেসের পিছনে বিভিন্ন প্ল্যাটফর্মের জন্য বিভিন্ন ইমপ্লিমেন্টেশন ব্যবহার করা।
  5. UI ব্যাকএন্ড: কম্বো বক্স ও উইন্ডোর মতো বেসিক উইজেট আঁকার জন্য ব্যবহার করা হয়। এই ব্যাকএন্ড একটি জেনেরিক ইন্টারফেস প্রকাশ করে যা প্ল্যাটফর্ম নির্দিষ্ট নয়। এটি অপারেটিং সিস্টেমের ইউজার ইন্টারফেস পদ্ধতি ব্যবহার করে।
  6. জাভাস্ক্রিপ্ট ইন্টারপ্রেটার। জাভাস্ক্রিপ্ট কোড পার্স ও এক্সিকিউট করতে ব্যবহার করা হয়।
  7. ডেটা স্টোরেজ। এটি একটি পারসিস্টেন্স লেয়ার। ব্রাউজারকে কুকির মতো সব ধরনের ডেটা স্থানীয়ভাবে সেভ করতে হতে পারে। এছাড়াও, ব্রাউজার localStorage, IndexedDB, WebSQL ও FileSystem-এর মতো স্টোরেজ মেকানিজম সাপোর্ট করে।
ব্রাউজার কম্পোনেন্ট
ছবি ১: ব্রাউজার কম্পোনেন্ট

মনে রাখবেন, Chrome-এর মতো ব্রাউজার রেন্ডারিং ইঞ্জিনের একাধিক ইনস্ট্যান্স চালায়: প্রতিটি ট্যাবের জন্য একটি করে। প্রতিটি ট্যাব আলাদা প্রসেসে চলে।

রেন্ডারিং ইঞ্জিন

রেন্ডারিং ইঞ্জিনের কাজ হল… রেন্ডার করা, অর্থাৎ ব্রাউজার স্ক্রিনে অনুরোধ করা কন্টেন্ট দেখানো।

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

বিভিন্ন ব্রাউজার বিভিন্ন রেন্ডারিং ইঞ্জিন ব্যবহার করে: Internet Explorer ব্যবহার করে Trident, Firefox ব্যবহার করে Gecko, Safari ব্যবহার করে WebKit। Chrome এবং Opera (ভার্সন 15 থেকে) Blink ব্যবহার করে, যা WebKit-এর একটি ফর্ক।

WebKit হল একটি ওপেন সোর্স রেন্ডারিং ইঞ্জিন যা Linux প্ল্যাটফর্মের জন্য একটি ইঞ্জিন হিসেবে শুরু হয়েছিল এবং Mac ও Windows-এ কাজ করার জন্য Apple দ্বারা পরিবর্তিত হয়েছিল।

মূল ফ্লো

রেন্ডারিং ইঞ্জিন নেটওয়ার্কিং লেয়ার থেকে অনুরোধ করা ডকুমেন্টের কন্টেন্ট পাওয়া শুরু করবে। এটি সাধারণত ৮কেবি চাঙ্কে করা হবে।

এর পরে, রেন্ডারিং ইঞ্জিনের বেসিক ফ্লো হল:

ইঞ্জিনের প্রাথমিক ফ্লো রেন্ডার করা হচ্ছে
ছবি ২: রেন্ডারিং ইঞ্জিনের বেসিক ফ্লো

রেন্ডারিং ইঞ্জিন HTML ডকুমেন্ট পার্স করা শুরু করবে এবং এলিমেন্টগুলিকে "কন্টেন্ট ট্রি" নামক একটি ট্রিতে DOM নোডে কনভার্ট করবে। এক্সটার্নাল CSS ফাইল এবং স্টাইল এলিমেন্ট, দুটিতেই ইঞ্জিন স্টাইল ডেটা পার্স করবে। HTML-এ ভিজ্যুয়াল নির্দেশাবলীর সাথে স্টাইলিং তথ্য ব্যবহার করে আরেকটি ট্রি তৈরি করা হবে: রেন্ডার ট্রি।

রেন্ডার ট্রিতে রঙ ও ডাইমেনশনের মতো ভিজ্যুয়াল অ্যাট্রিবিউট সহ আয়তক্ষেত্র থাকে। স্ক্রিনে দেখানোর জন্য আয়তক্ষেত্রগুলি সঠিক ক্রমে আছে।

রেন্ডার ট্রি তৈরি হওয়ার পরে এটি "লেআউট" প্রসেসের মধ্যে দিয়ে যায়। এর অর্থ হল, প্রতিটি নোডকে স্ক্রিনে ঠিক কোথায় দেখাতে হবে তার সঠিক কোঅর্ডিনেট দেওয়া। পরবর্তী ধাপ হল পেন্টিং - রেন্ডার ট্রি ট্রাভার্স করা হবে এবং UI ব্যাকএন্ড লেয়ার ব্যবহার করে প্রতিটি নোড পেন্ট করা হবে।

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

প্রধান ফ্লোর উদাহরণ

WebKit-এর মূল ফ্লো।
ছবি ৩: WebKit-এর মূল ফ্লো
Mozilla-র Gecko রেন্ডারিং ইঞ্জিনের মূল ফ্লো।
ছবি ৪: Mozilla-র Gecko রেন্ডারিং ইঞ্জিনের মূল ফ্লো

ছবি ৩ ও ৪ থেকে আপনি দেখতে পাবেন যে WebKit ও Gecko কিছুটা আলাদা পরিভাষা ব্যবহার করলেও, ফ্লো মূলত একই।

Gecko ভিজ্যুয়ালি ফর্ম্যাট করা এলিমেন্টের ট্রিকে "ফ্রেম ট্রি" বলে। প্রতিটি এলিমেন্ট হল একটি ফ্রেম। WebKit "Render Tree" শব্দটি ব্যবহার করে এবং এটি "Render Objects" নিয়ে গঠিত। WebKit এলিমেন্ট প্লেস করার জন্য "লেআউট" শব্দটি ব্যবহার করে, যেখানে Gecko এটিকে "রিফ্লো" বলে। "Attachment" হল WebKit-এর একটি শব্দ যা DOM নোড এবং ভিজ্যুয়াল তথ্যকে সংযুক্ত করে রেন্ডার ট্রি তৈরি করে। একটি ছোট নন-সিম্যান্টিক পার্থক্য হল যে Gecko-এর HTML এবং DOM ট্রির মধ্যে একটি অতিরিক্ত লেয়ার রয়েছে। এটিকে "কন্টেন্ট সিঙ্ক" বলা হয় এবং এটি DOM এলিমেন্ট তৈরি করার ফ্যাক্টরি। আমরা ফ্লোয়ের প্রতিটি অংশ সম্পর্কে আলোচনা করব:

পার্সিং - সাধারণ

যেহেতু রেন্ডারিং ইঞ্জিনের মধ্যে পার্সিং একটি অত্যন্ত গুরুত্বপূর্ণ প্রক্রিয়া, তাই আমরা এটি আরও একটু গভীরভাবে আলোচনা করব। পার্সিং সম্পর্কে একটু জেনে নেওয়া যাক।

কোনও ডকুমেন্ট পার্স করার অর্থ হল, কোড ব্যবহার করতে পারে এমন স্ট্রাকচারে সেটিকে অনুবাদ করা। পার্সিংয়ের ফলাফল সাধারণত নোডের একটি ট্রি হয় যা ডকুমেন্টের স্ট্রাকচারকে দেখায়। একে পার্স ট্রি বা সিনট্যাক্স ট্রি বলা হয়।

যেমন, 2 + 3 - 1 এক্সপ্রেশন পার্স করলে এই ট্রি পাওয়া যেতে পারে:

গাণিতিক এক্সপ্রেশন ট্রি নোড।
ছবি ৫: গাণিতিক এক্সপ্রেশন ট্রি নোড

ব্যাকরণ

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

পার্সার - লেক্সার কম্বিনেশন

পার্সিংকে দুটি সাব-প্রসেসে ভাগ করা যেতে পারে: লেক্সিক্যাল বিশ্লেষণ ও সিনট্যাক্স বিশ্লেষণ।

লেক্সিক্যাল বিশ্লেষণ হল ইনপুটকে টোকেনে বিভক্ত করার প্রক্রিয়া। টোকেন হল ভাষার শব্দভাণ্ডার: বৈধ বিল্ডিং ব্লকের সংগ্রহ। মানুষের ভাষার ক্ষেত্রে, সেই ভাষার অভিধানে থাকা সব শব্দ এতে অন্তর্ভুক্ত থাকবে।

সিনট্যাক্স বিশ্লেষণ হল ভাষার সিনট্যাক্স নিয়ম প্রয়োগ করা।

পার্সার সাধারণত দুটি কম্পোনেন্টের মধ্যে কাজ ভাগ করে নেয়: লেক্সার (কখনও কখনও টোকেনাইজার বলা হয়) যা ইনপুটকে সঠিক টোকেনে ভাগ করার জন্য দায়ী এবং পার্সার যা ভাষার সিনট্যাক্স নিয়ম অনুযায়ী ডকুমেন্ট স্ট্রাকচার বিশ্লেষণ করে পার্স ট্রি তৈরি করার জন্য দায়ী।

লেক্সার জানে কীভাবে হোয়াইট স্পেস এবং লাইন ব্রেকের মতো অপ্রাসঙ্গিক অক্ষরগুলি বাদ দিতে হয়।

সোর্স ডকুমেন্ট থেকে পার্স ট্রি
ছবি ৬: সোর্স ডকুমেন্ট থেকে পার্স ট্রি

পার্সিং প্রসেসটি পুনরাবৃত্তিমূলক। পার্সার সাধারণত লেক্সারকে নতুন টোকেনের জন্য অনুরোধ করে এবং সিনট্যাক্স নিয়মের সাথে টোকেনটি মেলানোর চেষ্টা করে। কোনও নিয়ম মিলে গেলে, টোকেনের সাথে সংশ্লিষ্ট নোড পার্স ট্রিতে যোগ করা হবে এবং পার্সার আরেকটি টোকেন চাইবে।

কোনও নিয়ম ম্যাচ না করলে, পার্সার ইন্টার্নালি টোকেন স্টোর করবে এবং ইন্টার্নালি স্টোর করা সব টোকেনের সাথে ম্যাচ করে এমন কোনও নিয়ম খুঁজে না পাওয়া পর্যন্ত টোকেন চাইতে থাকবে। কোনও নিয়ম খুঁজে না পাওয়া গেলে, পার্সার একটি ব্যতিক্রম দেখাবে। এর অর্থ হল, ডকুমেন্টটি সঠিক ছিল না এবং এতে সিনট্যাক্স সংক্রান্ত ভুল ছিল।

অনুবাদ

অনেক ক্ষেত্রে পার্স ট্রি চূড়ান্ত প্রোডাক্ট নয়। অনুবাদে প্রায়ই পার্সিং ব্যবহার করা হয়: ইনপুট ডকুমেন্টকে অন্য ফর্ম্যাটে পরিবর্তন করা। উদাহরণ হল কম্পাইলেশন। কম্পাইলার, যা সোর্স কোডকে মেশিন কোডে কম্পাইল করে, প্রথমে এটিকে একটি পার্স ট্রিতে পার্স করে এবং তারপরে ট্রিটিকে একটি মেশিন কোড ডকুমেন্টে অনুবাদ করে।

কম্পাইলেশন ফ্লো
ছবি ৭: কম্পাইলেশন ফ্লো

পার্সিংয়ের উদাহরণ

ছবি ৫-এ আমরা একটি গাণিতিক এক্সপ্রেশন থেকে পার্স ট্রি তৈরি করেছি। আসুন, একটি সহজ গাণিতিক ভাষা সংজ্ঞায়িত করার চেষ্টা করি এবং পার্স করার প্রসেসটি দেখি।

সিনট্যাক্স:

  1. ভাষার সিনট্যাক্স বিল্ডিং ব্লক হল এক্সপ্রেশন, টার্ম ও অপারেশন।
  2. আমাদের ভাষায় যেকোনও সংখ্যক এক্সপ্রেশন থাকতে পারে।
  3. একটি এক্সপ্রেশনকে "টার্ম" হিসেবে সংজ্ঞায়িত করা হয় যার পরে একটি "অপারেশন" এবং তারপরে আরেকটি টার্ম থাকে
  4. অপারেশন হল প্লাস টোকেন বা মাইনাস টোকেন
  5. টার্ম হল একটি পূর্ণসংখ্যা টোকেন বা এক্সপ্রেশন

আসুন, ইনপুট 2 + 3 - 1 বিশ্লেষণ করা যাক।

নিয়মের সাথে মিলে যাওয়া প্রথম সাবস্ট্রিং হল 2: নিয়ম #৫ অনুযায়ী এটি একটি শব্দ। দ্বিতীয় ম্যাচ হল 2 + 3: এটি তৃতীয় নিয়মের সাথে মেলে: একটি শব্দ, তারপরে একটি অপারেশন, তারপরে আরেকটি শব্দ। ইনপুটের শেষে পরবর্তী ম্যাচটি হিট করা হবে। 2 + 3 - 1 হল একটি এক্সপ্রেশন কারণ আমরা আগে থেকেই জানি যে 2 + 3 হল একটি টার্ম, তাই আমাদের কাছে একটি টার্ম আছে যার পরে একটি অপারেশন এবং তারপরে আরেকটি টার্ম আছে। 2 + + কোনও নিয়মের সাথে মিলবে না এবং তাই এটি ভুল ইনপুট।

শব্দভাণ্ডার ও সিনট্যাক্সের জন্য ফর্মাল সংজ্ঞা

শব্দভাণ্ডার সাধারণত রেগুলার এক্সপ্রেশন দ্বারা প্রকাশ করা হয়।

যেমন, আমাদের ভাষা এইভাবে সংজ্ঞায়িত করা হবে:

INTEGER: 0|[1-9][0-9]*
PLUS: +
MINUS: -

আপনি দেখতে পাচ্ছেন, পূর্ণসংখ্যা রেগুলার এক্সপ্রেশন দ্বারা সংজ্ঞায়িত করা হয়।

সিনট্যাক্স সাধারণত BNF নামক ফর্ম্যাটে সংজ্ঞায়িত করা হয়। আমাদের ভাষা এইভাবে সংজ্ঞায়িত করা হবে:

expression :=  term  operation  term
operation :=  PLUS | MINUS
term := INTEGER | expression

আমরা বলেছি যে কোনও ভাষার ব্যাকরণ যদি প্রসঙ্গ-মুক্ত ব্যাকরণ হয় তবে এটি নিয়মিত পার্সার দ্বারা পার্স করা যেতে পারে। প্রসঙ্গ-মুক্ত ব্যাকরণের একটি স্বজ্ঞাত সংজ্ঞা হল একটি ব্যাকরণ যা সম্পূর্ণরূপে BNF-এ প্রকাশ করা যেতে পারে। আনুষ্ঠানিক সংজ্ঞার জন্য কন্টেক্সট-ফ্রি গ্রামার সম্পর্কে Wikipedia-র নিবন্ধ দেখুন

পার্সারের ধরন

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

আসুন দেখে নেওয়া যাক, দুই ধরনের পার্সার কীভাবে আমাদের উদাহরণ পার্স করবে।

টপ ডাউন পার্সার উচ্চ লেভেলের নিয়ম থেকে শুরু করবে: এটি 2 + 3-কে এক্সপ্রেশন হিসেবে শনাক্ত করবে। এটি তখন 2 + 3 - 1-কে একটি এক্সপ্রেশন হিসেবে শনাক্ত করবে (এক্সপ্রেশন শনাক্ত করার প্রক্রিয়াটি বিকশিত হয়, অন্যান্য নিয়মের সাথে মিলে যায়, তবে শুরুর পয়েন্টটি হল সর্বোচ্চ স্তরের নিয়ম)।

কোনও নিয়ম ম্যাচ না করা পর্যন্ত বটম-আপ পার্সার ইনপুট স্ক্যান করবে। তারপর এটি নিয়মের সাথে ম্যাচ করা ইনপুট পরিবর্তন করবে। ইনপুট শেষ না হওয়া পর্যন্ত এটি চলতে থাকবে। আংশিকভাবে মিলে যাওয়া এক্সপ্রেশন পার্সারের স্ট্যাকে রাখা হয়।

স্ট্যাক করুন ইনপুট
২ + ৩ - ১
শব্দ + ৩ - ১
টার্ম অপারেশন ৩ - ১
এক্সপ্রেশন - ১
এক্সপ্রেশন অপারেশন 1
এক্সপ্রেশন -

এই ধরনের বটম-আপ পার্সারকে শিফ্ট-রিডিউস পার্সার বলা হয়, কারণ ইনপুট ডানদিকে শিফ্ট করা হয় (মনে করুন, একটি পয়েন্টার প্রথমে ইনপুটের শুরুতে পয়েন্ট করছে এবং ডানদিকে সরছে) এবং ধীরে ধীরে সিনট্যাক্স নিয়মে রিডিউস করা হয়।

অটোমেটিক পার্সার জেনারেট করা হচ্ছে

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

WebKit দুটি সুপরিচিত পার্সার জেনারেটর ব্যবহার করে: লেক্সার তৈরি করার জন্য Flex এবং পার্সার তৈরি করার জন্য Bison (আপনি Lex এবং Yacc নামে এগুলি দেখতে পেতে পারেন)। Flex ইনপুট হল এমন একটি ফাইল যাতে টোকেনের রেগুলার এক্সপ্রেশন সংজ্ঞা থাকে। Bison-এর ইনপুট হল BNF ফর্ম্যাটে ভাষার সিনট্যাক্স সংক্রান্ত নিয়ম।

HTML পার্সার

HTML পার্সারের কাজ হল HTML মার্কআপকে পার্স ট্রি হিসেবে পার্স করা।

HTML ব্যাকরণ

HTML-এর শব্দভাণ্ডার ও সিনট্যাক্স W3C সংস্থার তৈরি করা স্পেসিফিকেশনে সংজ্ঞায়িত করা আছে।

পার্সিংয়ের ভূমিকায় আমরা যেমন দেখেছি, BNF-এর মতো ফর্ম্যাট ব্যবহার করে ব্যাকরণগত সিনট্যাক্স আনুষ্ঠানিকভাবে সংজ্ঞায়িত করা যেতে পারে।

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

HTML - DTD (ডকুমেন্টের ধরন সংক্রান্ত সংজ্ঞা) সংজ্ঞায়িত করার জন্য একটি ফর্মাল ফর্ম্যাট আছে - তবে এটি প্রসঙ্গ-মুক্ত ব্যাকরণ নয়।

প্রথম দেখায় এটি অদ্ভুত মনে হতে পারে; HTML আসলে XML-এর কাছাকাছি। অনেক XML পার্সার উপলভ্য আছে। HTML-এর একটি XML ভেরিয়েশন আছে - XHTML - তাহলে বড় পার্থক্যটা কী?

পার্থক্য হল, HTML পদ্ধতি অনেক বেশি "সহজ": এটি আপনাকে নির্দিষ্ট কিছু ট্যাগ বাদ দিতে দেয় (যেগুলি পরে অন্তর্নিহিতভাবে যোগ করা হয়) অথবা কখনও কখনও শুরু বা শেষের ট্যাগ বাদ দিতে দেয় এবং আরও অনেক কিছু। XML-এর কঠোর ও জটিল সিনট্যাক্সের তুলনায় এটি একটি "সহজ" সিনট্যাক্স।

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

HTML DTD

HTML সংজ্ঞা DTD ফর্ম্যাটে আছে। এই ফর্ম্যাট SGML ফ্যামিলির ভাষা নির্ধারণ করতে ব্যবহার করা হয়। এই ফর্ম্যাটে অনুমোদিত সব এলিমেন্ট, তাদের অ্যাট্রিবিউট ও ক্রমের সংজ্ঞা থাকে। আমরা আগেই দেখেছি যে HTML DTD কোনও প্রসঙ্গ-মুক্ত ব্যাকরণ তৈরি করে না।

DTD-এর কয়েকটি ভেরিয়েশন আছে। স্ট্রিক্ট মোড শুধুমাত্র স্পেসিফিকেশন মেনে চলে কিন্তু অন্যান্য মোডে অতীতে ব্রাউজার দ্বারা ব্যবহৃত মার্কআপের জন্য সহায়তা অন্তর্ভুক্ত থাকে। উদ্দেশ্য হল পুরনো কন্টেন্টের সাথে ব্যাকওয়ার্ড কম্প্যাটিবিলিটি। বর্তমান স্ট্রিক্ট DTD এখানে আছে: www.w3.org/TR/html4/strict.dtd

DOM

আউটপুট ট্রি ("পার্স ট্রি") হল DOM এলিমেন্ট ও অ্যাট্রিবিউট নোডের ট্রি। DOM হল ডকুমেন্ট অবজেক্ট মডেলের সংক্ষিপ্ত রূপ। এটি হল HTML ডকুমেন্টের অবজেক্ট প্রেজেন্টেশন এবং জাভাস্ক্রিপ্টের মতো বাইরের জগতের কাছে HTML এলিমেন্টের ইন্টারফেস।

ট্রি-এর রুট হল "ডকুমেন্ট" অবজেক্ট।

DOM-এর সাথে মার্কআপের প্রায় এক-টু-এক সম্পর্ক আছে। যেমন:

<html>
  <body>
    <p>
      Hello World
    </p>
    <div> <img src="example.png"/></div>
  </body>
</html>

এই মার্কআপ নিম্নলিখিত DOM ট্রি-তে অনুবাদ করা হবে:

উদাহরণস্বরূপ মার্কআপের DOM ট্রি
ছবি ৮: উদাহরণ মার্কআপের DOM ট্রি

HTML-এর মতো DOM-ও W3C সংস্থা দ্বারা নির্দিষ্ট করা হয়। www.w3.org/DOM/DOMTR দেখুন। এটি ডকুমেন্ট ম্যানিপুলেট করার জন্য একটি জেনেরিক স্পেসিফিকেশন। নির্দিষ্ট মডিউল HTML-এর নির্দিষ্ট এলিমেন্ট বর্ণনা করে। HTML-এর সংজ্ঞা এখানে পাওয়া যাবে: www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/idl-definitions.html.

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

পার্সিং অ্যালগরিদম

আগের বিভাগে আমরা যেমন দেখেছি, রেগুলার টপ ডাউন বা বটম আপ পার্সার ব্যবহার করে HTML পার্স করা যায় না।

কারণগুলি হল:

  1. ভাষার ক্ষমাশীল প্রকৃতি।
  2. ব্রাউজারে ভুল HTML-এর সুপরিচিত কেস সাপোর্ট করার জন্য প্রথাগত ত্রুটি সহনশীলতা রয়েছে।
  3. পার্সিং প্রসেসটি রিএন্ট্র্যান্ট। অন্যান্য ভাষার ক্ষেত্রে, পার্সিংয়ের সময় সোর্স পরিবর্তন হয় না, তবে HTML-এ, ডায়নামিক কোড (যেমন document.write() কল সহ স্ক্রিপ্ট এলিমেন্ট) অতিরিক্ত টোকেন যোগ করতে পারে, তাই পার্সিং প্রসেস আসলে ইনপুট পরিবর্তন করে।

নিয়মিত পার্সিং টেকনিক ব্যবহার করতে না পারার কারণে, ব্রাউজার HTML পার্স করার জন্য কাস্টম পার্সার তৈরি করে।

পার্সিং অ্যালগরিদম HTML5 স্পেসিফিকেশনে বিস্তারিতভাবে বর্ণনা করা হয়েছে। অ্যালগরিদমে দুটি ধাপ রয়েছে: টোকেনাইজেশন ও ট্রি কনস্ট্রাকশন।

টোকেনাইজেশন হল আভিধানিক বিশ্লেষণ, ইনপুটকে টোকেনে পার্স করা। HTML টোকেনের মধ্যে স্টার্ট ট্যাগ, এন্ড ট্যাগ, অ্যাট্রিবিউটের নাম ও অ্যাট্রিবিউটের ভ্যালু থাকে।

টোকেনাইজার টোকেনটি শনাক্ত করে, এটি ট্রি কনস্ট্রাক্টরকে দেয় এবং পরবর্তী টোকেন শনাক্ত করার জন্য পরবর্তী অক্ষরটি ব্যবহার করে এবং ইনপুটের শেষ না হওয়া পর্যন্ত এটি চলতে থাকে।

HTML পার্সিং ফ্লো (HTML5 স্পেসিফিকেশন থেকে নেওয়া)
ছবি ৯: HTML পার্সিং ফ্লো (HTML5 স্পেসিফিকেশন থেকে নেওয়া)

টোকেনাইজেশন অ্যালগরিদম

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

প্রাথমিক উদাহরণ - নিম্নলিখিত HTML টোকেনাইজ করা:

<html>
  <body>
    Hello world
  </body>
</html>

প্রাথমিক অবস্থা হল "ডেটা স্টেট"। < অক্ষরটি পাওয়া গেলে, স্ট্যাটাস পরিবর্তন করে "ট্যাগ ওপেন স্ট্যাটাস" করা হয়। a-z অক্ষর ব্যবহার করলে "ট্যাগ টোকেন শুরু করুন" তৈরি হয়, স্ট্যাটাস পরিবর্তন হয়ে "ট্যাগ নামের স্ট্যাটাস" হয়ে যায়। > অক্ষরটি ব্যবহার না করা পর্যন্ত আমরা এই অবস্থায় থাকি। প্রতিটি অক্ষর নতুন টোকেনের নামের শেষে যোগ করা হয়। আমাদের ক্ষেত্রে তৈরি করা টোকেনটি হল একটি html টোকেন।

> ট্যাগটি পৌঁছে গেলে, বর্তমান টোকেনটি নির্গত হয় এবং স্ট্যাটাসটি আবার "ডেটা স্ট্যাটাস"-এ পরিবর্তিত হয়। <body> ট্যাগ একই ধাপের মাধ্যমে ট্রিট করা হবে। এখনও পর্যন্ত html এবং body ট্যাগ এমিট করা হয়েছে। আমরা এখন আবার "ডেটা স্টেট"-এ ফিরে এসেছি। Hello world-এর H অক্ষর ব্যবহার করলে একটি অক্ষর টোকেন তৈরি ও নির্গত হবে, </body>-এর <-এ না পৌঁছানো পর্যন্ত এটি চলতে থাকবে। আমরা Hello world-এর প্রতিটি অক্ষরের জন্য একটি করে অক্ষর টোকেন ইস্যু করব।

আমরা এখন "ট্যাগ খোলা আছে" অবস্থায় ফিরে এসেছি। পরবর্তী ইনপুট / ব্যবহার করলে, একটি end tag token তৈরি হবে এবং "ট্যাগ নামের অবস্থা"-তে চলে যাবে। >-এ না পৌঁছানো পর্যন্ত আমরা এই অবস্থায় থাকব। তারপর নতুন ট্যাগ টোকেন নির্গত হবে এবং আমরা "ডেটা স্টেট"-এ ফিরে যাব। </html> ইনপুটকে আগের ঘটনার মতো করে বিবেচনা করা হবে।

উদাহরণ ইনপুট টোকেনাইজ করা হচ্ছে
ছবি ১০: উদাহরণ ইনপুট টোকেনাইজ করা

ট্রি কনস্ট্রাকশন অ্যালগরিদম

পার্সার তৈরি করা হলে ডকুমেন্ট অবজেক্ট তৈরি করা হয়। ট্রি কনস্ট্রাকশন স্টেজে, রুটে ডকুমেন্ট সহ DOM ট্রি পরিবর্তন করা হবে এবং এতে এলিমেন্ট যোগ করা হবে। টোকেনাইজারের মাধ্যমে নির্গত প্রতিটি নোড ট্রি কনস্ট্রাক্টরের মাধ্যমে প্রসেস করা হবে। প্রতিটি টোকেনের জন্য স্পেসিফিকেশন নির্ধারণ করে যে কোন DOM এলিমেন্ট এটির সাথে প্রাসঙ্গিক এবং এই টোকেনের জন্য তৈরি করা হবে। এলিমেন্টটি DOM ট্রি এবং খোলা এলিমেন্টের স্ট্যাকে যোগ করা হয়। নেস্টিং মিসম্যাচ ও বন্ধ না করা ট্যাগ ঠিক করতে এই স্ট্যাক ব্যবহার করা হয়। অ্যালগরিদমকে স্টেট মেশিন হিসেবেও বর্ণনা করা হয়। এই স্ট্যাটাসগুলিকে "ইনসার্শন মোড" বলা হয়।

ইনপুটের উদাহরণ হিসেবে ট্রি কনস্ট্রাকশন প্রসেস দেখা যাক:

<html>
  <body>
    Hello world
  </body>
</html>

টোকেনাইজেশন স্টেজের টোকেনের সিকোয়েন্স ট্রি কনস্ট্রাকশন স্টেজে ইনপুট হিসেবে ব্যবহার করা হয়। প্রথম মোডটি হল "প্রাথমিক মোড"। "html" টোকেন পেলে, "html-এর আগে" মোডে চলে যাবে এবং সেই মোডে টোকেন আবার প্রসেস করা হবে। এর ফলে HTMLHtmlElement এলিমেন্ট তৈরি হবে, যা রুট Document অবজেক্টে যোগ করা হবে।

অবস্থা পরিবর্তন করে "হেডের আগে" করা হবে। তারপর "বডি" টোকেন রিসিভ করা হয়। আমাদের কাছে "head" টোকেন না থাকলেও, একটি HTMLHeadElement ইমপ্লিসিটভাবে তৈরি করা হবে এবং এটি ট্রিতে যোগ করা হবে।

আমরা এখন "হেডারে" মোডে এবং তারপরে "হেডারের পরে" মোডে চলে যাব। বডি টোকেন আবার প্রসেস করা হয়, HTMLBodyElement তৈরি করে যোগ করা হয় এবং মোড "বডিতে" ট্রান্সফার করা হয়।

"Hello world" স্ট্রিংয়ের ক্যারেক্টার টোকেন এখন পাওয়া গেছে। প্রথমটি "টেক্সট" নোড তৈরি ও যোগ করবে এবং অন্যান্য অক্ষর সেই নোডে যোগ করা হবে।

বডি এন্ড টোকেন রিসিভ করার ফলে "আফটার বডি" মোডে ট্রান্সফার হবে। আমরা এখন html এন্ড ট্যাগ পাব যা আমাদের "আফটার আফটার বডি" মোডে নিয়ে যাবে। ফাইলের শেষে টোকেন পেলে পার্সিং শেষ হবে।

উদাহরণ HTML-এর ট্রি কনস্ট্রাকশন।
ছবি ১১: উদাহরণ html-এর ট্রি কনস্ট্রাকশন

পার্সিং শেষ হয়ে গেলে অ্যাকশন

এই পর্যায়ে ব্রাউজার ডকুমেন্টকে ইন্টার‌্যাক্টিভ হিসেবে চিহ্নিত করবে এবং "বিলম্বিত" মোডে থাকা স্ক্রিপ্ট পার্স করা শুরু করবে: যেগুলি ডকুমেন্ট পার্স করার পরে এক্সিকিউট করা উচিত। ডকুমেন্টের স্ট্যাটাস "সম্পূর্ণ" হিসেবে সেট করা হবে এবং "লোড" ইভেন্ট শুরু হবে।

আপনি HTML5 স্পেসিফিকেশনে টোকেনাইজেশন ও ট্রি কনস্ট্রাকশনের সম্পূর্ণ অ্যালগরিদম দেখতে পাবেন।

ব্রাউজারের ত্রুটি সহ্য করার ক্ষমতা

HTML পৃষ্ঠায় আপনি কখনই "ভুল সিনট্যাক্স" সংক্রান্ত সমস্যা দেখতে পাবেন না। ব্রাউজার যেকোনও ভুল কন্টেন্ট ঠিক করে এবং চলতে থাকে।

উদাহরণ হিসেবে এই HTML দেখুন:

<html>
  <mytag>
  </mytag>
  <div>
  <p>
  </div>
    Really lousy HTML
  </p>
</html>

আমি হয়ত প্রায় এক মিলিয়ন নিয়ম লঙ্ঘন করেছি ("mytag" কোনও স্ট্যান্ডার্ড ট্যাগ নয়, "p" ও "div" এলিমেন্টের ভুল নেস্টিং এবং আরও অনেক কিছু) কিন্তু ব্রাউজার এখনও এটি সঠিকভাবে দেখাচ্ছে এবং কোনও অভিযোগ করছে না। তাই পার্সার কোডের বেশিরভাগই HTML লেখকের ভুল সংশোধন করে।

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

HTML5 স্পেসিফিকেশন এই প্রয়োজনীয়তাগুলির মধ্যে কিছু সংজ্ঞায়িত করে। (WebKit এটি HTML পার্সার ক্লাসের শুরুতে কমেন্টে সুন্দরভাবে সারসংক্ষেপ করে।)

পার্সার টোকেনাইজ করা ইনপুটকে ডকুমেন্টে পার্স করে, ডকুমেন্ট ট্রি তৈরি করে। ডকুমেন্টটি সুগঠিত হলে, এটি পার্স করা সহজ।

দুর্ভাগ্যবশত, আমাদের এমন অনেক HTML ডকুমেন্ট ম্যানেজ করতে হয় যেগুলি ভালভাবে গঠিত নয়, তাই পার্সারকে ত্রুটি সম্পর্কে সহনশীল হতে হয়।

আমাদের অন্তত নিম্নলিখিত সমস্যার শর্তগুলি সমাধান করতে হবে:

  1. যে এলিমেন্ট যোগ করা হচ্ছে সেটি কিছু বাইরের ট্যাগের মধ্যে স্পষ্টভাবে নিষিদ্ধ করা হয়েছে। এই ক্ষেত্রে, যে ট্যাগটি এলিমেন্টকে নিষিদ্ধ করে, সেই ট্যাগ পর্যন্ত আমাদের সব ট্যাগ বন্ধ করে দিতে হবে এবং পরে এটি যোগ করতে হবে।
  2. আমাদের সরাসরি এলিমেন্ট যোগ করার অনুমতি নেই। এমন হতে পারে যে ডকুমেন্ট যিনি লিখেছেন তিনি মাঝখানে কোনও ট্যাগ দিতে ভুলে গেছেন (অথবা মাঝখানের ট্যাগটি ঐচ্ছিক)। নিম্নলিখিত ট্যাগের ক্ষেত্রে এটি হতে পারে: HTML HEAD BODY TBODY TR TD LI (আমি কি কোনওটি ভুলে গেছি?)।
  3. আমরা ইনলাইন এলিমেন্টের মধ্যে ব্লক এলিমেন্ট যোগ করতে চাই। পরবর্তী উচ্চতর ব্লক এলিমেন্ট পর্যন্ত সব ইনলাইন এলিমেন্ট বন্ধ করুন।
  4. এতে কাজ না হলে, এলিমেন্ট যোগ করার অনুমতি না পাওয়া পর্যন্ত এলিমেন্ট বন্ধ করুন - অথবা ট্যাগ উপেক্ষা করুন।

WebKit-এর ত্রুটি সহ্য করার ক্ষমতা সংক্রান্ত কিছু উদাহরণ দেখা যাক:

<br>-এর পরিবর্তে </br>

কিছু সাইট <br>-এর পরিবর্তে </br> ব্যবহার করে। IE এবং Firefox-এর সাথে মানানসই হওয়ার জন্য, WebKit এটিকে <br>-এর মতো বিবেচনা করে।

কোড:

if (t->isCloseTag(brTag) && m_document->inCompatMode()) {
     reportError(MalformedBRError);
     t->beginTag = true;
}

মনে রাখবেন যে সমস্যা ম্যানেজ করার বিষয়টি ইন্টার্নাল: এটি ব্যবহারকারীকে দেখানো হবে না।

একটি স্ট্রে টেবিল

স্ট্রে টেবিল হল অন্য টেবিলের মধ্যে থাকা টেবিল, তবে টেবিল সেলের মধ্যে নয়।

যেমন:

<table>
  <table>
    <tr><td>inner table</td></tr>
  </table>
  <tr><td>outer table</td></tr>
</table>

WebKit হায়ারার্কি পরিবর্তন করে দুটি সিবলিং টেবিল তৈরি করবে:

<table>
  <tr><td>outer table</td></tr>
</table>
<table>
  <tr><td>inner table</td></tr>
</table>

কোড:

if (m_inStrayTableContent && localName == tableTag)
        popBlock(tableTag);

WebKit বর্তমান এলিমেন্ট কন্টেন্টের জন্য স্ট্যাক ব্যবহার করে: এটি ইনার টেবিলকে আউটার টেবিল স্ট্যাক থেকে বের করে দেবে। টেবিলগুলি এখন সিবলিং হবে।

নেস্টেড ফর্ম এলিমেন্ট

ব্যবহারকারী যদি একটি ফর্মের মধ্যে আরেকটি ফর্ম রাখেন, তাহলে দ্বিতীয় ফর্মটি উপেক্ষা করা হয়।

কোড:

if (!m_currentFormElement) {
        m_currentFormElement = new HTMLFormElement(formTag,    m_document);
}

ট্যাগ হায়ারার্কি খুব গভীর

কমেন্টটি নিজেই নিজের ব্যাখ্যা দেয়।

bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName)
{

unsigned i = 0;
for (HTMLStackElem* curr = m_blockStack;
         i < cMaxRedundantTagDepth && curr && curr->tagName == tagName;
     curr = curr->next, i++) { }
return i != cMaxRedundantTagDepth;
}

ভুল জায়গায় html বা বডি এন্ড ট্যাগ

আবারও বলছি - কমেন্টটি নিজেই নিজের পরিচয় দেয়।

if (t->tagName == htmlTag || t->tagName == bodyTag )
        return;

তাই ওয়েব লেখকরা সাবধান - আপনি যদি WebKit-এর ত্রুটি সহনশীলতা কোড স্নিপেটে উদাহরণ হিসেবে উপস্থিত হতে না চান - তাহলে সঠিক ফর্ম্যাটে HTML লিখুন।

CSS পার্সিং

ভূমিকার পার্সিং কনসেপ্ট মনে আছে? HTML-এর মতো নয়, CSS হল একটি কনটেক্সট ফ্রি গ্রামার এবং ভূমিকায় বর্ণিত পার্সারের ধরন ব্যবহার করে পার্স করা যেতে পারে। আসলে CSS স্পেসিফিকেশন CSS লেক্সিক্যাল ও সিনট্যাক্স ব্যাকরণকে সংজ্ঞায়িত করে।

কিছু উদাহরণ দেখা যাক:

প্রতিটি টোকেনের জন্য রেগুলার এক্সপ্রেশনের মাধ্যমে লেক্সিক্যাল গ্রামার (শব্দভাণ্ডার) সংজ্ঞায়িত করা হয়:

comment   \/\*[^*]*\*+([^/*][^*]*\*+)*\/
num       [0-9]+|[0-9]*"."[0-9]+
nonascii  [\200-\377]
nmstart   [_a-z]|{nonascii}|{escape}
nmchar    [_a-z0-9-]|{nonascii}|{escape}
name      {nmchar}+
ident     {nmstart}{nmchar}*

"ident" হল শনাক্তকারীর সংক্ষিপ্ত রূপ, যেমন ক্লাস নেম। "name" হল একটি এলিমেন্ট আইডি (যা "#" দ্বারা উল্লেখ করা হয় )

সিনট্যাক্স ব্যাকরণ BNF-এ বর্ণনা করা হয়েছে।

ruleset
  : selector [ ',' S* selector ]*
    '{' S* declaration [ ';' S* declaration ]* '}' S*
  ;
selector
  : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]?
  ;
simple_selector
  : element_name [ HASH | class | attrib | pseudo ]*
  | [ HASH | class | attrib | pseudo ]+
  ;
class
  : '.' IDENT
  ;
element_name
  : IDENT | '*'
  ;
attrib
  : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
    [ IDENT | STRING ] S* ] ']'
  ;
pseudo
  : ':' [ IDENT | FUNCTION S* [IDENT S*] ')' ]
  ;

ব্যাখ্যা:

নিয়মের সেট এই স্ট্রাকচার অনুযায়ী তৈরি হয়:

div.error, a.error {
  color:red;
  font-weight:bold;
}

div.error এবং a.error হল নির্বাচক। কার্লি ব্র্যাকেটের মধ্যে থাকা অংশে এই রুলসেট দ্বারা প্রয়োগ করা নিয়মগুলি থাকে। এই স্ট্রাকচারটি এই সংজ্ঞায় আনুষ্ঠানিকভাবে সংজ্ঞায়িত করা হয়েছে:

ruleset
  : selector [ ',' S* selector ]*
    '{' S* declaration [ ';' S* declaration ]* '}' S*
  ;

এর অর্থ হল, রুলসেট হল একটি সিলেক্টর বা বিকল্প হিসেবে কমা ও স্পেস (S বলতে হোয়াইট স্পেস বোঝায়) দিয়ে আলাদা করা একাধিক সিলেক্টর। রুলসেটে কার্লি ব্র্যাকেট থাকে এবং তার মধ্যে একটি ডিক্লারেশন বা বিকল্প হিসেবে সেমিকোলন দিয়ে আলাদা করা একাধিক ডিক্লারেশন থাকে। "declaration" এবং "selector" নিম্নলিখিত BNF সংজ্ঞায় সংজ্ঞায়িত করা হবে।

WebKit CSS পার্সার

CSS গ্রামার ফাইল থেকে অটোমেটিক পার্সার তৈরি করতে WebKit Flex and Bison পার্সার জেনারেটর ব্যবহার করে। পার্সার পরিচিতি থেকে আপনার মনে থাকতে পারে যে Bison একটি বটম-আপ শিফ্ট-রিডিউস পার্সার তৈরি করে। Firefox-এ ম্যানুয়ালি লেখা টপ ডাউন পার্সার ব্যবহার করা হয়। দুটি ক্ষেত্রেই প্রতিটি CSS ফাইল একটি StyleSheet অবজেক্টে পার্স করা হয়। প্রতিটি অবজেক্টে CSS নিয়ম থাকে। CSS রুল অবজেক্টে সিলেক্টর ও ডিক্লারেশন অবজেক্ট এবং CSS ব্যাকরণ অনুযায়ী অন্যান্য অবজেক্ট থাকে।

CSS পার্স করা হচ্ছে।
ছবি ১২: CSS পার্স করা হচ্ছে

স্ক্রিপ্ট ও স্টাইল শিটের জন্য প্রসেসিং অর্ডার

লিপি

ওয়েবের মডেলটি সিঙ্ক্রোনাস। পার্সার <script> ট্যাগে পৌঁছালে, লেখক আশা করেন যে স্ক্রিপ্টটি অবিলম্বে পার্স এবং কার্যকর করা হবে। স্ক্রিপ্টটি কার্যকর না হওয়া পর্যন্ত ডকুমেন্টের পার্সিং বন্ধ থাকে। স্ক্রিপ্টটি এক্সটার্নাল হলে, রিসোর্সটি প্রথমে নেটওয়ার্ক থেকে আনতে হবে - এটিও সিঙ্ক্রোনাসভাবে করা হয় এবং রিসোর্সটি না আনা পর্যন্ত পার্সিং বন্ধ থাকে। এটি বহু বছর ধরে মডেল হিসেবে ব্যবহৃত হয়ে আসছে এবং HTML4 ও 5 স্পেসিফিকেশনেও উল্লেখ করা আছে। লেখক স্ক্রিপ্টে "defer" অ্যাট্রিবিউট যোগ করতে পারেন, যার ফলে ডকুমেন্ট পার্সিং বন্ধ হবে না এবং ডকুমেন্ট পার্স করার পরে এটি এক্সিকিউট হবে। HTML5 স্ক্রিপ্টকে অ্যাসিঙ্ক্রোনাস হিসেবে চিহ্নিত করার বিকল্প যোগ করে, যাতে এটি অন্য থ্রেড দ্বারা পার্স ও এক্সিকিউট করা যায়।

স্পেকুলেটিভ পার্সিং

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

স্টাইল শিট

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

রেন্ডার ট্রি কনস্ট্রাকশন

DOM ট্রি তৈরি করার সময়, ব্রাউজার আরেকটি ট্রি তৈরি করে, রেন্ডার ট্রি। এই ট্রি হল ভিজ্যুয়াল এলিমেন্টের ক্রম, যে ক্রমে সেগুলি দেখানো হবে। এটি হল ডকুমেন্টের ভিজ্যুয়াল উপস্থাপনা। এই ট্রি-এর উদ্দেশ্য হল কন্টেন্টকে সঠিক ক্রমে পেইন্ট করার সুবিধা প্রদান করা।

Firefox-এ রেন্ডার ট্রির এলিমেন্টকে "ফ্রেম" বলা হয়। WebKit-এ রেন্ডারার বা রেন্ডার অবজেক্ট শব্দ ব্যবহার করা হয়।

রেন্ডারার জানে কীভাবে নিজেকে এবং তার চাইল্ডকে লে-আউট এবং পেইন্ট করতে হয়।

WebKit-এর RenderObject ক্লাস, রেন্ডারারের মূল ক্লাস, নিম্নলিখিত সংজ্ঞা আছে:

class RenderObject{
  virtual void layout();
  virtual void paint(PaintInfo);
  virtual void rect repaintRect();
  Node* node;  //the DOM node
  RenderStyle* style;  // the computed style
  RenderLayer* containgLayer; //the containing z-index layer
}

প্রতিটি রেন্ডারার একটি আয়তক্ষেত্রাকার এলাকাকে উপস্থাপন করে যা সাধারণত CSS2 স্পেক দ্বারা বর্ণিত নোডের CSS বক্সের সাথে সম্পর্কিত। এতে প্রস্থ, উচ্চতা এবং অবস্থানের মতো জ্যামিতিক তথ্য অন্তর্ভুক্ত থাকে।

বক্সের ধরন নোডের সাথে প্রাসঙ্গিক স্টাইল অ্যাট্রিবিউটের "ডিসপ্লে" ভ্যালু দ্বারা প্রভাবিত হয় (স্টাইল কম্পিউটেশন বিভাগ দেখুন)। ডিসপ্লে অ্যাট্রিবিউট অনুযায়ী DOM নোডের জন্য কোন ধরনের রেন্ডারার তৈরি করা উচিত তা নির্ধারণ করার জন্য WebKit কোড এখানে দেওয়া হল:

RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
{
    Document* doc = node->document();
    RenderArena* arena = doc->renderArena();
    ...
    RenderObject* o = 0;

    switch (style->display()) {
        case NONE:
            break;
        case INLINE:
            o = new (arena) RenderInline(node);
            break;
        case BLOCK:
            o = new (arena) RenderBlock(node);
            break;
        case INLINE_BLOCK:
            o = new (arena) RenderBlock(node);
            break;
        case LIST_ITEM:
            o = new (arena) RenderListItem(node);
            break;
       ...
    }

    return o;
}

এলিমেন্টের ধরনও বিবেচনা করা হয়: যেমন, ফর্ম কন্ট্রোল ও টেবিলের বিশেষ ফ্রেম থাকে।

WebKit-এ কোনও এলিমেন্ট যদি বিশেষ রেন্ডারার তৈরি করতে চায়, তাহলে এটি createRenderer() পদ্ধতি ওভাররাইড করবে। রেন্ডারার স্টাইল অবজেক্টের দিকে পয়েন্ট করে যাতে নন-জিওমেট্রিক তথ্য থাকে।

DOM ট্রির সাথে রেন্ডার ট্রির সম্পর্ক

রেন্ডারার DOM এলিমেন্টের সাথে সম্পর্কিত, তবে সম্পর্কটি এক থেকে এক নয়। রেন্ডার ট্রিতে নন-ভিজ্যুয়াল DOM এলিমেন্ট যোগ করা হবে না। উদাহরণ হিসেবে "head" এলিমেন্টের কথা বলা যায়। এছাড়াও, যেসব এলিমেন্টের ডিসপ্লে ভ্যালু "কিছুই নয়" হিসেবে অ্যাসাইন করা হয়েছে সেগুলি ট্রিতে দেখা যাবে না (তবে "লুকানো" দৃশ্যমানতা সহ এলিমেন্ট ট্রিতে দেখা যাবে)।

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

একাধিক রেন্ডারারের আরেকটি উদাহরণ হল ব্রোকেন HTML। CSS স্পেসিফিকেশন অনুযায়ী, ইনলাইন এলিমেন্টে শুধুমাত্র ব্লক এলিমেন্ট অথবা শুধুমাত্র ইনলাইন এলিমেন্ট থাকতে হবে। মিক্সড কন্টেন্টের ক্ষেত্রে, ইনলাইন এলিমেন্ট র‍্যাপ করার জন্য বেনামী ব্লক রেন্ডারার তৈরি করা হবে।

কিছু রেন্ডার অবজেক্ট DOM নোডের সাথে সম্পর্কিত হলেও ট্রিতে একই জায়গায় থাকে না। ফ্লোট ও অ্যাবসোলিউট পজিশন করা এলিমেন্ট ফ্লোর বাইরে থাকে, ট্রিয়ের অন্য অংশে প্লেস করা হয় এবং আসল ফ্রেমে ম্যাপ করা হয়। একটি প্লেসহোল্ডার ফ্রেম হল যেখানে সেগুলি থাকা উচিত ছিল।

রেন্ডার ট্রি এবং সংশ্লিষ্ট DOM ট্রি।
ছবি ১৩: রেন্ডার ট্রি এবং সংশ্লিষ্ট DOM ট্রি। "ভিউ পোর্ট" হল প্রাথমিক কন্টেনিং ব্লক। WebKit-এ এটি "RenderView" অবজেক্ট হবে

ট্রি তৈরি করার ফ্লো

Firefox-এ, প্রেজেন্টেশনটি DOM আপডেটের জন্য শ্রোতা হিসেবে রেজিস্টার করা হয়। প্রেজেন্টেশন FrameConstructor-এ ফ্রেম তৈরির কাজ ডেলিগেট করে এবং কনস্ট্রাক্টর স্টাইল (স্টাইল কম্পিউটেশন দেখুন) সমাধান করে এবং একটি ফ্রেম তৈরি করে।

WebKit-এ স্টাইল সমাধান করা এবং রেন্ডারার তৈরি করার প্রসেসকে "অ্যাটাচমেন্ট" বলা হয়। প্রতিটি DOM নোডে একটি "অ্যাটাচ" পদ্ধতি আছে। অ্যাটাচমেন্ট সিঙ্ক্রোনাস, DOM ট্রিতে নোড ইনসার্ট করলে নতুন নোড "অ্যাটাচ" পদ্ধতি কল করে।

html এবং বডি ট্যাগ প্রসেস করার ফলে রেন্ডার ট্রি রুট তৈরি হয়। রুট রেন্ডার অবজেক্ট CSS স্পেক যাকে কন্টেনিং ব্লক বলে তার সাথে সম্পর্কিত: সবচেয়ে উপরের ব্লক যাতে অন্যান্য সব ব্লক থাকে। এর ডাইমেনশন হল ভিউপোর্ট: ব্রাউজার উইন্ডো ডিসপ্লে এরিয়া ডাইমেনশন। Firefox-এ এটিকে ViewPortFrame এবং WebKit-এ এটিকে RenderView বলা হয়। এটি হল রেন্ডার অবজেক্ট যা ডকুমেন্ট পয়েন্ট করে। ট্রি-এর বাকি অংশ DOM নোড ইনসার্শন হিসেবে তৈরি করা হয়।

প্রসেসিং মডেলের CSS2 স্পেসিফিকেশন দেখুন।

স্টাইল কম্পিউটেশন

রেন্ডার ট্রি তৈরি করার জন্য প্রতিটি রেন্ডার অবজেক্টের ভিজ্যুয়াল প্রপার্টি গণনা করতে হয়। প্রতিটি এলিমেন্টের স্টাইল প্রপার্টি হিসেব করে এটি করা হয়।

স্টাইলের মধ্যে বিভিন্ন সোর্স থেকে পাওয়া স্টাইল শিট, ইনলাইন স্টাইল এলিমেন্ট এবং HTML-এ ভিজ্যুয়াল প্রপার্টি (যেমন "bgcolor" প্রপার্টি) অন্তর্ভুক্ত থাকে। পরেরটি ম্যাচিং CSS স্টাইল প্রপার্টিতে অনুবাদ করা হয়।

স্টাইল শিটের উৎস হল ব্রাউজারের ডিফল্ট স্টাইল শিট, পৃষ্ঠার লেখকের দেওয়া স্টাইল শিট এবং ব্যবহারকারীর স্টাইল শিট - এগুলি ব্রাউজার ব্যবহারকারীর দেওয়া স্টাইল শিট (ব্রাউজার আপনাকে পছন্দের স্টাইল বেছে নিতে দেয়। যেমন, Firefox-এ "Firefox প্রোফাইল" ফোল্ডারে স্টাইল শিট রেখে এটি করা হয়)।

স্টাইল কম্পিউটেশনের ক্ষেত্রে কিছু সমস্যা দেখা দেয়:

  1. স্টাইল ডেটা হল একটি খুব বড় কনস্ট্রাক্ট, যা অসংখ্য স্টাইল প্রপার্টি ধারণ করে, এটি মেমরি সংক্রান্ত সমস্যা সৃষ্টি করতে পারে।
  2. প্রতিটি এলিমেন্টের জন্য ম্যাচিং নিয়ম খুঁজে বের করার বিষয়টি অপ্টিমাইজ করা না থাকলে, পারফর্ম্যান্স সংক্রান্ত সমস্যা হতে পারে। মিল খুঁজে পেতে প্রতিটি এলিমেন্টের জন্য সম্পূর্ণ নিয়মের তালিকা ট্রাভার্স করা একটি কঠিন কাজ। নির্বাচকের জটিল স্ট্রাকচার থাকতে পারে যার ফলে ম্যাচিং প্রসেস এমন একটি পথে শুরু হতে পারে যা আপাতদৃষ্টিতে আশাব্যঞ্জক মনে হলেও পরে দেখা যায় যে সেটি কার্যকর নয় এবং অন্য পথ চেষ্টা করতে হবে।

    যেমন - এই কম্পাউন্ড সিলেক্টর:

    div div div div{
    ...
    }
    

    এর অর্থ হল, ৩টি div-এর বংশধর <div>-এর ক্ষেত্রে নিয়ম প্রযোজ্য। ধরা যাক, আপনি চেক করতে চান যে নিয়মটি প্রদত্ত <div> এলিমেন্টের ক্ষেত্রে প্রযোজ্য কিনা। আপনি চেক করার জন্য ট্রি-তে একটি নির্দিষ্ট পাথ বেছে নেন। আপনাকে নোড ট্রি উপরের দিকে ট্রাভার্স করতে হতে পারে, শুধু এটি খুঁজে দেখার জন্য যে সেখানে মাত্র দুটি div আছে এবং নিয়মটি প্রযোজ্য নয়। তারপর আপনাকে ট্রি-তে অন্য পাথ চেষ্টা করতে হবে।

  3. নিয়ম প্রয়োগ করার মধ্যে বেশ জটিল ক্যাসকেড নিয়ম অন্তর্ভুক্ত থাকে যা নিয়মের হায়ারার্কি নির্ধারণ করে।

ব্রাউজার কীভাবে এইসব সমস্যার সম্মুখীন হয় তা দেখা যাক:

স্টাইল ডেটা শেয়ার করা

WebKit নোড রেফারেন্স স্টাইল অবজেক্ট (RenderStyle)। কিছু শর্তে নোডের মাধ্যমে এইসব অবজেক্ট শেয়ার করা যেতে পারে। নোডগুলি হল ভাইবোন বা কাজিন এবং:

  1. এলিমেন্টগুলি একই মাউস স্টেটে থাকতে হবে (যেমন, একটি :hover-এ থাকলে অন্যটি থাকতে পারবে না)
  2. কোনও এলিমেন্টেরই আইডি থাকা উচিত নয়
  3. ট্যাগের নাম মিলতে হবে
  4. ক্লাসের অ্যাট্রিবিউট মিলতে হবে
  5. ম্যাপ করা অ্যাট্রিবিউটের সেট অবশ্যই অভিন্ন হতে হবে
  6. লিঙ্কের স্ট্যাটাস অবশ্যই মিলতে হবে
  7. ফোকাসড মোড অবশ্যই মিলতে হবে
  8. অ্যাট্রিবিউট সিলেক্টর দ্বারা কোনও এলিমেন্ট প্রভাবিত হওয়া উচিত নয়, যেখানে প্রভাবিত হওয়ার অর্থ হল সিলেক্টরের মধ্যে যেকোনও পজিশনে অ্যাট্রিবিউট সিলেক্টর ব্যবহার করে এমন যেকোনও সিলেক্টর ম্যাচ থাকা
  9. এলিমেন্টে কোনও ইনলাইন স্টাইল অ্যাট্রিবিউট থাকলে চলবে না
  10. কোনও সিবলিং সিলেক্টর ব্যবহার করা যাবে না। WebCore simply throws a global switch when any sibling selector is encountered and disables style sharing for the entire document when they are present. এর মধ্যে + সিলেক্টর এবং :first-child ও :last-child-এর মতো সিলেক্টর অন্তর্ভুক্ত।

Firefox-এর নিয়ম ট্রি

স্টাইল কম্পিউটেশন আরও সহজ করার জন্য Firefox-এ দুটি অতিরিক্ত ট্রি আছে: রুল ট্রি এবং স্টাইল কনটেক্সট ট্রি। WebKit-এও স্টাইল অবজেক্ট আছে, তবে সেগুলি স্টাইল কনটেক্সট ট্রির মতো ট্রিতে স্টোর করা হয় না, শুধুমাত্র DOM নোড তার প্রাসঙ্গিক স্টাইলকে পয়েন্ট করে।

Firefox স্টাইল কন্টেক্সট ট্রি।
ছবি ১৪: Firefox স্টাইল কনটেক্সট ট্রি।

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

মিলে যাওয়া সব নিয়ম একটি ট্রিতে স্টোর করা হয়। পাথের নিচের নোডের অগ্রাধিকার বেশি। নিয়ম ম্যাচ করার জন্য যতগুলি পাথ পাওয়া গেছে, ট্রি-তে সেগুলি সব দেখানো হয়। নিয়ম স্টোর করার কাজ ধীরে ধীরে করা হয়। প্রতিটি নোডের জন্য শুরুতে ট্রি গণনা করা হয় না, তবে যখনই কোনও নোড স্টাইল গণনা করার প্রয়োজন হয়, গণনা করা পাথগুলি ট্রিতে যোগ করা হয়।

উদ্দেশ্য হল, ট্রি পাথকে লেক্সিকনের শব্দ হিসেবে দেখা। ধরা যাক, আমরা আগেই এই রুল ট্রি গণনা করেছি:

গণনা করা নিয়ম ট্রি
ছবি ১৫: গণনা করা নিয়মের ট্রি।

ধরুন, কন্টেন্ট ট্রিতে অন্য একটি এলিমেন্টের জন্য আমাদের নিয়ম ম্যাচ করতে হবে এবং আমরা দেখতে পেলাম যে ম্যাচ করা নিয়ম (সঠিক ক্রমে) হল B-E-I। ট্রি-তে এই পাথ আগে থেকেই আছে কারণ আমরা আগে থেকেই পাথ A-B-E-I-L গণনা করেছি। আমাদের এখন কম কাজ করতে হবে।

চলো দেখি, গাছ কীভাবে আমাদের কাজ বাঁচায়।

স্ট্রাক্টে ভাগ করা

স্টাইল কনটেক্সট স্ট্রাক্টে ভাগ করা হয়েছে। এইসব স্ট্রাক্টে বর্ডার বা রঙের মতো নির্দিষ্ট বিভাগের জন্য স্টাইল সংক্রান্ত তথ্য থাকে। স্ট্রাক্টের সব প্রপার্টি হয় ইনহেরিট করা অথবা ইনহেরিট করা নয়। উত্তরাধিকারসূত্রে প্রাপ্ত প্রপার্টি হল এমন প্রপার্টি যা এলিমেন্ট দ্বারা সংজ্ঞায়িত না হলে, তার প্যারেন্ট থেকে উত্তরাধিকারসূত্রে প্রাপ্ত হয়। ইনহেরিট করা হয়নি এমন প্রপার্টি (যাকে "রিসেট" প্রপার্টি বলা হয়) ডিফল্ট ভ্যালু ব্যবহার করে যদি তা উল্লেখ করা না থাকে।

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

রুল ট্রি ব্যবহার করে স্টাইল কনটেক্সট গণনা করা হচ্ছে

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

আমরা আংশিক সংজ্ঞা খুঁজে পেলে, স্ট্রাক্ট পূরণ না হওয়া পর্যন্ত আমরা ট্রি-এর উপরের দিকে যেতে থাকি।

আমরা যদি আমাদের স্ট্রাক্টের জন্য কোনও সংজ্ঞা খুঁজে না পাই, তাহলে স্ট্রাক্টটি "উত্তরাধিকারসূত্রে প্রাপ্ত" ধরনের হলে, আমরা কন্টেক্সট ট্রি-তে আমাদের পেরেন্টের স্ট্রাক্টকে পয়েন্ট করি। এই ক্ষেত্রে আমরা স্ট্রাক্ট শেয়ার করতেও সফল হয়েছি। এটি রিসেট স্ট্রাক্ট হলে ডিফল্ট ভ্যালু ব্যবহার করা হবে।

সবচেয়ে নির্দিষ্ট Node যদি ভ্যালু যোগ করে, তাহলে সেটিকে আসল ভ্যালুতে পরিবর্তন করার জন্য আমাদের কিছু অতিরিক্ত গণনা করতে হবে। তারপর আমরা ট্রি নোডে ফলাফল ক্যাশে করি যাতে এটি চিলড্রেন ব্যবহার করতে পারে।

কোনও এলিমেন্টের যদি কোনও সিবলিং বা ব্রাদার থাকে যা একই ট্রি নোডকে পয়েন্ট করে, তাহলে তাদের মধ্যে সম্পূর্ণ স্টাইল কনটেক্সট শেয়ার করা যেতে পারে।

একটি উদাহরণ দেখা যাক: ধরা যাক, আমাদের কাছে এই HTML আছে

<html>
  <body>
    <div class="err" id="div1">
      <p>
        this is a <span class="big"> big error </span>
        this is also a
        <span class="big"> very  big  error</span> error
      </p>
    </div>
    <div class="err" id="div2">another error</div>
  </body>
</html>

এবং নিম্নলিখিত নিয়মগুলি:

div {margin: 5px; color:black}
.err {color:red}
.big {margin-top:3px}
div span {margin-bottom:4px}
#div1 {color:blue}
#div2 {color:green}

সহজভাবে বলতে গেলে, আমাদের শুধু দুটি স্ট্রাক্ট পূরণ করতে হবে: কালার স্ট্রাক্ট ও মার্জিন স্ট্রাক্ট। কালার স্ট্রাক্টে শুধুমাত্র একটি মেম্বার থাকে: কালার মার্জিন স্ট্রাক্টে চারটি সাইড থাকে।

ফলাফল হিসেবে পাওয়া রুল ট্রিটি এইরকম দেখতে হবে (নোডগুলি নোডের নাম দিয়ে চিহ্নিত করা হয়েছে: তারা যে নিয়মের দিকে নির্দেশ করে তার সংখ্যা):

নিয়ম ট্রি
ছবি ১৬: নিয়মের ট্রি

কন্টেক্সট ট্রি দেখতে এইরকম হবে (নোডের নাম: যে রুল নোডকে এটি পয়েন্ট করে):

কনটেক্সট ট্রি।
ছবি ১৭: কনটেক্সট ট্রি

ধরা যাক, আমরা HTML পার্স করে দ্বিতীয় <div> ট্যাগে পৌঁছেছি। আমাদের এই নোডের জন্য একটি স্টাইল কনটেক্সট তৈরি করতে হবে এবং এর স্টাইল স্ট্রাক্ট পূরণ করতে হবে।

আমরা নিয়মগুলি ম্যাচ করব এবং দেখতে পাব যে <div>-এর জন্য ম্যাচিং নিয়মগুলি হল ১, ২ এবং ৬। এর অর্থ হল, ট্রি-তে আগে থেকেই এমন একটি পাথ আছে যা আমাদের এলিমেন্ট ব্যবহার করতে পারে এবং নিয়ম ৬-এর জন্য আমাদের শুধু এতে আরেকটি নোড যোগ করতে হবে (নিয়ম ট্রি-তে নোড F)।

আমরা একটি স্টাইল কনটেক্সট তৈরি করব এবং এটি কনটেক্সট ট্রিতে রাখব। নতুন স্টাইল কনটেক্সট রুল ট্রিতে নোড F-কে পয়েন্ট করবে।

আমাদের এখন স্টাইল স্ট্রাক্ট পূরণ করতে হবে। আমরা মার্জিন স্ট্রাক্ট পূরণ করে শুরু করব। যেহেতু শেষ রুল নোড (F) মার্জিন স্ট্রাক্টে যোগ করে না, তাই আমরা আগের নোড ইনসার্ট করার সময় গণনা করা ক্যাশে করা স্ট্রাক্ট খুঁজে না পাওয়া পর্যন্ত ট্রি-এর উপরের দিকে যেতে পারি এবং এটি ব্যবহার করতে পারি। আমরা এটি নোড B-তে খুঁজে পাব, যা হল সবচেয়ে উপরের নোড যা মার্জিন নিয়ম নির্দিষ্ট করে।

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

দ্বিতীয় <span> এলিমেন্টের কাজ আরও সহজ। আমরা নিয়মগুলি মিলিয়ে দেখব এবং এই সিদ্ধান্তে আসব যে এটি আগের স্প্যানের মতো নিয়ম G-কে নির্দেশ করে। যেহেতু আমাদের কাছে একই নোডকে পয়েন্ট করে এমন সিবলিং আছে, তাই আমরা সম্পূর্ণ স্টাইল কন্টেক্সট শেয়ার করতে পারি এবং আগের স্প্যানের কন্টেক্সটকে পয়েন্ট করতে পারি।

যেসব স্ট্রাক্টে পেরেন্ট থেকে ইনহেরিট করা নিয়ম থাকে, সেগুলির ক্ষেত্রে কনটেক্সট ট্রিতে ক্যাশিং করা হয় (কালার প্রপার্টি আসলে ইনহেরিট করা হয়, কিন্তু Firefox এটিকে রিসেট হিসেবে বিবেচনা করে এবং রুল ট্রিতে ক্যাশ করে)।

যেমন, আমরা যদি কোনও অনুচ্ছেদে ফন্টের জন্য নিয়ম যোগ করি:

p {font-family: Verdana; font size: 10px; font-weight: bold}

তারপর, প্যারাগ্রাফ এলিমেন্ট, যা কনটেক্সট ট্রিতে div-এর চাইল্ড, সেটি তার পেরেন্টের মতো একই ফন্ট স্ট্রাক্ট শেয়ার করতে পারত। অনুচ্ছেদের জন্য কোনও ফন্ট সংক্রান্ত নিয়ম নির্দিষ্ট করা না থাকলে এটি প্রযোজ্য হয়।

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

সুতরাং, সংক্ষেপে বলতে গেলে: স্টাইল অবজেক্ট (সম্পূর্ণ বা এর মধ্যে থাকা কিছু স্ট্রাক্ট) শেয়ার করলে ১ ও ৩ নম্বর সমস্যার সমাধান হয়। Firefox-এর রুল ট্রিও সঠিক ক্রমে প্রপার্টি প্রয়োগ করতে সাহায্য করে।

সহজে ম্যাচ করার জন্য নিয়ম ম্যানিপুলেট করা

স্টাইল সংক্রান্ত নিয়মের জন্য একাধিক সোর্স আছে:

  1. CSS নিয়ম, এক্সটার্নাল স্টাইল শিট বা স্টাইল এলিমেন্টে। css p {color: blue}
  2. ইনলাইন স্টাইল অ্যাট্রিবিউট যেমন html <p style="color: blue" />
  3. HTML ভিজ্যুয়াল অ্যাট্রিবিউট (যা প্রাসঙ্গিক স্টাইল রুলের সাথে ম্যাপ করা হয়) html <p bgcolor="blue" /> শেষের দুটি সহজেই এলিমেন্টের সাথে ম্যাচ করে যায় কারণ স্টাইল অ্যাট্রিবিউট তার মালিকানাধীন এবং এলিমেন্টকে 'কী' হিসেবে ব্যবহার করে HTML অ্যাট্রিবিউট ম্যাপ করা যায়।

সমস্যা #২-এ আগে যেমন উল্লেখ করা হয়েছে, CSS রুল ম্যাচিং আরও জটিল হতে পারে। সমস্যার সমাধান করতে, আরও সহজে অ্যাক্সেস করার জন্য নিয়মগুলি ম্যানিপুলেট করা হয়।

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

এই ম্যানিপুলেশন নিয়ম ম্যাচ করা অনেক সহজ করে তোলে। প্রতিটি ডিক্লারেশন দেখার প্রয়োজন নেই: আমরা ম্যাপ থেকে কোনও এলিমেন্টের জন্য প্রাসঙ্গিক নিয়ম এক্সট্র্যাক্ট করতে পারি। এই অপ্টিমাইজেশন ৯৫+% নিয়ম বাদ দেয়, যাতে ম্যাচিং প্রসেসের সময় সেগুলি বিবেচনা করার প্রয়োজন না হয়(৪.১)।

উদাহরণ হিসেবে নিচের স্টাইল সংক্রান্ত নিয়মগুলি দেখুন:

p.error {color: red}
#messageDiv {height: 50px}
div {margin: 5px}

প্রথম নিয়মটি ক্লাস ম্যাপে যোগ করা হবে। দ্বিতীয়টি আইডি ম্যাপে এবং তৃতীয়টি ট্যাগ ম্যাপে।

নিম্নলিখিত HTML ফ্র্যাগমেন্টের জন্য;

<p class="error">an error occurred</p>
<div id=" messageDiv">this is a message</div>

আমরা প্রথমে p এলিমেন্টের জন্য নিয়ম খুঁজে দেখার চেষ্টা করব। ক্লাস ম্যাপে "error" কী থাকবে যার অধীনে "p.error"-এর নিয়ম পাওয়া যাবে। div এলিমেন্টের আইডি ম্যাপ (কী হল আইডি) এবং ট্যাগ ম্যাপে প্রাসঙ্গিক নিয়ম থাকবে। তাই, এখন শুধু এইটুকু কাজই বাকি আছে যে, 'কী' দিয়ে এক্সট্র্যাক্ট করা নিয়মগুলির মধ্যে কোনটি সত্যিই ম্যাচ করছে তা খুঁজে বের করা।

যেমন, div-এর জন্য নিয়ম যদি এটি হয়:

table div {margin: 5px}

এটি এখনও ট্যাগ ম্যাপ থেকে এক্সট্র্যাক্ট করা হবে, কারণ কী হল সবচেয়ে ডানদিকের সিলেক্টর, কিন্তু এটি আমাদের div এলিমেন্টের সাথে মিলবে না, যার কোনও টেবিল অ্যানসেস্টর নেই।

WebKit এবং Firefox, দুটিই এই ম্যানিপুলেশন করে।

স্টাইল শিট ক্যাসকেড অর্ডার

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

একাধিক সংজ্ঞা থাকলে সমস্যা শুরু হয় - এই সমস্যার সমাধান করতে ক্যাসকেড অর্ডার ব্যবহার করা হয়।

স্টাইল প্রপার্টির ঘোষণা একাধিক স্টাইল শিটে এবং একটি স্টাইল শিটের মধ্যে একাধিকবার দেখা যেতে পারে। এর অর্থ হল, নিয়ম প্রয়োগ করার ক্রম খুবই গুরুত্বপূর্ণ। এটিকে "ক্যাসকেড" অর্ডার বলা হয়। CSS2 স্পেসিফিকেশন অনুযায়ী, ক্যাসকেড অর্ডার হল (কম থেকে বেশি):

  1. ব্রাউজার ডিক্লারেশন
  2. ব্যবহারকারীর সাধারণ ডিক্লারেশন
  3. লেখকের স্বাভাবিক ঘোষণা
  4. লেখক সংক্রান্ত গুরুত্বপূর্ণ ঘোষণা
  5. ব্যবহারকারীর গুরুত্বপূর্ণ ঘোষণা

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

নির্দিষ্টতা

সিলেক্টর স্পেসিফিসিটি CSS2 স্পেসিফিকেশন দ্বারা নিম্নলিখিতভাবে সংজ্ঞায়িত করা হয়:

  1. ডিক্লেয়ারেশনটি সিলেক্টর সহ রুলের পরিবর্তে 'স্টাইল' অ্যাট্রিবিউট থেকে হলে ১ গণনা করুন, অন্যথায় ০ (= a)
  2. সিলেক্টরে ID অ্যাট্রিবিউটের সংখ্যা গণনা করুন (= b)
  3. সিলেক্টরে অন্যান্য অ্যাট্রিবিউট ও ছদ্ম-ক্লাসের সংখ্যা গণনা করুন (= c)
  4. সিলেক্টরে এলিমেন্টের নাম ও ছদ্ম-এলিমেন্টের সংখ্যা গণনা করা (= d)

চারটি সংখ্যা a-b-c-d (বড় বেস সহ একটি সংখ্যা সিস্টেমে) কনক্যাটিনেট করলে নির্দিষ্টতা পাওয়া যায়।

আপনাকে যে সংখ্যা বেস ব্যবহার করতে হবে তা কোনও একটি বিভাগে আপনার কাছে থাকা সর্বোচ্চ সংখ্যা দ্বারা নির্ধারিত হয়।

যেমন, a=14 হলে আপনি হেক্সাডেসিমাল বেস ব্যবহার করতে পারেন। যদি a=17 হয়, তাহলে আপনাকে ১৭ সংখ্যার বেস ব্যবহার করতে হবে। পরের পরিস্থিতিটি এই ধরনের সিলেক্টরের ক্ষেত্রে ঘটতে পারে: html body div div p… (আপনার সিলেক্টরে ১৭টি ট্যাগ… খুব একটা সম্ভাবনা নেই)।

কিছু উদাহরণ:

 *             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
 li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
 li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
 ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
 ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
 h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
 ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
 li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
 #x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */
 style=""          /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */

নিয়ম সাজানো হচ্ছে

নিয়ম মিলে যাওয়ার পরে, ক্যাসকেড নিয়ম অনুযায়ী সেগুলি সাজানো হয়। WebKit ছোট তালিকার জন্য বাবল সর্ট এবং বড় তালিকার জন্য মার্জ সর্ট ব্যবহার করে। WebKit, নিয়মের জন্য > অপারেটর ওভাররাইড করে সাজানোর কাজটি করে:

static bool operator >(CSSRuleData& r1, CSSRuleData& r2)
{
    int spec1 = r1.selector()->specificity();
    int spec2 = r2.selector()->specificity();
    return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
}

ধীরে ধীরে হওয়া প্রক্রিয়া

WebKit একটি ফ্ল্যাগ ব্যবহার করে যা সমস্ত শীর্ষ স্তরের স্টাইল শিট (@imports সহ) লোড করা হয়েছে কিনা তা চিহ্নিত করে। অ্যাটাচ করার সময় স্টাইল সম্পূর্ণভাবে লোড না হলে, প্লেসহোল্ডার ব্যবহার করা হয় এবং ডকুমেন্টে সেটি চিহ্নিত করা হয় এবং স্টাইল শিট লোড হয়ে গেলে সেগুলি আবার গণনা করা হবে।

লেআউট

রেন্ডারার তৈরি করে ট্রি-তে যোগ করা হলে, এটির কোনও পজিশন ও সাইজ থাকে না। এইসব ভ্যালু গণনা করাকে লেআউট বা রিফ্লো বলা হয়।

HTML ফ্লো-ভিত্তিক লেআউট মডেল ব্যবহার করে, যার অর্থ হল বেশিরভাগ সময় একটি একক পাসে জ্যামিতি গণনা করা সম্ভব। "ফ্লোতে" পরে থাকা এলিমেন্ট সাধারণত "ফ্লোতে" আগে থাকা এলিমেন্টের জ্যামিতিকে প্রভাবিত করে না, তাই লে-আউট ডকুমেন্টের মধ্যে বাঁদিক থেকে ডানদিকে, উপর থেকে নিচে চলতে পারে। ব্যতিক্রম আছে: যেমন, HTML টেবিলের জন্য একাধিক পাসের প্রয়োজন হতে পারে।

কোঅর্ডিনেট সিস্টেম রুট ফ্রেমের সাথে সম্পর্কিত। উপরে এবং বাঁদিকের কোঅর্ডিনেট ব্যবহার করা হয়।

লেআউট হল একটি রিকার্সিভ প্রসেস। এটি রুট রেন্ডারার থেকে শুরু হয়, যা HTML ডকুমেন্টের <html> এলিমেন্টের সাথে সম্পর্কিত। লেআউট কিছু বা সমস্ত ফ্রেম হায়ারার্কির মাধ্যমে পুনরাবৃত্তিমূলকভাবে চলতে থাকে, প্রতিটি রেন্ডারারের জন্য জ্যামিতিক তথ্য গণনা করে যার এটি প্রয়োজন।

রুট রেন্ডারারের পজিশন হল ০,০ এবং এর ডাইমেনশন হল ভিউপোর্ট - ব্রাউজার উইন্ডোর দৃশ্যমান অংশ।

সব রেন্ডারারের "লেআউট" বা "রিফ্লো" পদ্ধতি আছে, প্রতিটি রেন্ডারার তার চাইল্ডের লেআউট পদ্ধতিকে ইনভোক করে যার লেআউট প্রয়োজন।

ডার্টি বিট সিস্টেম

প্রতিটি ছোট পরিবর্তনের জন্য যাতে সম্পূর্ণ লেআউট করতে না হয়, তার জন্য ব্রাউজার "ডার্টি বিট" সিস্টেম ব্যবহার করে। কোনও রেন্ডারার পরিবর্তন বা যোগ করা হলে, সেটি নিজেকে এবং তার চিলড্রেনকে "ডার্টি" হিসেবে চিহ্নিত করে: লেআউট প্রয়োজন।

দুটি ফ্ল্যাগ আছে: "ডার্টি" এবং "চিলড্রেন আর ডার্টি" যার অর্থ হল, রেন্ডারার নিজে ঠিক থাকলেও, এর অন্তত একটি চাইল্ড আছে যার লেআউট প্রয়োজন।

গ্লোবাল ও ইনক্রিমেন্টাল লেআউট

সম্পূর্ণ রেন্ডার ট্রিতে লেআউট ট্রিগার করা যেতে পারে - এটি হল "গ্লোবাল" লেআউট। এগুলি হওয়ার কারণে এটি হতে পারে:

  1. গ্লোবাল স্টাইল পরিবর্তন যা সব রেন্ডারারকে প্রভাবিত করে, যেমন ফন্ট সাইজ পরিবর্তন।
  2. স্ক্রিনের সাইজ পরিবর্তন করার ফলে

লেআউট ইনক্রিমেন্টাল হতে পারে, শুধুমাত্র ডার্টি রেন্ডারার লেআউট করা হবে (এর ফলে কিছু ক্ষতি হতে পারে যার জন্য অতিরিক্ত লেআউটের প্রয়োজন হবে)।

রেন্ডারার ডার্টি হলে ইনক্রিমেন্টাল লেআউট ট্রিগার করা হয় (অ্যাসিঙ্ক্রোনাসভাবে)। যেমন, নেটওয়ার্ক থেকে অতিরিক্ত কন্টেন্ট আসার পরে এবং DOM ট্রিতে যোগ করার পরে রেন্ডার ট্রিতে নতুন রেন্ডারার যোগ করা হলে।

ইনক্রিমেন্টাল লেআউট।
ছবি ১৮: ইনক্রিমেন্টাল লেআউট - শুধুমাত্র ডার্টি রেন্ডারার এবং তাদের চাইল্ড লেআউট করা হয়

অ্যাসিঙ্ক্রোনাস ও সিঙ্ক্রোনাস লেআউট

ইনক্রিমেন্টাল লেআউট অ্যাসিঙ্ক্রোনাসভাবে করা হয়। ইনক্রিমেন্টাল লেআউটের জন্য Firefox "রিফ্লো কমান্ড" সারিবদ্ধ করে এবং একটি শিডিউলার এই কমান্ডগুলির ব্যাচ এক্সিকিউশন ট্রিগার করে। WebKit-এ একটি টাইমারও আছে যা ইনক্রিমেন্টাল লেআউট এক্সিকিউট করে - ট্রি ট্রাভার্স করা হয় এবং "ডার্টি" রেন্ডারার লেআউট করা হয়।

"offsetHeight"-এর মতো স্টাইল সংক্রান্ত তথ্য জানতে চাওয়া স্ক্রিপ্ট ইনক্রিমেন্টাল লেআউট সিঙ্ক করতে পারে।

গ্লোবাল লেআউট সাধারণত সিঙ্ক্রোনাসভাবে ট্রিগার করা হবে।

প্রাথমিক লেআউটের পরে কখনও কখনও লেআউট কলব্যাক হিসেবে ট্রিগার করা হয় কারণ স্ক্রলিং পজিশনের মতো কিছু অ্যাট্রিবিউট পরিবর্তন করা হয়েছে।

অপ্টিমাইজেশন

"ছোট বড় করা" বা রেন্ডারার পজিশনে(সাইজে নয়) পরিবর্তনের কারণে কোনও লেআউট ট্রিগার হলে, রেন্ডার সাইজ ক্যাশে থেকে নেওয়া হয় এবং আবার গণনা করা হয় না…

কিছু ক্ষেত্রে শুধু সাব-ট্রি পরিবর্তন করা হয় এবং লেআউট রুট থেকে শুরু হয় না। এটি এমন ক্ষেত্রে ঘটতে পারে যেখানে পরিবর্তনটি লোকাল এবং এর আশেপাশের উপর প্রভাব ফেলে না - যেমন টেক্সট ফিল্ডে টেক্সট যোগ করা (অন্যথায় প্রতিটি কীস্ট্রোক রুট থেকে শুরু করে একটি লেআউট ট্রিগার করবে)।

লেআউট প্রসেস

লে-আউটে সাধারণত নিম্নলিখিত প্যাটার্ন থাকে:

  1. পেরেন্ট রেন্ডারার নিজের প্রস্থ নির্ধারণ করে।
  2. অভিভাবক বাচ্চাদের উপর নজর রাখেন এবং:
    1. চাইল্ড রেন্ডারার প্লেস করুন (এটির x এবং y সেট করে)।
    2. প্রয়োজন হলে চাইল্ড লেআউট কল করে - সেগুলি ডার্টি হলে বা আমরা গ্লোবাল লেআউটে থাকলে অথবা অন্য কোনও কারণে - যা চাইল্ডের উচ্চতা গণনা করে।
  3. প্যারেন্ট, চাইল্ডের মোট উচ্চতা এবং মার্জিন ও প্যাডিংয়ের উচ্চতা ব্যবহার করে নিজের উচ্চতা সেট করে - এটি প্যারেন্ট রেন্ডারারের প্যারেন্ট ব্যবহার করবে।
  4. এর ডার্টি বিটকে মিথ্যা হিসেবে সেট করে।

Firefox লেআউটের(যাকে "রিফ্লো" বলা হয়) প্যারামিটার হিসেবে "স্টেট" অবজেক্ট (nsHTMLReflowState) ব্যবহার করে। অন্যান্য বিষয়ের মধ্যে, এই স্ট্যাটাসে পেরেন্ট উইডথ অন্তর্ভুক্ত থাকে।

Firefox লেআউটের আউটপুট হল একটি "মেট্রিক্স" অবজেক্ট(nsHTMLReflowMetrics)। এতে রেন্ডারার কম্পিউটেড উচ্চতা থাকবে।

প্রস্থ গণনা

রেন্ডারারের প্রস্থ কন্টেনার ব্লকের প্রস্থ, রেন্ডারারের স্টাইল "প্রস্থ" প্রপার্টি, মার্জিন এবং বর্ডার ব্যবহার করে গণনা করা হয়।

যেমন, নিম্নলিখিত div-এর প্রস্থ:

<div style="width: 30%"/>

WebKit-এর মাধ্যমে নিম্নলিখিতভাবে হিসেব করা হবে(class RenderBox method calcWidth):

  • কন্টেনারের প্রস্থ হল কন্টেনারের availableWidth এবং ০-এর মধ্যে যেটি বেশি সেটি। এই ক্ষেত্রে availableWidth হল contentWidth যা এইভাবে গণনা করা হয়:
clientWidth() - paddingLeft() - paddingRight()

clientWidth এবং clientHeight বর্ডার এবং স্ক্রলবার বাদ দিয়ে অবজেক্টের ভেতরের অংশকে বোঝায়।

  • এলিমেন্টের প্রস্থ হল "width" স্টাইল অ্যাট্রিবিউট। কন্টেনারের প্রস্থের শতাংশ গণনা করে এটি একটি পরম মান হিসাবে গণনা করা হবে।

  • অনুভূমিক সীমানা এবং প্যাডিং এখন যোগ করা হয়েছে।

এখনও পর্যন্ত এটি "পছন্দের প্রস্থ" গণনা করার পদ্ধতি ছিল। এখন ন্যূনতম এবং সর্বাধিক প্রস্থ গণনা করা হবে।

পছন্দের প্রস্থ সর্বাধিক প্রস্থের চেয়ে বেশি হলে, সর্বাধিক প্রস্থ ব্যবহার করা হয়। এটি ন্যূনতম প্রস্থের (সবচেয়ে ছোট অবিচ্ছেদ্য ইউনিট) চেয়ে কম হলে, ন্যূনতম প্রস্থ ব্যবহার করা হয়।

লেআউটের প্রয়োজন হলে ভ্যালু ক্যাশে করা হয়, তবে প্রস্থ পরিবর্তন হয় না।

লাইন ব্রেকিং

লেআউটের মাঝখানে কোনও রেন্ডারার যদি সিদ্ধান্ত নেয় যে সেটিকে ভাঙতে হবে, তাহলে রেন্ডারারটি থেমে যায় এবং লেআউটের পেরেন্টকে জানায় যে সেটিকে ভাঙতে হবে। প্যারেন্ট অতিরিক্ত রেন্ডারার তৈরি করে এবং সেগুলিতে লেআউট কল করে।

পেন্টিং

পেন্টিং স্টেজে, রেন্ডার ট্রি ট্রাভার্স করা হয় এবং স্ক্রিনে কন্টেন্ট দেখানোর জন্য রেন্ডারের "paint()" মেথড কল করা হয়। পেন্টিং UI ইনফ্রাস্ট্রাকচার কম্পোনেন্ট ব্যবহার করে।

গ্লোবাল ও ইনক্রিমেন্টাল

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

পেন্টিংয়ের ক্রম

CSS2 পেইন্টিং প্রসেসের ক্রম নির্ধারণ করে। এটি আসলে সেই ক্রম যাতে এলিমেন্টগুলি স্ট্যাকিং কনটেক্সটে স্ট্যাক করা হয়। এই ক্রম পেইন্টিংকে প্রভাবিত করে কারণ স্ট্যাকগুলি পিছন থেকে সামনের দিকে পেইন্ট করা হয়। ব্লক রেন্ডারারের স্ট্যাকিং অর্ডার হল:

  1. ব্যাকগ্রাউন্ডের রঙ
  2. ব্যাকগ্রাউন্ডের ছবি
  3. বর্ডার
  4. বাচ্চাকে
  5. আউটলাইন

Firefox ডিসপ্লে তালিকা

Firefox রেন্ডার ট্রি পর্যালোচনা করে এবং আঁকা আয়তক্ষেত্রের জন্য একটি ডিসপ্লে তালিকা তৈরি করে। এতে আয়তক্ষেত্রের জন্য প্রাসঙ্গিক রেন্ডারার থাকে, যা সঠিক পেইন্টিং অর্ডারে (রেন্ডারারের ব্যাকগ্রাউন্ড, তারপর বর্ডার ইত্যাদি) থাকে।

এর ফলে, একাধিকবার ট্রাভার্স করার পরিবর্তে, রিপেন্ট করার জন্য ট্রিকে একবারই ট্রাভার্স করতে হয় - সব ব্যাকগ্রাউন্ড, তারপর সব ছবি, তারপর সব বর্ডার ইত্যাদি আঁকা।

Firefox, লুকানো থাকবে এমন এলিমেন্ট যোগ না করে প্রসেস অপ্টিমাইজ করে, যেমন অন্যান্য অস্বচ্ছ এলিমেন্টের নিচে সম্পূর্ণভাবে থাকা এলিমেন্ট।

WebKit আয়তক্ষেত্র স্টোরেজ

আবার আঁকার আগে, WebKit পুরনো আয়তক্ষেত্রকে বিটম্যাপ হিসেবে সেভ করে। তারপর এটি শুধুমাত্র নতুন এবং পুরানো আয়তক্ষেত্রের মধ্যে ডেল্টা আঁকে।

ডায়নামিক পরিবর্তন

কোনও পরিবর্তনের উত্তরে ব্রাউজার যতটা সম্ভব কম অ্যাকশন করার চেষ্টা করে। তাই কোনও এলিমেন্টের রঙ পরিবর্তন করলে শুধু সেই এলিমেন্টটিই আবার আঁকা হবে। এলিমেন্টের পজিশনে পরিবর্তন করলে এলিমেন্ট, তার চিলড্রেন এবং সম্ভবত সিবলিংয়ের লেআউট ও রিপেন্ট হবে। DOM নোড যোগ করলে নোডের লেআউট ও রিপেন্ট হবে। "html" এলিমেন্টের ফন্ট সাইজ বাড়ানোর মতো বড় পরিবর্তন করলে, ক্যাশে বাতিল হয়ে যাবে এবং পুরো ট্রি আবার লেআউট ও পেইন্ট করতে হবে।

রেন্ডারিং ইঞ্জিনের থ্রেড

রেন্ডারিং ইঞ্জিন হল সিঙ্গেল থ্রেডেড। নেটওয়ার্ক অপারেশন ছাড়া প্রায় সবকিছুই একটি থ্রেডে ঘটে। Firefox ও Safari-তে এটি ব্রাউজারের মূল থ্রেড। Chrome-এ এটি হল ট্যাব প্রসেসের মূল থ্রেড।

নেটওয়ার্ক অপারেশন একাধিক সমান্তরাল থ্রেডের মাধ্যমে করা যেতে পারে। সমান্তরাল কানেকশনের সংখ্যা সীমিত (সাধারণত ২ - ৬টি কানেকশন)।

ইভেন্ট লুপ

ব্রাউজারের প্রধান থ্রেড হল একটি ইভেন্ট লুপ। এটি একটি অসীম লুপ যা প্রসেসটি চালু রাখে। এটি ইভেন্টের (যেমন লেআউট এবং পেইন্ট ইভেন্ট) জন্য অপেক্ষা করে এবং সেগুলি প্রসেস করে। এটি হল প্রধান ইভেন্ট লুপের জন্য Firefox কোড:

while (!mExiting)
    NS_ProcessNextEvent(thread);

CSS2 ভিজ্যুয়াল মডেল

ক্যানভাস

CSS2 স্পেসিফিকেশন অনুযায়ী, ক্যানভাস বলতে "যে স্পেসে ফর্ম্যাটিং স্ট্রাকচার রেন্ডার করা হয়" তাকে বোঝায়: যেখানে ব্রাউজার কন্টেন্ট দেখায়।

স্পেসের প্রতিটি ডাইমেনশনের জন্য ক্যানভাস অসীম, তবে ব্রাউজার ভিউপোর্টের ডাইমেনশনের উপর ভিত্তি করে একটি প্রাথমিক প্রস্থ বেছে নেয়।

www.w3.org/TR/CSS2/zindex.html অনুযায়ী, ক্যানভাস অন্য কোনও এলিমেন্টের মধ্যে থাকলে সেটি স্বচ্ছ হয় এবং না থাকলে ব্রাউজার দ্বারা নির্ধারিত রঙে দেখানো হয়।

CSS বক্স মডেল

CSS বক্স মডেল আয়তাকার বক্সের বিবরণ দেয় যা ডকুমেন্ট ট্রিতে এলিমেন্টের জন্য তৈরি করা হয় এবং ভিজ্যুয়াল ফর্ম্যাটিং মডেল অনুযায়ী সাজানো হয়।

প্রতিটি বক্সে একটি কন্টেন্ট এরিয়া (যেমন, টেক্সট, ছবি ইত্যাদি) এবং চারপাশে ঐচ্ছিক প্যাডিং, বর্ডার ও মার্জিন এরিয়া থাকে।

CSS2 বক্স মডেল
ছবি ১৯: CSS2 বক্স মডেল

প্রতিটি নোড ০…n সংখ্যক বক্স তৈরি করে।

সব এলিমেন্টের "ডিসপ্লে" প্রপার্টি থাকে যা বক্সের ধরন নির্ধারণ করে।

উদাহরণ:

block: generates a block box.
inline: generates one or more inline boxes.
none: no box is generated.

ডিফল্ট হল ইনলাইন কিন্তু ব্রাউজার স্টাইল শিট অন্যান্য ডিফল্ট সেট করতে পারে। যেমন: "div" এলিমেন্টের জন্য ডিফল্ট ডিসপ্লে হল ব্লক।

আপনি এখানে ডিফল্ট স্টাইল শিটের উদাহরণ দেখতে পাবেন: www.w3.org/TR/CSS2/sample.html.

পজিশনিং স্কিম

তিনটি স্কিম আছে:

  1. স্বাভাবিক: ডকুমেন্টে অবজেক্টের জায়গা অনুযায়ী সেটির পজিশন ঠিক করা হয়। এর অর্থ হল, রেন্ডার ট্রিতে এর স্থান DOM ট্রিতে এর স্থানের মতো এবং এর বক্সের ধরন ও ডাইমেনশন অনুযায়ী সাজানো হয়েছে
  2. ফ্লোট: অবজেক্টটি প্রথমে সাধারণ ফ্লোর মতো সাজানো হয়, তারপরে যতটা সম্ভব বাম বা ডানদিকে সরানো হয়
  3. অ্যাবসোলিউট: অবজেক্টটি DOM ট্রির পরিবর্তে রেন্ডার ট্রির অন্য কোনও জায়গায় রাখা হয়

পজিশনিং স্কিম "পজিশন" প্রপার্টি ও "ফ্লোট" অ্যাট্রিবিউট দ্বারা সেট করা হয়।

  • স্ট্যাটিক এবং রিলেটিভ একটি সাধারণ ফ্লো তৈরি করে
  • অ্যাবসলিউট ও ফিক্সড পজিশনিংয়ের কারণে অ্যাবসলিউট পজিশনিং হয়

স্ট্যাটিক পজিশনিংয়ে কোনও পজিশন নির্দিষ্ট করা থাকে না এবং ডিফল্ট পজিশনিং ব্যবহার করা হয়। অন্যান্য স্কিমে, লেখক পজিশন উল্লেখ করেন: উপরে, নিচে, বাঁদিকে, ডানদিকে।

বক্সটি যেভাবে সাজানো হয়েছে তা নির্ধারণ করা হয়:

  • বক্সের ধরন
  • বক্সের ডাইমেনশন
  • পজিশনিং স্কিম
  • ছবির সাইজ ও স্ক্রিনের সাইজের মতো এক্সটার্নাল তথ্য

বক্সের ধরন

ব্লক বক্স: একটি ব্লক তৈরি করে - ব্রাউজার উইন্ডোতে এর নিজস্ব আয়তক্ষেত্র রয়েছে।

ব্লক বক্স।
ছবি ২০: ব্লক বক্স

ইনলাইন বক্স: এর নিজস্ব ব্লক নেই, তবে এটি একটি কন্টেনিং ব্লকের মধ্যে রয়েছে।

ইনলাইন বক্স।
ছবি ২১: ইনলাইন বক্স

ব্লকগুলি উল্লম্বভাবে একের পর এক ফর্ম্যাট করা হয়। ইনলাইন অনুভূমিকভাবে ফর্ম্যাট করা হয়।

ব্লক ও ইনলাইন ফর্ম্যাটিং।
ছবি ২২: ব্লক ও ইনলাইন ফর্ম্যাটিং

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

লাইন।
ছবি ২৩: লাইন

পজিশনিং

আত্মীয়

আপেক্ষিক পজিশনিং - স্বাভাবিকের মতো পজিশন করা এবং তারপরে প্রয়োজনীয় ডেল্টা দ্বারা সরানো।

আপেক্ষিক পজিশনিং।
ছবি ২৪: আপেক্ষিক পজিশনিং

ফ্লোট

একটি ফ্লোট বক্স লাইনের বাঁদিকে বা ডানদিকে সরানো হয়েছে। আকর্ষণীয় ফিচারটি হল, অন্যান্য বক্স এটির চারপাশে ফ্লো করে। HTML:

<p>
  <img style="float: right" src="images/image.gif" width="100" height="100">
  Lorem ipsum dolor sit amet, consectetuer...
</p>

এরকম দেখতে লাগবে:

ফ্লোট।
ছবি ২৫: ফ্লোট

চূড়ান্ত ও নির্দিষ্ট

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

ফিক্সড পজিশনিং।
ছবি ২৬: ফিক্সড পজিশনিং

লেয়ার করা উপস্থাপনা

এটি z-ইনডেক্স CSS প্রপার্টি দ্বারা নির্দিষ্ট করা হয়। এটি বক্সের তৃতীয় ডাইমেনশন দেখায়: "z অক্ষ" বরাবর এর পজিশন।

বক্সগুলি স্ট্যাকে (স্ট্যাকিং কনটেক্সট বলা হয়) ভাগ করা থাকে। প্রতিটি স্ট্যাকে, পিছনের এলিমেন্টগুলি প্রথমে আঁকা হবে এবং সামনের এলিমেন্টগুলি উপরে, ব্যবহারকারীর কাছাকাছি থাকবে। ওভারল্যাপের ক্ষেত্রে, সামনের এলিমেন্টটি আগের এলিমেন্টটিকে আড়াল করবে।

z-ইনডেক্স প্রপার্টি অনুযায়ী স্ট্যাকগুলি সাজানো হয়। "z-index" প্রপার্টি সহ বক্সগুলি একটি লোকাল স্ট্যাক তৈরি করে। ভিউ পোর্টে আউটার স্ট্যাক আছে।

উদাহরণ:

<style type="text/css">
  div {
    position: absolute;
    left: 2in;
    top: 2in;
  }
</style>

<p>
  <div
    style="z-index: 3;background-color:red; width: 1in; height: 1in; ">
  </div>
  <div
    style="z-index: 1;background-color:green;width: 2in; height: 2in;">
  </div>
</p>

ফলাফল হবে এই:

ফিক্সড পজিশনিং।
ছবি ২৭: নির্দিষ্ট পজিশনিং

যদিও মার্কআপে লাল div সবুজটির আগে আসে এবং রেগুলার ফ্লোতে আগে আঁকা হত, z-ইনডেক্স প্রপার্টি বেশি, তাই এটি রুট বক্সের স্ট্যাকে আরও এগিয়ে রয়েছে।

রিসোর্স

  1. ব্রাউজার আর্কিটেকচার

    1. গ্রসকুর্থ, অ্যালান। ওয়েব ব্রাউজারের জন্য রেফারেন্স আর্কিটেকচার (pdf)
    2. Gupta, Vineet. How Browsers Work - Part 1 - Architecture
  2. পার্সিং

    1. Aho, Sethi, Ullman, Compilers: Principles, Techniques, and Tools (aka the "Dragon book"), Addison-Wesley, 1986
    2. রিক জেল্লিফ। The Bold and the Beautiful: HTML 5-এর জন্য দুটি নতুন ড্রাফ্ট।
  3. Firefox

    1. L. ডেভিড ব্যারন, Faster HTML and CSS: Layout Engine Internals for Web Developers.
    2. L. ডেভিড ব্যারন, Faster HTML and CSS: Layout Engine Internals for Web Developers (Google tech talk video)
    3. L. ডেভিড ব্যারন, Mozilla-র লেআউট ইঞ্জিন
    4. L. ডেভিড ব্যারন, Mozilla স্টাইল সিস্টেম ডকুমেন্টেশন
    5. ক্রিস ওয়াটারসন, HTML রিফ্লো সংক্রান্ত নোট
    6. ক্রিস ওয়াটারসন, Gecko ওভারভিউ
    7. আলেকজান্ডার লারসন, HTML HTTP অনুরোধের জীবন
  4. WebKit

    1. ডেভিড হায়াট, CSS প্রয়োগ করা(পার্ট ১)
    2. ডেভিড হায়াট, WebCore-এর ওভারভিউ
    3. WebCore Rendering, ডেভিড হায়াট
    4. ডেভিড হায়াট, The FOUC Problem
  5. W3C স্পেসিফিকেশন

    1. HTML 4.01 স্পেসিফিকেশন
    2. W3C HTML5 স্পেসিফিকেশন
    3. ক্যাসকেডিং স্টাইল শিট লেভেল ২ রিভিশন ১ (CSS 2.1) স্পেসিফিকেশন
  6. ব্রাউজার বিল্ড সংক্রান্ত নির্দেশাবলী

    1. Firefox. https://developer.mozilla.org/Build_Documentation
    2. WebKit. http://webkit.org/building/build.html

অনুবাদ

এই পৃষ্ঠাটি জাপানি ভাষায় দুবার অনুবাদ করা হয়েছে:

আপনি কোরিয়ান এবং তুর্কি ভাষার এক্সটার্নাল হোস্ট করা অনুবাদ দেখতে পারবেন।

সবাইকে ধন্যবাদ!