لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 03/20/24 في كل الموقع
-
سنطّلع في هذا المقال على مشاكل التوافق مع المتصفحات Cross-browser الشائعة التي ستواجهها في شيفرة HTML و CSS، بالإضافة إلى الأدوات التي يمكن استخدامها لمنع حدوثها أو إصلاحها، إذ يتضمن ذلك كشف الأخطاء المحتملة في الشيفرة البرمجية والتعامل مع بادئات CSS واستخدام أدوات تطوير المتصفح لتعقّب المشاكل واستخدام تعويض نقص دعم المتصفحات Polyfill لإضافة الدعم إليها، ومعالجة مشاكل التصميم المتجاوب مع الشاشات وغير ذلك. المتطلبات الأساسية: يجب أن تتعلم أساسيات لغات HTML و CSS وجافاسكربت JavaScript، وأن تكون لديك فكرة عن المبادئ عالية المستوى لاختبار التوافق مع المتصفحات. الهدف: أن تكون قادرًا على تشخيص مشاكل التوافق مع المتصفحات المختلفة الشائعة في شيفرة HTML و CSS واستخدام الأدوات والتقنيات المناسبة لإصلاحها. مشاكل لغتي HTML و CSS تكمن مشاكل لغتَي HTML و CSS في حقيقة أنهما لغتان بسيطتان إلى حد ما، ولا يأخذها المطورون على محمل الجد في أغلب الأحيان من حيث التأكد من أن الشيفرة مُعَدّة جيدًا وفعالة وتصف الغرض من الميزات الموجودة في الصفحة. تُستخدَم لغة جافاسكربت في أسوأ الحالات لإنشاء محتوى صفحة الويب وتنسيقها بالكامل، مما يجعل صفحاتك غير شاملة وذات أداء ضعيف، ويُعَد إنشاء عناصر DOM مكلفًا، كما لا تُدعَم الميزات الجديدة في حالات أخرى باستمرار على متصفحات متعددة، مما يجعل بعض الميزات والتنسيقات لا تعمل عند بعض المستخدِمين. تُعَدّ مشاكل التصميم المتجاوب مع الشاشات شائعًا أيضًا، إذ يمكن أن يوفر الموقع الذي يبدو جيدًا في متصفح على حاسوب تجربةً سيئةً على هاتف محمول، لأن المحتوى صغير جدًا بحيث لا يمكن قراءته أو بسبب كون الموقع بطيئًا بسبب الحركات الثقيلة. لننتقل الآن إلى كيفية تقليل الأخطاء على المتصفحات التي تنتج عن شيفرة HTML أو CSS. إصلاح المشاكل العامة يُعَدّ اختبار بعض المتصفحات الحديثة على الحاسوب وعلى الهاتف المحمول استراتيجيةً جيدةً للتأكد من عمل شيفرتك بنجاح قبل التركيز على مشاكل التوافق مع المتصفحات. قدّمنا في مقالَي تنقيح أخطاء شيفرة HTML وتنقيح أخطاء شيفرة CSS بعض الإرشادات الأساسية حول تنقيح أخطاء شيفرة HTML و CSS، فإذا لم تكن على دراية بالأساسيات، فيجب عليك بالتأكيد مراجعة هذين المقالين قبل المتابعة، إذ يتعلق الأمر بالتحقق مما إذا كانت شيفرة HTML و CSS منسقةً جيدًا ولا تحتوي على أيّ أخطاء صياغية. ملاحظة: تظهر إحدى المشاكل الشائعة في لغتَي CSS و HTML عندما تبدأ قواعد CSS المختلفة في التعارض مع بعضها البعض، ويمكن أن يشكّل ذلك مشكلةً خاصةً عند استخدام شيفرة خارجية مثل استخدام إطار عمل خاص بلغة CSS ثم تجد أن أحد أسماء الأصناف Class التي يستخدِمها هذا الإطار يتعارض مع اسم استخدَمته مسبقًا لغرض مختلف، أو يمكن أن تجد أن شيفرة HTML التي تنشئها واجهة برمجة تطبيقات جهة خارجية -مثل إنشاء إعلانات- تتضمن اسم صنف أو معرّف ID استخدمته مسبقًا لغرض مختلف، ويمكنك ضمان عدم حدوث ذلك من خلال البحث في الأدوات التي تستخدِمها أولًا وتصميم شيفرتك على أساسها، ويمكنك استخدام فضاء أسماء Namespace في CSS إذا كان لديك عنصر واجهة مستخدم Widget مثلًا، ولكن تأكد من أنه يحتوي على صنف مميز، ثم استخدم المحدّدات Selectors التي تحدد العناصر ضمن عنصر واجهة المستخدم باستخدام هذا الصنف، وبالتالي تقل احتمالية التعارضات مثل .audio-player ul a. التحقق من صحة شيفرة HTML و CSS يتضمن التحققُ من صحة شيفرة HTML التأكدَ من أن جميع الوسوم Tags مغلقة ومتداخلة بطريقة صحيحة، وأنك تستخدِم DOCTYPE والوسوم لغرضها الصحيح، كما يجب التحقق من صحة الشيفرة البرمجية بانتظام، وإحدى الخدمات التي يمكنها التحقق من صحة الشيفرة البرمجية هي خدمة Markup Validation Service من W3C التي تسمح لك بالإشارة إلى شيفرتك البرمجية ثم تعيد قائمةً بالأخطاء: كما تحتاج إلى شيفرة CSS للتحقق من أنّ أسماء الخاصيات مكتوبة بطريقة صحيحة وأنّ قيم الخاصيات صحيحة وصالحة مع الخاصيات المستخدَمة فيها، وللتحقق من عدم فقدان أي أقواس معقوصة وما إلى ذلك، كما تحتوي W3C على أداة التحقق CSS Validator أيضًا. منقحات الصياغة Linters لا يشير تطبيق منقّح الصياغة Linter إلى الأخطاء فقط، وإنما يمكنه إعطاء تحذيرات حول الممارسات السيئة في شيفرة CSS، ويمكن تخصيص منقّحات الصياغة لتكون أكثر أو أقل صرامةً في تقارير الأخطاء أو التحذيرات الناتجة. هناك العديد من تطبيقات منقحات الصياغة على الإنترنت وأفضلها تطبيق Dirty Markup لشيفرات HTML و CSS وجافاسكربت وتطبيق CSS Lint لشيفرة CSS فقط، إذ تسمح لك هذه التطبيقات بلصق شيفرتك في نافذة ما ثم ستضع علامة x على الأخطاء، ويمكن بعد ذلك تحريك مؤشر الفأرة فوقها للحصول على رسالة خطأ تخبرك ما هي المشكلة، ويسمح لك تطبيق Dirty Markup بإجراء إصلاحات على شيفرة HTML باستخدام زر التنظيف "Clean". ولكن لا يُعَدّ ذلك ملائمًا، إذ ستضطر إلى نسخ شيفرتك ولصقها في صفحة ويب للتحقق من صحتها عدة مرات، إذ تريد منقّح صياغة يتناسب مع سير عملك بأقل قدر من المتاعب، كما تحتوي العديد من محرّرات الشيفرات البرمجية على إضافات تنقيح الصياغة، إذ يحتوي المحرّر Atom من GitHub مثلًا على نظام بيئي غني بالإضافات مع العديد من خيارات تنقيح الأخطاء، وإليك مثال عن كيفية عمل هذه الإضافات Plugins: ثبّت المحرّر Atom إذا لم يكن لديك إصدار حديث مثبَّت مسبقًا. انتقل إلى مربع حوار تفضيلات Atom من خلال اختيار قائمة Atom ثم التفضيلات Preferences على نظام Mac أو من قائمة ملف File ثم Preferences في نظامَي Windows و Linux، ثم اختر خيار التثبيت Install في القائمة اليسرى. اكتب الكلمة "lint" في حقل البحث عن الحزم Search Packages واضغط على الزر Enter أو Return للبحث عن الحِزم المتعلقة بتنقيح الصياغة. يجب أن ترى حزمة تسمى "lint" في أعلى القائمة، لذا ثبّتها باستخدام زر التثبيت Install، إذ تعتمد منقّحات الصياغة الأخرى عليها في العمل، ثم ثبّت الإضافة linter-csslint لتنقيح صياغة شيفرة CSS والإضافة linter-tidy لتنقيح صياغة شيفرة HTML. حاول تحميل ملف HTML وملف CSS بعد انتهاء تثبيت الحزم، حيث سترى المشاكل مميزةً باللون الأخضر للتحذيرات وسترى دوائر حمراء للأخطاء بجوار أرقام الأسطر، ولوحةً منفصلةً في الأسفل توفِّر أرقام الأسطر ورسائل الخطأ وقيمًا مقترحة أو إصلاحات أخرى في بعض الأحيان. يتوفر لدى المحررات المشهورة الأخرى حزم تنقيح صياغة مماثلة مثل: SublimeLinter للمحرّر Sublime Text. Notepad++ Linter. VSCode linters. أدوات المطور في المتصفحات تتميز أدوات المطور المُضمَّنة في معظم المتصفحات بأدوات مفيدة لتعقب الأخطاء خاصة في شيفرة CSS. ملاحظة: لا تظهر أخطاء شيفرة HTML بسهولة في أدوات المطور، إذ سيحاول المتصفح تصحيح الوسوم ذات التنسيق السيئ تلقائيًا، حيث تُعَدّ أداة التحقق W3C Validator أفضل طريقة للعثور على أخطاء HTML. يعرض فاحص CSS في المتصفح Firefox مثلًا تصريحات CSS غير المُطبَّقة مشطوبة مع مثلث تحذير بجانبها، وسيوفر تحريك الفأرة فوق مثلث التحذير رسالةً تشرح الخطأ كما يلي: تمتلك أدوات التطوير في المتصفحات الأخرى ميزات مماثلة أيضًا. المشاكل الشائعة للتوافق مع المتصفحات لننتقل الآن إلى إلقاء نظرة على بعض مشاكل HTML و CSS الأكثر شيوعًا للتوافق مع المتصفحات، فالمجالات الرئيسية التي سنركز عليها هي نقص دعم الميزات الحديثة ومشاكل التخطيط. لا تدعم المتصفحات القديمة الميزات الحديثة تُعَدّ هذه المشكلة شائعةً خاصةً عندما تحتاج إلى دعم المتصفحات القديمة مثل إصدارات IE القديمة، أو إذا أردت استخدام ميزات تُطبَّق باستخدام بادئات CSS، إذ تعمل معظم وظائف HTML و CSS الأساسية مثل عناصر HTML وتنسيق CSS الأساسي للألوان والنصوص على معظم المتصفحات التي تريد دعمها، ولكن يظهر مزيد من المشاكل عندما تبدأ في استخدام ميزات أحدث من HTML و CSS. يُفضَّل البحث عن المتصفحات المدعومة والتقنيات ذات الصلة المفيدة بعد تحديد قائمة بالتقنيات غير المدعومة بصورة عامة التي ستستخدمها. سلوك HTML الاحتياطي يمكن حل بعض المشاكل بمجرد الاستفادة من الطريقة التي تعمل بها لغة HTML و CSS. تُعامَل عناصر HTML التي لا يتعرّف عليها المتصفح بوصفها عناصر مضمنةً مجهولة الاسم، أي هي عناصر مضمنة فعالة بدون قيمة دلالية مثل عناصر <span>، ولا يزال بإمكانك الإشارة إليها باستخدام أسماءها وتنسيقها باستخدام لغة CSS، فما عليك سوى التأكد من أنها تتصرف كما تريدها أن تتصرف مثل إعداد الخاصية display إلى شيء آخر غير inline إن كان هنالك حاجة. تحتوي عناصر HTML الأكثر تعقيدًا مثل <video> و <audio> و <canvas> على آليات احتياطية لإضافتها، والتي تعمل باستخدام المبدأ السابق نفسه، إذ يمكنك إضافة محتوًى احتياطيًا بين وسمَي الفتح والإغلاق، وستتجاهل المتصفحات غير الداعمة العنصر الخارجي بفعالية وتشغّل المحتوى المتداخل. إليك المثال التالي: <video id="video" controls preload="metadata" poster="img/poster.jpg"> <source src="video/tears-of-steel-battle-clip-medium.mp4" type="video/mp4"> <source src="video/tears-of-steel-battle-clip-medium.webm" type="video/webm"> <!-- Offer download --> <p>Your browser does not support HTML5 video; here is a link to <a href="video/tears-of-steel-battle-clip-medium.mp4">view the video</a> directly.</p> </video> يتضمن هذا المثال رابطًا بسيطًا يسمح لك بتنزيل الفيديو إذا لم يعمل مشغل فيديو HTML، لذا لا يزال على الأقل بإمكان المستخدِم الوصول إلى الفيديو. تعرض عناصر نموذج HTML صفات احتياطية، إذ أدخلت لغة HTML5 أنواعًا خاصة من عناصر <input> لإدخال معلومات محددة في النماذج مثل الأوقات والتواريخ والألوان والأعداد وما إلى ذلك أو يستعمل النوع النصي type="text" إن لم يدعم المتصفح نوعًا حديثًا يقدم ميزة جديدة، وهي مفيدة جدًا لا سيما على منصات الهاتف المحمول، إذ توفر طريقةً لإدخال البيانات التي تُعَدّ مهمةً جدًا لتجربة المستخدِم، كما توفر المنصات الداعمة أدوات واجهة مستخدِم خاصةً عند استخدام هذه الأنواع من حقول الإدخال مثل أداة التقويم لإدخال التواريخ. يوضِّح المثال التالي حقول إدخال التاريخ والوقت: <form> <div> <label for="date">Enter a date:</label> <input id="date" type="date"> </div> <div> <label for="time">Enter a time:</label> <input id="time" type="time"> </div> </form> يكون خرج الشيفرة السابقة كما يلي: ملاحظة: يمكنك مشاهدة هذا الخرج قيد التشغيل مباشرةً على forms-test.html، كما يمكنك الاطلاع على شيفرة هذا المثال على GitHub. إذا عرضت هذا المثال على متصفح داعم مثل المتصفح Chrome للحاسوب ولنظام Android أو iOS Safari، فسترى عناصر واجهة المستخدِم أو الميزات الخاصة قيد التشغيل أثناء إدخال البيانات. بينما ستعود المدخلات إلى مدخلات نص عادية على منصة غير داعمة مثل Internet Explorer، لذا لا يزال بإمكان المستخدِم إدخال بعض المعلومات على الأقل. سلوك CSS الاحتياطي يمكن القول أنّ لغة CSS أفضل من لغة HTML في الإجراءات الاحتياطية، فإذا صادف المتصفح تصريحًا أو قاعدةً لا يفهمها، فسيتخطاها دون تطبيقها أو ارتكاب خطأ ما، ويمكن أن يكون ذلك محبطًا لك وللمستخدِمين إذا انتقل هذا الخطأ إلى شيفرة الإنتاج، ولكن هذا يعني على الأقل عدم انهيار الموقع بأكمله بسبب خطأ واحد. لنلقِ نظرةً على المثال التالي الذي يحوي مربعًا بسيطًا مُنسَّقًا باستخدام CSS المختلفة: ملاحظة: يمكنك مشاهدة هذا المثال قيد التشغيل مباشرةً على button-with-fallback.html. يحتوي الزر على عدد من التصريحات الخاصة بتنسيقه، ولكن أكثر ما نهتم به هو ما يلي: button { ... background-color: #ff0000; background-color: rgba(255,0,0,1); box-shadow: inset 1px 1px 3px rgba(255,255,255,0.4), inset -1px -1px 3px rgba(0,0,0,0.4); } button:hover { background-color: rgba(255,0,0,0.5); } button:active { box-shadow: inset 1px 1px 3px rgba(0,0,0,0.4), inset -1px -1px 3px rgba(255,255,255,0.4); } استخدمنا هنا الخاصية background-color من النمط RGBA التي تغير العتامة Opacity عند التمرير على الزر لمنح المستخدم تلميحًا إلى أنّ الزر تفاعلي، وبعض الظل شبه الشفاف الداخلي box-shadow لإعطاء الزر ملمسًا وعمقًا. تكمن المشكلة في أن ألوان RGBA وخاصية الظلال box-shadow لا تعمل في إصدارات IE الأقدم من الإصدار 9، إذ لن تظهر الخلفية على الإطلاق في الإصدارات القديمة، لذا سيكون النص غير قابل للقراءة وسيئًا جدًا. يمكن حل هذه المشكلة من خلال إضافة تصريح ثانٍ للخاصية background-color الذي يحدد فقط اللون السداسي عشر المدعوم في المتصفحات القديمة، ويعمل بوصفه بديلًا احتياطيًا عن الميزات الحديثة إذا لم تعمل بنجاح، فما يحدث هو أن المتصفح الذي يزور هذه الصفحة يطبّق أولًا القيمة الأولى للخاصية background-color، ثم يبدّل القيمة الأولية بقيمة التصريح الثاني عندما يصل إليه إذا دعم هذا المتصفح ألوان RGBA، فإذا لم يكن الأمر كذلك، فسيتجاهل التصريح بالكامل وسيمضي قدمًا. ملاحظة: ينطبق الأمر نفسه على ميزات CSS الأخرى مثل استعلامات الوسائط Media Queries وكتل @font-face و @supports، فإذا لم تكن مدعومةً، فسيتجاهلها المتصفح فقط. دعم المحددات Selector لن تُطبَّق ميزات CSS على الإطلاق إذا لم تستخدِم محددات CSS الصحيحة لتحديد العنصر الذي تريد تنسيقه، فإذا كتبتَ محددًا في قائمة محددات مفصولة بفاصلة بصورة غير صحيحة، فقد لا يُحدد أو يطابق أي عنصر، وإذا كان المُحدد غير صالح، فسيجري تجاهل كل القائمة مع كتلة التنسيقات طبعًا، لذلك أضف لاحقة الصنف الزائف :-moz- فقط في قائمة محددات متسامحة forgiving selector list مثل :where(::-moz-thumb) واحذر أن تضيفها أو تستعملها في قائمة محددات ليست ضمن :is() أو :where() التي تتسامح مع محددات غير صالحة أو صحيحة لأن كل المتصفحات سوى متصفح Firefox سيراها غير صالحة وبالتالي يتجاهل كل القائمة، ولاحظ أن كلا من :is() أو :where() يمكن تمريرهما ضمن قائمة محددات أخرى من ضمنها :has() و :not(). وقد وجدنا أن فحص العنصر الذي تحاول تنسيقه باستخدام أدوات التطوير في المتصفح أمر مفيد، ثم يجب النظر إلى مسار تنقل شجرة DOM الذي تميل أدوات فحص DOM إلى توفيره لمعرفة ما إذا كان المحدِّد منطقيًا بالمقارنة به. يمكنك الحصول على هذا النوع من الخرج أسفلَ أداة فحص DOM مثلًا في أدوات تطوير فايرفوكس Firefox: إذا أردت استخدام المحدد التالي مثلًا، فستتمكن من رؤية أنه لن يحدد العنصر input كما تريد: form > #date لا يُعَدّ عنصر الإدخال date في النموذج ابنًا مباشرًا للعنصر <form>، لذا يُفضَّل استخدام محدد حفيد Descendant Selector عام بدلًا من محدد ابن Child Selector. التعامل مع بادئات CSS تأتي مجموعة أخرى من المشاكل من استخدام البادئات Prefixes الخاصة بلغة CSS، وهي آلية مستخدمة للسماح لبائعي المتصفحات بتطبيق إصدارهم من ميزة CSS أو جافاسكربت أثناء وجود التقنيات في حالة تجريبية ليتمكنوا من تعديلها لتكون صحيحة دون التعارض مع تطبيقات المتصفح الأخرى أو عمليات التطبيق النهائية التي تكون بدون بادئات مثل ما يلي: يستخدِم Mozilla البادئة -moz-. تستخدِم المتصفحات Chrome و Opera و Safari و Edge البادئة -webkit-. يستخدِم Microsoft البادئة -ms-. تستخدِم الإصدارات الأصلية من المتصفح Opera البادئة o-. لا يُفترَض أبدًا استخدام الميزات ذات البادئات في مواقع الإنتاج، فهي عرضة للتغيير أو الإزالة دون سابق إنذار، وتتسبب في حدوث مشاكل على المتصفحات المختلفة عندما يقرر المطورون استخدام الإصدار -webkit- فقط من خاصية ما، مما يعني أن الموقع لن يعمل في متصفحات أخرى، ويحدث ذلك كثيرًا لدرجة أنّ المتصفحات الأخرى بدأت في تنفيذ إصدارات مع البادئة -webkit- من خاصيات CSS المختلفة، لذلك ستعمل مع مثل هذه الشيفرة البرمجية، وقد انخفض استخدام البادئات لدى بائعي المتصفحات مؤخرًا بسبب هذه الأنواع من المشاكل، ولكن لا يزال هناك بعض البادئات التي يجب الاهتمام بها. إذا أصريت على استخدام الميزات ذات البادئات، فتأكد من استخدام الميزات الصحيحة (استعمل مثلًا موقع caniuse.com)، فإذا لم تكن متأكدًا من ذلك، فيمكنك التأكد من خلال إجراء بعض الاختبارات في المتصفحات مباشرةً. وحاول تضمين الإصدار الذي لا يحوي أي بادئات بعد الذي يحوي بادئات، حيث سيُتجاهل إن لم يكن مدعومًا ويُستخدَم إن كان مدعومًا مثل: .masked { -webkit-mask-image: url(MDN.svg); mask-image: url(MDN.svg); -webkit-mask-size: 50%; mask-size: 50%; } جرب المثال البسيط التالي: افتح موقع google.com أو أيّ موقع آخر يحتوي على عنوان بارز أو أيّ عنصر كتلي آخر Block-level Element. انقر بزر الفأرة الأيمن أو اضغط على مفتاح Cmd مع الضغط على العنصر، ثم اختر فحص Inspect أو فحص العنصر Inspect element أو أيًا كان الخيار الموجود في متصفحك، إذ يجب أن يؤدي ذلك إلى فتح أدوات التطوير في متصفحك مع تحديد العنصر في أداة فحص نموذج DOM. ابحث عن ميزة يمكنك استخدامها لتحديد هذا العنصر، فقد كان لشعار جوجل الرئيسي مثلًا المعرّف hplogo في وقت كتابة هذا المقال. خزّن مرجعًا لهذا العنصر في متغير كما يلي: const test = document.getElementById("hplogo"); حاول الآن ضبط قيمة جديدة لخاصية CSS التي تهتم بها في هذا العنصر، إذ يمكنك تطبيق ذلك باستخدام الخاصية style الخاصة بالعنصر، أي اكتب ما يلي في طرفية جافاسكربت مثلًا: test.style.transform = 'rotate(90deg)' يجب أن تكمِل طرفية جافاسكربت تلقائيًا أسماء الخاصيات الموجودة في المتصفح ومطابقة ما كتبته حتى الآن عندما تكتب تمثيل اسم الخاصية بعد النقطة الثانية (لاحظ كتابة أسماء خاصيات CSS في جافاسكربت بحالة أحرف سنام الجَمل وليس باستخدام الواصلة - )، ويُعَدّ ذلك مفيدًا لمعرفة إصدارات الخاصية المُطبَّقة في ذلك المتصفح. إن أردت تضمين ميزة حديثة، فاختبر دعمها باستعمال @support التي تساعدك على معرفة دعم الميزة من المتصفح أساسًا من عدمه حتى تعرف إن كنت بحاجة إلى بادئات أو حلول أخرى. مشاكل التصميم المتجاوب مع الشاشات Responsive Design التصميم المتجاوب مع الشاشات هو إنشاء تخطيطات الويب التي تتغير لتناسب عوامل أشكال الأجهزة المختلفة مثل عروض الشاشات المختلفة أو الاتجاهات (عموديًا أو أفقيًا) أو درجات الدقة، إذ سيبدو تخطيط الحاسوب مثلًا سيئًا عند عرضه على هاتف محمول، لذا يجب توفير تخطيط مناسب للهاتف المحمول باستخدام استعلامات الوسائط Media Queries والتأكد من تطبيقه بطريقة صحيحة باستخدام إطار العرض Viewport. تُعَدّ الدقة Resolution مشكلةً كبيرةً أيضًا، فليس مرجحًا أن تحتاج الأجهزة المحمولة إلى صور ثقيلة وكبيرة مثل الحواسيب، ويمكن أن يكون لديها اتصالات إنترنت أبطأ وخطط بيانات باهظة الثمن تجعل عرض النطاق الترددي الضائع مشكلةً أكبر، كما يمكن أن تحتوي الأجهزة المختلفة على مجالات من درجات الدقة المختلفة، مما يعني أنّ الصور الأصغر يمكن أن تكون غير واضحة، وهناك عدد من الأساليب التي تسمح لك بالتغلب على مثل هذه المشاكل بدءًا من استعلامات الوسائط البسيطة للهاتف المحمول أولًا وحتى تقنيات الصور المتجاوبة مع الشاشات الأكثر تعقيدًا. البحث عن المساعدة هناك العديد من المشاكل الأخرى التي ستواجهها مع شيفرة HTML و CSS، مما يجعل معرفة كيفية العثور على إجابات عبر الإنترنت لا تقدر بثمن. يمكنك طرح مشكلتك في قسم الأسئلة والأجوبة من أكاديمية حسوب للحصول على حل لمشكلتك التي تواجهها، إذ يُحتمَل أنّ المطورين الآخرين قد واجهوا المشاكل نفسها التي تواجهها أنت الآن، أو يمكنك مساعدتهم، كما يمكنك الانتقال إلى مجتمع تطوير الويب في حسوب IO، وهو مجتمع خاص بمناقشة وطرح المواضيع والقضايا العامة المتعلقة بتطوير الويب ولغاتها المختلفة. يمكنك البحث أيضًا في موسوعة حسوب والتعرف على أي ميزة أو قسم تحتاج إلى استخدامه، كما يمكنك الرجوع إلى الموقع الشهري CanIUse لمعرفة دعم الميزات في المتصفحات. الخلاصة يجب أن تكون الآن على دراية بالأنواع الرئيسية لمشاكل توافق HTML و CSS على المتصفحات التي ستواجهها في تطوير الويب وكيفية إصلاحها. ترجمة -وبتصرُّف- للمقال Handling common HTML and CSS problems. اقرأ أيضًا المقال السابق: استراتيجيات اختبارات مشاريع الويب للتوافق مع المتصفحات مدخل إلى اختبار مشاريع الويب للتوافق مع المتصفحات الأدوات المستخدمة في بناء مواقع ويب1 نقطة
-
السلام عليكم حاولت كثير تحويل كود بايثون kivy الى apk يظهر الخطأ التالي مراراً وتكراراً STDERR: # Command failed: ['/usr/bin/python3', '-m', 'pythonforandroid.toolchain', 'create', '--dist_name=myapp', '--bootstrap=sdl2', '--requirements=python3,kivy', '--arch=arm64-v8a', '--arch=armeabi-v7a', '--copy-libs', '--color=always', '--storage-dir=/content/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a', '--ndk-api=21', '--ignore-setup-py', '--debug'] # ENVIRONMENT: # SHELL = '/bin/bash' # NV_LIBCUBLAS_VERSION = '12.2.5.6-1' # NVIDIA_VISIBLE_DEVICES = 'all' # COLAB_JUPYTER_TRANSPORT = 'ipc' # NV_NVML_DEV_VERSION = '12.2.140-1' # NV_CUDNN_PACKAGE_NAME = 'libcudnn8' # CGROUP_MEMORY_EVENTS = '/sys/fs/cgroup/memory.events /var/colab/cgroup/jupyter-children/memory.events' # NV_LIBNCCL_DEV_PACKAGE = 'libnccl-dev=2.19.3-1+cuda12.2' # NV_LIBNCCL_DEV_PACKAGE_VERSION = '2.19.3-1' # VM_GCE_METADATA_HOST = '169.254.169.253' # HOSTNAME = '1ad5698ccfed' # LANGUAGE = 'en_US' # TBE_RUNTIME_ADDR = '172.28.0.1:8011' # COLAB_TPU_1VM = '' # GCE_METADATA_TIMEOUT = '3' # NVIDIA_REQUIRE_CUDA = ('cuda>=12.2 brand=tesla,driver>=470,driver<471 ' 'brand=unknown,driver>=470,driver<471 brand=nvidia,driver>=470,driver<471 ' 'brand=nvidiartx,driver>=470,driver<471 brand=geforce,driver>=470,driver<471 ' 'brand=geforcertx,driver>=470,driver<471 brand=quadro,driver>=470,driver<471 ' 'brand=quadrortx,driver>=470,driver<471 brand=titan,driver>=470,driver<471 ' 'brand=titanrtx,driver>=470,driver<471 brand=tesla,driver>=525,driver<526 ' 'brand=unknown,driver>=525,driver<526 brand=nvidia,driver>=525,driver<526 ' 'brand=nvidiartx,driver>=525,driver<526 brand=geforce,driver>=525,driver<526 ' 'brand=geforcertx,driver>=525,driver<526 brand=quadro,driver>=525,driver<526 ' 'brand=quadrortx,driver>=525,driver<526 brand=titan,driver>=525,driver<526 ' 'brand=titanrtx,driver>=525,driver<526') # NV_LIBCUBLAS_DEV_PACKAGE = 'libcublas-dev-12-2=12.2.5.6-1' # NV_NVTX_VERSION = '12.2.140-1' # COLAB_JUPYTER_IP = '172.28.0.12' # NV_CUDA_CUDART_DEV_VERSION = '12.2.140-1' # NV_LIBCUSPARSE_VERSION = '12.1.2.141-1' # COLAB_LANGUAGE_SERVER_PROXY_ROOT_URL = 'http://172.28.0.1:8013/' # NV_LIBNPP_VERSION = '12.2.1.4-1' # NCCL_VERSION = '2.19.3-1' # KMP_LISTEN_PORT = '6000' # TF_FORCE_GPU_ALLOW_GROWTH = 'true' # ENV = '/root/.bashrc' # PWD = '/content' # COLAB_LANGUAGE_SERVER_PROXY_REQUEST_TIMEOUT = '30s' # TBE_EPHEM_CREDS_ADDR = '172.28.0.1:8009' # TBE_CREDS_ADDR = '172.28.0.1:8008' # NV_CUDNN_PACKAGE = 'libcudnn8=8.9.6.50-1+cuda12.2' # NVIDIA_DRIVER_CAPABILITIES = 'compute,utility' # COLAB_JUPYTER_TOKEN = '' # LAST_FORCED_REBUILD = '20240305' # NV_NVPROF_DEV_PACKAGE = 'cuda-nvprof-12-2=12.2.142-1' # NV_LIBNPP_PACKAGE = 'libnpp-12-2=12.2.1.4-1' # NV_LIBNCCL_DEV_PACKAGE_NAME = 'libnccl-dev' # TCLLIBPATH = '/usr/share/tcltk/tcllib1.20' # NV_LIBCUBLAS_DEV_VERSION = '12.2.5.6-1' # COLAB_KERNEL_MANAGER_PROXY_HOST = '172.28.0.12' # NVIDIA_PRODUCT_NAME = 'CUDA' # NV_LIBCUBLAS_DEV_PACKAGE_NAME = 'libcublas-dev-12-2' # USE_AUTH_EPHEM = '1' # NV_CUDA_CUDART_VERSION = '12.2.140-1' # COLAB_WARMUP_DEFAULTS = '1' # HOME = '/root' # LANG = 'en_US.UTF-8' # COLUMNS = '100' # CUDA_VERSION = '12.2.2' # CLOUDSDK_CONFIG = '/content/.config' # NV_LIBCUBLAS_PACKAGE = 'libcublas-12-2=12.2.5.6-1' # NV_CUDA_NSIGHT_COMPUTE_DEV_PACKAGE = 'cuda-nsight-compute-12-2=12.2.2-1' # COLAB_RELEASE_TAG = 'release-colab_20240319-060144_RC00' # PYDEVD_USE_FRAME_EVAL = 'NO' # KMP_TARGET_PORT = '9000' # CLICOLOR = '1' # KMP_EXTRA_ARGS = ('--logtostderr --listen_host=172.28.0.12 --target_host=172.28.0.12 ' '--tunnel_background_save_url=https://colab.research.google.com/tun/m/cc48301118ce562b961b3c22d803539adc1e0c19/m-s-3bbuezqnnu0ut ' '--tunnel_background_save_delay=10s ' '--tunnel_periodic_background_save_frequency=30m0s ' '--enable_output_coalescing=true --output_coalescing_required=true') # NV_LIBNPP_DEV_PACKAGE = 'libnpp-dev-12-2=12.2.1.4-1' # COLAB_LANGUAGE_SERVER_PROXY_LSP_DIRS = '/datalab/web/pyright/typeshed-fallback/stdlib,/usr/local/lib/python3.10/dist-packages' # NV_LIBCUBLAS_PACKAGE_NAME = 'libcublas-12-2' # COLAB_KERNEL_MANAGER_PROXY_PORT = '6000' # CLOUDSDK_PYTHON = 'python3' # NV_LIBNPP_DEV_VERSION = '12.2.1.4-1' # ENABLE_DIRECTORYPREFETCHER = '1' # NO_GCE_CHECK = 'False' # JPY_PARENT_PID = '85' # PYTHONPATH = '/env/python' # TERM = 'xterm-color' # NV_LIBCUSPARSE_DEV_VERSION = '12.1.2.141-1' # GIT_PAGER = 'cat' # LIBRARY_PATH = '/usr/local/cuda/lib64/stubs' # NV_CUDNN_VERSION = '8.9.6.50' # SHLVL = '0' # PAGER = 'cat' # COLAB_LANGUAGE_SERVER_PROXY = '/usr/colab/bin/language_service' # NV_CUDA_LIB_VERSION = '12.2.2-1' # NVARCH = 'x86_64' # NV_CUDNN_PACKAGE_DEV = 'libcudnn8-dev=8.9.6.50-1+cuda12.2' # NV_CUDA_COMPAT_PACKAGE = 'cuda-compat-12-2' # MPLBACKEND = 'module://ipykernel.pylab.backend_inline' # NV_LIBNCCL_PACKAGE = 'libnccl2=2.19.3-1+cuda12.2' # LD_LIBRARY_PATH = '/usr/local/nvidia/lib:/usr/local/nvidia/lib64' # COLAB_GPU = '' # GCS_READ_CACHE_BLOCK_SIZE_MB = '16' # NV_CUDA_NSIGHT_COMPUTE_VERSION = '12.2.2-1' # NV_NVPROF_VERSION = '12.2.142-1' # LC_ALL = 'en_US.UTF-8' # COLAB_FILE_HANDLER_ADDR = 'localhost:3453' # PATH = '/root/.buildozer/android/platform/apache-ant-1.9.4/bin:/opt/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/tools/node/bin:/tools/google-cloud-sdk/bin' # NV_LIBNCCL_PACKAGE_NAME = 'libnccl2' # COLAB_DEBUG_ADAPTER_MUX_PATH = '/usr/local/bin/dap_multiplexer' # NV_LIBNCCL_PACKAGE_VERSION = '2.19.3-1' # PYTHONWARNINGS = 'ignore:::pip._internal.cli.base_command' # DEBIAN_FRONTEND = 'noninteractive' # COLAB_BACKEND_VERSION = 'next' # OLDPWD = '/' # _ = '/usr/local/bin/buildozer' # PACKAGES_PATH = '/root/.buildozer/android/packages' # ANDROIDSDK = '/root/.buildozer/android/platform/android-sdk' # ANDROIDNDK = '/root/.buildozer/android/platform/android-ndk-r25b' # ANDROIDAPI = '31' # ANDROIDMINAPI = '21' # # Buildozer failed to execute the last command # The error might be hidden in the log above this error # Please read the full log, and search for it before # raising an issue with buildozer itself. # In case of a bug report, please add a full log with log_level = 21 نقطة
-
لدي سؤال اريد حله عندما اضع خلفية لل body واشغل الصفحه علي الجوال لاتظهر الخلفية الكاملة فقط تظهر ربعها او نصفها كيف احل هذه المشكلة وشكرا ..1 نقطة
-
سلام عليكم. انا سبق لي واشتركت في دورة تطوير الواجهات. والآن ارغب في شراء دورتين: ادارة تطوير المنتجات - دورة الذكاء الإصطناعي. لكن السعر مبالغ فيه ولا اساطيع دفع هذا المبلغ. هل توجد عروض وخصومات ومتى تكون1 نقطة
-
إذا قمت بعملية Validate لهذا البريد الإلكتروني على سبيل المثال: 434user@gmail.com باستخدام هذا الـ Pattern: /(^[0-9].*)@(^[0-9]+.*)\.(\w{2,})/i يتم إرجاع قيمة true (أي أن هذا البريد الإلكتروني متوافق مع هذا الـ Pattern) بينما باستخدام هذا الـ Pattern: /(\D+.*)@(\D+.*)\.(\w{2,})/i يتم إرجاع قيمة false لماذا يحدث هذا ؟1 نقطة
-
فكر بالأمر على أنّ التعبير النمطي يبحث عن نمط معين بالسلسلة النصية، والنمط لديك موجود لذا يرجع True، لكن لماذا؟ لأن \D يشير إلى جميع الأحرف باستثناء الأرقام، لكنه يُستخدم مع المشغل +، مما يجعل الأمر مختلفًا. فتعبير \D+.* يبحث عن مجموعة واحدة أو أكثر من أي حرف باستثناء الأرقام، متبوعًا بأي عدد من الأحرف (.*). لذا، فهو يتطابق مع أي بريد إلكتروني يبدأ بأي حرف باستثناء رقم، ثم يتبعه أي عدد من الأحرف، ثم @، ثم أي حرف باستثناء رقم، ثم يتبعه أي عدد من الأحرف، ثم .، ثم أي حرفين على الأقل (لأن \w يطابق أي حرف أو رقم أو سطر سفلي). في email، يتطابق التعبير مع "43ffdfsdf" (الحرف الأول ليس رقمًا، ثم يتبعه أي عدد من الأحرف) و "gmail" (أي حرف باستثناء رقم، ثم يتبعه أي عدد من الأحرف) و "com" (حرفين على الأقل). بالتالي، فإن p.test(email) يُرجع true لأن التعبير \D+.* يطابق البريد الإلكتروني "43ffdfsdf@gmail.com". من الأفضل استخدام regex101.com لإختبار النمط، أدخل التعبير \D+.* وقم بتجربته مع مختلف عناوين البريد الإلكتروني. وفي حال تريد التأكد من أن البريد الإلكتروني لا يبدأ برقم، فنستخدم التعبير التالي: let p = /^[^0-9].*@\S+\.\w{2,}$/i; وهو يتطابق مع أي بريد إلكتروني، يتصف بالتالي: لا يبدأ برقم (^[^0-9]) يحتوي على @ لا يحتوي على مسافات بيضاء (/\S+/) ينتهي بـ . وحرفين على الأقل (\w{2,}) لذا النمط التالي سيرجع نتيجة Flase: let p = /^[^0-9].*@\S+\.\w{2,}$/i; let email = "43ffdfsdf@gmail.com"; console.log(p.test(email)); // false1 نقطة
-
البداية بالتعلم النظري، بدراسة الأساسيات مثل: تعريف الخوارزميات وهياكل البيانات أنواع الخوارزميات وهياكل البيانات المختلفة تعقيد الوقت والذاكرة كيفية تحليل الخوارزميات ويجب فهم للنظرية قبل الانتقال إلى التطبيق. بعد ذلك تنتقل إلى التطبيق العملي من خلال كتابة الكود، ولكن ابدأ بمسائل بسيطة وقم بزيادة صعوبة المسائل تدريجيًا، مع استخدام لغة البرمجة التي تجد أريحية في استعمالها أيضًا تدعم هياكل البيانات التي تريد استخدامها وبالطبع ستجد أن بايثون هي الأسهل. وقبل كتابة الكود ركز على فهم كيفية عمل الخوارزمية، مع الإلتزام بالتدرج في المسائل. وبالنسبة لخوارزمية DFS، فهي خوارزمية لتجول مخطط أو البحث فيه، حيث تبدأ من عقدة جذر المخطط وتستكشف جميع العقد المتصلة بها قبل الانتقال إلى العقدة التالية في نفس المستوى. تتبع الخوارزمية نهجًا "العمق أولاً"، وتتعمق في كل فرع من فروع المخطط حتى تصل إلى نهاية مسدودة، ثم تعود إلى العقدة السابقة وتستكشف الفرع التالي. وطريقة عمل الخوارزمية، هي كالتالي: ابدأ من عقدة جذر المخطط. ضع العقدة الحالية في مكدس (Stack). علامة العقدة الحالية على أنها "تمت زيارتها". إذا كانت العقدة الحالية لها أي عقدة فرعية غير "تمت زيارتها": اختر أحد العقد الفرعية غير "تمت زيارتها". انتقل إلى الخطوة 2. 5- إذا لم يكن للعقدة الحالية أي عقدة فرعية غير "تمت زيارتها": أخرج العقدة الحالية من المكدس. إذا لم يكن المكدس فارغًا: انتقل إلى الخطوة 3. إذا كان المكدس فارغًا: تم الانتهاء من تجول المخطط. وكتطبيقات عملية، تستخدم الخوارزمية للعثور على مسار من نقطة البداية إلى نقطة النهاية في متاهة أو للتحقق من صحة التعبير الحسابي، ولتلوين مناطق المخطط دون استخدام ألوان متجاورة.1 نقطة
-
@Chihab Hedidi أخطأت في سؤالي, ما أقصده حقا وباختصار هو أن هذا الكود يقوم بارجاع true ولا أعلم لماذا, علما أن \D يفترض أن يشير إلى جميع الأحرف إلا الأرقام let p = /(\D+.*)@(\D+.*)\.(\w{2,})/i; let email = "43ffdfsdf@gmail.com"; console.log(p.test(email)); // true1 نقطة
-
1 نقطة
-
اقصد كيف يمكنني جلب كل معلومات الصفحة1 نقطة
-
الأمر بسيط، يعتمد تحديد ترتيب التنقل بين الحقول عند الضغط على Tab على الخاصية tabindex. وما تحتاجه هو إضافة الخاصية tabindex إلى كل عنصر قابل للتحديد بالترتيب الذي تريده. <input type="text" name="name" tabindex="1"> <input type="email" name="email" tabindex="2"> <input type="submit" value="Submit" tabindex="3"> ستجد شرح مفصل هنا:1 نقطة